// 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_chromeos.h"

#include <string>

#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/sys_info.h"
#include "base/thread_task_runner_handle.h"
#include "chromeos/dbus/bluetooth_adapter_client.h"
#include "chromeos/dbus/bluetooth_agent_manager_client.h"
#include "chromeos/dbus/bluetooth_agent_service_provider.h"
#include "chromeos/dbus/bluetooth_device_client.h"
#include "chromeos/dbus/bluetooth_input_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_device_chromeos.h"
#include "device/bluetooth/bluetooth_pairing_chromeos.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
#include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
#include "device/bluetooth/bluetooth_socket_chromeos.h"
#include "device/bluetooth/bluetooth_socket_thread.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using device::BluetoothAdapter;
using device::BluetoothDevice;
using device::BluetoothSocket;
using device::BluetoothUUID;

namespace {

// The agent path is relatively meaningless since BlueZ only permits one to
// exist per D-Bus connection, it just has to be unique within Chromium.
const char kAgentPath[] = "/org/chromium/bluetooth_agent";

void OnUnregisterAgentError(const std::string& error_name,
                            const std::string& error_message) {
  // It's okay if the agent didn't exist, it means we never saw an adapter.
  if (error_name == bluetooth_agent_manager::kErrorDoesNotExist)
    return;

  LOG(WARNING) << "Failed to unregister pairing agent: "
               << error_name << ": " << error_message;
}

}  // namespace

namespace device {

// static
base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
    const InitCallback& init_callback) {
  return chromeos::BluetoothAdapterChromeOS::CreateAdapter();
}

}

namespace chromeos {

// static
base::WeakPtr<BluetoothAdapter> BluetoothAdapterChromeOS::CreateAdapter() {
  BluetoothAdapterChromeOS* adapter = new BluetoothAdapterChromeOS();
  return adapter->weak_ptr_factory_.GetWeakPtr();
}

BluetoothAdapterChromeOS::BluetoothAdapterChromeOS()
    : num_discovery_sessions_(0),
      discovery_request_pending_(false),
      weak_ptr_factory_(this) {
  ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
  socket_thread_ = device::BluetoothSocketThread::Get();

  DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this);
  DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
  DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this);

  // Register the pairing agent.
  dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
  agent_.reset(BluetoothAgentServiceProvider::Create(
      system_bus, dbus::ObjectPath(kAgentPath), this));
  DCHECK(agent_.get());

  std::vector<dbus::ObjectPath> object_paths =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters();

  if (!object_paths.empty()) {
    VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available.";
    SetAdapter(object_paths[0]);
  }
}

BluetoothAdapterChromeOS::~BluetoothAdapterChromeOS() {
  DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this);
  DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
  DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this);

  VLOG(1) << "Unregistering pairing agent";
  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
      UnregisterAgent(
          dbus::ObjectPath(kAgentPath),
          base::Bind(&base::DoNothing),
          base::Bind(&OnUnregisterAgentError));
}

void BluetoothAdapterChromeOS::AddObserver(
    BluetoothAdapter::Observer* observer) {
  DCHECK(observer);
  observers_.AddObserver(observer);
}

void BluetoothAdapterChromeOS::RemoveObserver(
    BluetoothAdapter::Observer* observer) {
  DCHECK(observer);
  observers_.RemoveObserver(observer);
}

std::string BluetoothAdapterChromeOS::GetAddress() const {
  if (!IsPresent())
    return std::string();

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);
  DCHECK(properties);

  return BluetoothDevice::CanonicalizeAddress(properties->address.value());
}

std::string BluetoothAdapterChromeOS::GetName() const {
  if (!IsPresent())
    return std::string();

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);
  DCHECK(properties);

  return properties->alias.value();
}

void BluetoothAdapterChromeOS::SetName(const std::string& name,
                                       const base::Closure& callback,
                                       const ErrorCallback& error_callback) {
  if (!IsPresent())
    error_callback.Run();

  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      GetProperties(object_path_)->alias.Set(
          name,
          base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback,
                     error_callback));
}

bool BluetoothAdapterChromeOS::IsInitialized() const {
  return true;
}

bool BluetoothAdapterChromeOS::IsPresent() const {
  return !object_path_.value().empty();
}

bool BluetoothAdapterChromeOS::IsPowered() const {
  if (!IsPresent())
    return false;

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  return properties->powered.value();
}

void BluetoothAdapterChromeOS::SetPowered(
    bool powered,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!IsPresent())
    error_callback.Run();

  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      GetProperties(object_path_)->powered.Set(
          powered,
          base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback,
                     error_callback));
}

bool BluetoothAdapterChromeOS::IsDiscoverable() const {
  if (!IsPresent())
    return false;

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  return properties->discoverable.value();
}

void BluetoothAdapterChromeOS::SetDiscoverable(
    bool discoverable,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (!IsPresent())
    error_callback.Run();

  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      GetProperties(object_path_)->discoverable.Set(
          discoverable,
          base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback,
                     error_callback));
}

bool BluetoothAdapterChromeOS::IsDiscovering() const {
  if (!IsPresent())
    return false;

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  return properties->discovering.value();
}

void BluetoothAdapterChromeOS::CreateRfcommService(
    const BluetoothUUID& uuid,
    const ServiceOptions& options,
    const CreateServiceCallback& callback,
    const CreateServiceErrorCallback& error_callback) {
  VLOG(1) << object_path_.value() << ": Creating RFCOMM service: "
          << uuid.canonical_value();
  scoped_refptr<BluetoothSocketChromeOS> socket =
      BluetoothSocketChromeOS::CreateBluetoothSocket(
          ui_task_runner_, socket_thread_);
  socket->Listen(this,
                 BluetoothSocketChromeOS::kRfcomm,
                 uuid,
                 options,
                 base::Bind(callback, socket),
                 error_callback);
}

void BluetoothAdapterChromeOS::CreateL2capService(
    const BluetoothUUID& uuid,
    const ServiceOptions& options,
    const CreateServiceCallback& callback,
    const CreateServiceErrorCallback& error_callback) {
  VLOG(1) << object_path_.value() << ": Creating L2CAP service: "
          << uuid.canonical_value();
  scoped_refptr<BluetoothSocketChromeOS> socket =
      BluetoothSocketChromeOS::CreateBluetoothSocket(
          ui_task_runner_, socket_thread_);
  socket->Listen(this,
                 BluetoothSocketChromeOS::kL2cap,
                 uuid,
                 options,
                 base::Bind(callback, socket),
                 error_callback);
}

void BluetoothAdapterChromeOS::RemovePairingDelegateInternal(
    BluetoothDevice::PairingDelegate* pairing_delegate) {
  // Before removing a pairing delegate make sure that there aren't any devices
  // currently using it; if there are, clear the pairing context which will
  // make any responses no-ops.
  for (DevicesMap::iterator iter = devices_.begin();
       iter != devices_.end(); ++iter) {
    BluetoothDeviceChromeOS* device_chromeos =
        static_cast<BluetoothDeviceChromeOS*>(iter->second);

    BluetoothPairingChromeOS* pairing = device_chromeos->GetPairing();
    if (pairing && pairing->GetPairingDelegate() == pairing_delegate)
      device_chromeos->EndPairing();
  }
}

void BluetoothAdapterChromeOS::AdapterAdded(
    const dbus::ObjectPath& object_path) {
  // Set the adapter to the newly added adapter only if no adapter is present.
  if (!IsPresent())
    SetAdapter(object_path);
}

void BluetoothAdapterChromeOS::AdapterRemoved(
    const dbus::ObjectPath& object_path) {
  if (object_path == object_path_)
    RemoveAdapter();
}

void BluetoothAdapterChromeOS::AdapterPropertyChanged(
    const dbus::ObjectPath& object_path,
    const std::string& property_name) {
  if (object_path != object_path_)
    return;

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  if (property_name == properties->powered.name())
    PoweredChanged(properties->powered.value());
  else if (property_name == properties->discoverable.name())
    DiscoverableChanged(properties->discoverable.value());
  else if (property_name == properties->discovering.name())
    DiscoveringChanged(properties->discovering.value());
}

void BluetoothAdapterChromeOS::DeviceAdded(
  const dbus::ObjectPath& object_path) {
  BluetoothDeviceClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
          GetProperties(object_path);
  if (properties->adapter.value() != object_path_)
    return;

  BluetoothDeviceChromeOS* device_chromeos =
      new BluetoothDeviceChromeOS(this,
                                  object_path,
                                  ui_task_runner_,
                                  socket_thread_);
  DCHECK(devices_.find(device_chromeos->GetAddress()) == devices_.end());

  devices_[device_chromeos->GetAddress()] = device_chromeos;

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    DeviceAdded(this, device_chromeos));
}

void BluetoothAdapterChromeOS::DeviceRemoved(
    const dbus::ObjectPath& object_path) {
  for (DevicesMap::iterator iter = devices_.begin();
       iter != devices_.end(); ++iter) {
    BluetoothDeviceChromeOS* device_chromeos =
        static_cast<BluetoothDeviceChromeOS*>(iter->second);
    if (device_chromeos->object_path() == object_path) {
      devices_.erase(iter);

      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                        DeviceRemoved(this, device_chromeos));
      delete device_chromeos;
      return;
    }
  }
}

void BluetoothAdapterChromeOS::DevicePropertyChanged(
    const dbus::ObjectPath& object_path,
    const std::string& property_name) {
  BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
  if (!device_chromeos)
    return;

  BluetoothDeviceClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
          GetProperties(object_path);

  if (property_name == properties->bluetooth_class.name() ||
      property_name == properties->address.name() ||
      property_name == properties->alias.name() ||
      property_name == properties->paired.name() ||
      property_name == properties->trusted.name() ||
      property_name == properties->connected.name() ||
      property_name == properties->uuids.name() ||
      property_name == properties->rssi.name() ||
      property_name == properties->connection_rssi.name() ||
      property_name == properties->connection_tx_power.name())
    NotifyDeviceChanged(device_chromeos);

  // When a device becomes paired, mark it as trusted so that the user does
  // not need to approve every incoming connection
  if (property_name == properties->paired.name() &&
      properties->paired.value() && !properties->trusted.value())
    device_chromeos->SetTrusted();

  // UMA connection counting
  if (property_name == properties->connected.name()) {
    // PlayStation joystick tries to reconnect after disconnection from USB.
    // If it is still not trusted, set it, so it becomes available on the
    // list of known devices.
    if (properties->connected.value() && device_chromeos->IsTrustable() &&
        !properties->trusted.value())
      device_chromeos->SetTrusted();

    int count = 0;

    for (DevicesMap::iterator iter = devices_.begin();
         iter != devices_.end(); ++iter) {
      if (iter->second->IsPaired() && iter->second->IsConnected())
        ++count;
    }

    UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count);
  }
}

void BluetoothAdapterChromeOS::InputPropertyChanged(
    const dbus::ObjectPath& object_path,
    const std::string& property_name) {
  BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
  if (!device_chromeos)
    return;

  BluetoothInputClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothInputClient()->
          GetProperties(object_path);

  // Properties structure can be removed, which triggers a change in the
  // BluetoothDevice::IsConnectable() property, as does a change in the
  // actual reconnect_mode property.
  if (!properties ||
      property_name == properties->reconnect_mode.name())
    NotifyDeviceChanged(device_chromeos);
}

void BluetoothAdapterChromeOS::Released() {
  DCHECK(agent_.get());
  VLOG(1) << "Release";

  // Called after we unregister the pairing agent, e.g. when changing I/O
  // capabilities. Nothing much to be done right now.
}

void BluetoothAdapterChromeOS::RequestPinCode(
    const dbus::ObjectPath& device_path,
    const PinCodeCallback& callback) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": RequestPinCode";

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing) {
    callback.Run(REJECTED, "");
    return;
  }

  pairing->RequestPinCode(callback);
}

void BluetoothAdapterChromeOS::DisplayPinCode(
    const dbus::ObjectPath& device_path,
    const std::string& pincode) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": DisplayPinCode: " << pincode;

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing)
    return;

  pairing->DisplayPinCode(pincode);
}

void BluetoothAdapterChromeOS::RequestPasskey(
    const dbus::ObjectPath& device_path,
    const PasskeyCallback& callback) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": RequestPasskey";

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing) {
    callback.Run(REJECTED, 0);
    return;
  }

  pairing->RequestPasskey(callback);
}

void BluetoothAdapterChromeOS::DisplayPasskey(
    const dbus::ObjectPath& device_path,
    uint32 passkey,
    uint16 entered) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": DisplayPasskey: " << passkey
          << " (" << entered << " entered)";

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing)
    return;

  if (entered == 0)
    pairing->DisplayPasskey(passkey);

  pairing->KeysEntered(entered);
}

void BluetoothAdapterChromeOS::RequestConfirmation(
    const dbus::ObjectPath& device_path,
    uint32 passkey,
    const ConfirmationCallback& callback) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": RequestConfirmation: " << passkey;

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing) {
    callback.Run(REJECTED);
    return;
  }

  pairing->RequestConfirmation(passkey, callback);
}

void BluetoothAdapterChromeOS::RequestAuthorization(
    const dbus::ObjectPath& device_path,
    const ConfirmationCallback& callback) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": RequestAuthorization";

  BluetoothPairingChromeOS* pairing = GetPairing(device_path);
  if (!pairing) {
    callback.Run(REJECTED);
    return;
  }

  pairing->RequestAuthorization(callback);
}

void BluetoothAdapterChromeOS::AuthorizeService(
    const dbus::ObjectPath& device_path,
    const std::string& uuid,
    const ConfirmationCallback& callback) {
  DCHECK(agent_.get());
  VLOG(1) << device_path.value() << ": AuthorizeService: " << uuid;

  BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(device_path);
  if (!device_chromeos) {
    callback.Run(CANCELLED);
    return;
  }

  // We always set paired devices to Trusted, so the only reason that this
  // method call would ever be called is in the case of a race condition where
  // our "Set('Trusted', true)" method call is still pending in the Bluetooth
  // daemon because it's busy handling the incoming connection.
  if (device_chromeos->IsPaired()) {
    callback.Run(SUCCESS);
    return;
  }

  // TODO(keybuk): reject service authorizations when not paired, determine
  // whether this is acceptable long-term.
  LOG(WARNING) << "Rejecting service connection from unpaired device "
               << device_chromeos->GetAddress() << " for UUID " << uuid;
  callback.Run(REJECTED);
}

void BluetoothAdapterChromeOS::Cancel() {
  DCHECK(agent_.get());
  VLOG(1) << "Cancel";
}

void BluetoothAdapterChromeOS::OnRegisterAgent() {
  VLOG(1) << "Pairing agent registered, requesting to be made default";

  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
      RequestDefaultAgent(
          dbus::ObjectPath(kAgentPath),
          base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent,
                     weak_ptr_factory_.GetWeakPtr()),
          base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgentError,
                     weak_ptr_factory_.GetWeakPtr()));

}

void BluetoothAdapterChromeOS::OnRegisterAgentError(
    const std::string& error_name,
    const std::string& error_message) {
  // Our agent being already registered isn't an error.
  if (error_name == bluetooth_agent_manager::kErrorAlreadyExists)
    return;

  LOG(WARNING) << ": Failed to register pairing agent: "
               << error_name << ": " << error_message;
}

void BluetoothAdapterChromeOS::OnRequestDefaultAgent() {
  VLOG(1) << "Pairing agent now default";
}

void BluetoothAdapterChromeOS::OnRequestDefaultAgentError(
    const std::string& error_name,
    const std::string& error_message) {
  LOG(WARNING) << ": Failed to make pairing agent default: "
               << error_name << ": " << error_message;
}

BluetoothDeviceChromeOS*
BluetoothAdapterChromeOS::GetDeviceWithPath(
    const dbus::ObjectPath& object_path) {
  for (DevicesMap::iterator iter = devices_.begin();
       iter != devices_.end(); ++iter) {
    BluetoothDeviceChromeOS* device_chromeos =
        static_cast<BluetoothDeviceChromeOS*>(iter->second);
    if (device_chromeos->object_path() == object_path)
      return device_chromeos;
  }

  return NULL;
}

BluetoothPairingChromeOS* BluetoothAdapterChromeOS::GetPairing(
    const dbus::ObjectPath& object_path)
{
  BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
  if (!device_chromeos) {
    LOG(WARNING) << "Pairing Agent request for unknown device: "
                 << object_path.value();
    return NULL;
  }

  BluetoothPairingChromeOS* pairing = device_chromeos->GetPairing();
  if (pairing)
    return pairing;

  // The device doesn't have its own pairing context, so this is an incoming
  // pairing request that should use our best default delegate (if we have one).
  BluetoothDevice::PairingDelegate* pairing_delegate = DefaultPairingDelegate();
  if (!pairing_delegate)
    return NULL;

  return device_chromeos->BeginPairing(pairing_delegate);
}

void BluetoothAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) {
  DCHECK(!IsPresent());
  object_path_ = object_path;

  VLOG(1) << object_path_.value() << ": using adapter.";

  VLOG(1) << "Registering pairing agent";
  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
      RegisterAgent(
          dbus::ObjectPath(kAgentPath),
          bluetooth_agent_manager::kKeyboardDisplayCapability,
          base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent,
                     weak_ptr_factory_.GetWeakPtr()),
          base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError,
                     weak_ptr_factory_.GetWeakPtr()));

  SetDefaultAdapterName();

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  PresentChanged(true);

  if (properties->powered.value())
    PoweredChanged(true);
  if (properties->discoverable.value())
    DiscoverableChanged(true);
  if (properties->discovering.value())
    DiscoveringChanged(true);

  std::vector<dbus::ObjectPath> device_paths =
      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
          GetDevicesForAdapter(object_path_);

  for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin();
       iter != device_paths.end(); ++iter) {
    DeviceAdded(*iter);
  }
}

void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
  std::string board = base::SysInfo::GetLsbReleaseBoard();
  std::string alias;
  if (board.substr(0, 6) == "stumpy") {
    alias = "Chromebox";
  } else if (board.substr(0, 4) == "link") {
    alias = "Chromebook Pixel";
  } else {
    alias = "Chromebook";
  }

  SetName(alias, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
}

void BluetoothAdapterChromeOS::RemoveAdapter() {
  DCHECK(IsPresent());
  VLOG(1) << object_path_.value() << ": adapter removed.";

  BluetoothAdapterClient::Properties* properties =
      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
          GetProperties(object_path_);

  object_path_ = dbus::ObjectPath("");

  if (properties->powered.value())
    PoweredChanged(false);
  if (properties->discoverable.value())
    DiscoverableChanged(false);
  if (properties->discovering.value())
    DiscoveringChanged(false);

  // Copy the devices list here and clear the original so that when we
  // send DeviceRemoved(), GetDevices() returns no devices.
  DevicesMap devices = devices_;
  devices_.clear();

  for (DevicesMap::iterator iter = devices.begin();
       iter != devices.end(); ++iter) {
    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                      DeviceRemoved(this, iter->second));
    delete iter->second;
  }

  PresentChanged(false);
}

void BluetoothAdapterChromeOS::PoweredChanged(bool powered) {
  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    AdapterPoweredChanged(this, powered));
}

void BluetoothAdapterChromeOS::DiscoverableChanged(bool discoverable) {
  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    AdapterDiscoverableChanged(this, discoverable));
}

void BluetoothAdapterChromeOS::DiscoveringChanged(
    bool discovering) {
  // If the adapter stopped discovery due to a reason other than a request by
  // us, reset the count to 0.
  VLOG(1) << "Discovering changed: " << discovering;
  if (!discovering && !discovery_request_pending_
      && num_discovery_sessions_ > 0) {
    VLOG(1) << "Marking sessions as inactive.";
    num_discovery_sessions_ = 0;
    MarkDiscoverySessionsAsInactive();
  }
  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    AdapterDiscoveringChanged(this, discovering));
}

void BluetoothAdapterChromeOS::PresentChanged(bool present) {
  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    AdapterPresentChanged(this, present));
}

void BluetoothAdapterChromeOS::NotifyDeviceChanged(
    BluetoothDeviceChromeOS* device) {
  DCHECK(device->adapter_ == this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                    DeviceChanged(this, device));
}

void BluetoothAdapterChromeOS::NotifyGattServiceAdded(
    BluetoothRemoteGattServiceChromeOS* service) {
  DCHECK_EQ(service->GetAdapter(), this);
  DCHECK_EQ(
      static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
      this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattServiceAdded(this, service->GetDevice(), service));
}

void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
    BluetoothRemoteGattServiceChromeOS* service) {
  DCHECK_EQ(service->GetAdapter(), this);
  DCHECK_EQ(
      static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
      this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattServiceRemoved(this, service->GetDevice(), service));
}

void BluetoothAdapterChromeOS::NotifyGattServiceChanged(
    BluetoothRemoteGattServiceChromeOS* service) {
  DCHECK_EQ(service->GetAdapter(), this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattServiceChanged(this, service));
}

void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
    BluetoothRemoteGattServiceChromeOS* service) {
  DCHECK_EQ(service->GetAdapter(), this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattDiscoveryCompleteForService(this, service));
}

void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
    BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                characteristic->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattCharacteristicAdded(this, characteristic));
}

void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
    BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                characteristic->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattCharacteristicRemoved(this, characteristic));
}

void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
    BluetoothRemoteGattDescriptorChromeOS* descriptor) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                descriptor->GetCharacteristic()->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattDescriptorAdded(this, descriptor));
}

void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
    BluetoothRemoteGattDescriptorChromeOS* descriptor) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                descriptor->GetCharacteristic()->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattDescriptorRemoved(this, descriptor));
}

void BluetoothAdapterChromeOS::NotifyGattCharacteristicValueChanged(
    BluetoothRemoteGattCharacteristicChromeOS* characteristic,
    const std::vector<uint8>& value) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                characteristic->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(
      BluetoothAdapter::Observer,
      observers_,
      GattCharacteristicValueChanged(this, characteristic, value));
}

void BluetoothAdapterChromeOS::NotifyGattDescriptorValueChanged(
    BluetoothRemoteGattDescriptorChromeOS* descriptor,
    const std::vector<uint8>& value) {
  DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
                descriptor->GetCharacteristic()->GetService())->GetAdapter(),
            this);

  FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
                    observers_,
                    GattDescriptorValueChanged(this, descriptor, value));
}

void BluetoothAdapterChromeOS::OnSetDiscoverable(
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    bool success) {
  // Set the discoverable_timeout property to zero so the adapter remains
  // discoverable forever.
  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      GetProperties(object_path_)->discoverable_timeout.Set(
          0,
          base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback,
                     error_callback));
}

void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    bool success) {
  if (success)
    callback.Run();
  else
    error_callback.Run();
}

void BluetoothAdapterChromeOS::AddDiscoverySession(
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << __func__;
  if (discovery_request_pending_) {
    // The pending request is either to stop a previous session or to start a
    // new one. Either way, queue this one.
    DCHECK(num_discovery_sessions_ == 1 || num_discovery_sessions_ == 0);
    VLOG(1) << "Pending request to start/stop device discovery. Queueing "
            << "request to start a new discovery session.";
    discovery_request_queue_.push(std::make_pair(callback, error_callback));
    return;
  }

  // The adapter is already discovering.
  if (num_discovery_sessions_ > 0) {
    DCHECK(IsDiscovering());
    DCHECK(!discovery_request_pending_);
    num_discovery_sessions_++;
    callback.Run();
    return;
  }

  // There are no active discovery sessions.
  DCHECK(num_discovery_sessions_ == 0);

  // This is the first request to start device discovery.
  discovery_request_pending_ = true;
  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      StartDiscovery(
          object_path_,
          base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback),
          base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback,
                     error_callback));
}

void BluetoothAdapterChromeOS::RemoveDiscoverySession(
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  VLOG(1) << __func__;
  // There are active sessions other than the one currently being removed.
  if (num_discovery_sessions_ > 1) {
    DCHECK(IsDiscovering());
    DCHECK(!discovery_request_pending_);
    num_discovery_sessions_--;
    callback.Run();
    return;
  }

  // If there is a pending request to BlueZ, then queue this request.
  if (discovery_request_pending_) {
    VLOG(1) << "Pending request to start/stop device discovery. Queueing "
            << "request to stop discovery session.";
    error_callback.Run();
    return;
  }

  // There are no active sessions. Return error.
  if (num_discovery_sessions_ == 0) {
    // TODO(armansito): This should never happen once we have the
    // DiscoverySession API. Replace this case with an assert once it's
    // the deprecated methods have been removed. (See crbug.com/3445008).
    VLOG(1) << "No active discovery sessions. Returning error.";
    error_callback.Run();
    return;
  }

  // There is exactly one active discovery session. Request BlueZ to stop
  // discovery.
  DCHECK(num_discovery_sessions_ == 1);
  discovery_request_pending_ = true;
  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
      StopDiscovery(
          object_path_,
          base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery,
                     weak_ptr_factory_.GetWeakPtr(),
                     callback),
          base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError,
                     weak_ptr_factory_.GetWeakPtr(),
                     error_callback));
}

void BluetoothAdapterChromeOS::OnStartDiscovery(const base::Closure& callback) {
  // Report success on the original request and increment the count.
  VLOG(1) << __func__;
  DCHECK(discovery_request_pending_);
  DCHECK(num_discovery_sessions_ == 0);
  discovery_request_pending_ = false;
  num_discovery_sessions_++;
  callback.Run();

  // Try to add a new discovery session for each queued request.
  ProcessQueuedDiscoveryRequests();
}

void BluetoothAdapterChromeOS::OnStartDiscoveryError(
    const base::Closure& callback,
    const ErrorCallback& error_callback,
    const std::string& error_name,
    const std::string& error_message) {
  LOG(WARNING) << object_path_.value() << ": Failed to start discovery: "
               << error_name << ": " << error_message;

  // Failed to start discovery. This can only happen if the count is at 0.
  DCHECK(num_discovery_sessions_ == 0);
  DCHECK(discovery_request_pending_);
  discovery_request_pending_ = false;

  // Discovery request may fail if discovery was previously initiated by Chrome,
  // but the session were invalidated due to the discovery state unexpectedly
  // changing to false and then back to true. In this case, report success.
  if (error_name == bluetooth_device::kErrorInProgress && IsDiscovering()) {
    VLOG(1) << "Discovery previously initiated. Reporting success.";
    num_discovery_sessions_++;
    callback.Run();
  } else {
    error_callback.Run();
  }

  // Try to add a new discovery session for each queued request.
  ProcessQueuedDiscoveryRequests();
}

void BluetoothAdapterChromeOS::OnStopDiscovery(const base::Closure& callback) {
  // Report success on the original request and decrement the count.
  VLOG(1) << __func__;
  DCHECK(discovery_request_pending_);
  DCHECK(num_discovery_sessions_ == 1);
  discovery_request_pending_ = false;
  num_discovery_sessions_--;
  callback.Run();

  // Try to add a new discovery session for each queued request.
  ProcessQueuedDiscoveryRequests();
}

void BluetoothAdapterChromeOS::OnStopDiscoveryError(
    const ErrorCallback& error_callback,
    const std::string& error_name,
    const std::string& error_message) {
  LOG(WARNING) << object_path_.value() << ": Failed to stop discovery: "
               << error_name << ": " << error_message;

  // Failed to stop discovery. This can only happen if the count is at 1.
  DCHECK(discovery_request_pending_);
  DCHECK(num_discovery_sessions_ == 1);
  discovery_request_pending_ = false;
  error_callback.Run();

  // Try to add a new discovery session for each queued request.
  ProcessQueuedDiscoveryRequests();
}

void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() {
  while (!discovery_request_queue_.empty()) {
    VLOG(1) << "Process queued discovery request.";
    DiscoveryCallbackPair callbacks = discovery_request_queue_.front();
    discovery_request_queue_.pop();
    AddDiscoverySession(callbacks.first, callbacks.second);

    // If the queued request resulted in a pending call, then let it
    // asynchonously process the remaining queued requests once the pending
    // call returns.
    if (discovery_request_pending_)
      return;
  }
}

}  // namespace chromeos
