This source file includes following definitions.
- GetFactoryInstance
 
- Shutdown
 
- OnListenerAdded
 
- OnListenerRemoved
 
- ValidatePairingResponseOptions
 
- BluetoothPrivateSetAdapterStateFunction
 
- BluetoothPrivateSetAdapterStateFunction
 
- DoWork
 
- CreatePropertySetCallback
 
- CreatePropertyErrorCallback
 
- OnAdapterPropertySet
 
- OnAdapterPropertyError
 
- SendError
 
- BluetoothPrivateSetPairingResponseFunction
 
- BluetoothPrivateSetPairingResponseFunction
 
- DoWork
 
#include "chrome/browser/extensions/api/bluetooth/bluetooth_private_api.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/strings/string_util.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
#include "chrome/common/extensions/api/bluetooth_private.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "extensions/browser/extension_system.h"
namespace bt_private = extensions::api::bluetooth_private;
namespace extensions {
static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothPrivateAPI> >
    g_factory = LAZY_INSTANCE_INITIALIZER;
BrowserContextKeyedAPIFactory<BluetoothPrivateAPI>*
BluetoothPrivateAPI::GetFactoryInstance() {
  return g_factory.Pointer();
}
BluetoothPrivateAPI::BluetoothPrivateAPI(content::BrowserContext* context)
    : browser_context_(context) {
  ExtensionSystem::Get(browser_context_)->event_router()->RegisterObserver(
      this, bt_private::OnPairing::kEventName);
}
BluetoothPrivateAPI::~BluetoothPrivateAPI() {}
void BluetoothPrivateAPI::Shutdown() {
  ExtensionSystem::Get(browser_context_)->event_router()->UnregisterObserver(
      this);
}
void BluetoothPrivateAPI::OnListenerAdded(const EventListenerInfo& details) {
  BluetoothAPI::Get(browser_context_)
      ->bluetooth_event_router()
      ->AddPairingDelegate(details.extension_id);
}
void BluetoothPrivateAPI::OnListenerRemoved(const EventListenerInfo& details) {
  BluetoothAPI::Get(browser_context_)
      ->bluetooth_event_router()
      ->RemovePairingDelegate(details.extension_id);
}
namespace api {
namespace {
const char kNameProperty[] = "name";
const char kPoweredProperty[] = "powered";
const char kDiscoverableProperty[] = "discoverable";
const char kSetAdapterPropertyError[] = "Error setting adapter properties: $1";
const char kDeviceNotFoundError[] =
    "Given address is not a valid Bluetooth device.";
const char kPairingNotEnabled[] =
    "Pairing must be enabled to set a pairing response.";
const char kInvalidPairingResponseOptions[] =
    "Invalid pairing response options";
bool ValidatePairingResponseOptions(
    const device::BluetoothDevice* device,
    const bt_private::SetPairingResponseOptions& options) {
  bool response = options.response != bt_private::PAIRING_RESPONSE_NONE;
  bool pincode = options.pincode.get() != NULL;
  bool passkey = options.passkey.get() != NULL;
  if (!response && !pincode && !passkey)
    return false;
  if (pincode && passkey)
    return false;
  if (options.response != bt_private::PAIRING_RESPONSE_CONFIRM &&
      (pincode || passkey))
    return false;
  
  if (pincode && !device->ExpectingPinCode())
    return false;
  if (passkey && !device->ExpectingPasskey())
    return false;
  if (options.response == bt_private::PAIRING_RESPONSE_CONFIRM && !pincode &&
      !passkey && !device->ExpectingConfirmation())
    return false;
  return true;
}
}  
BluetoothPrivateSetAdapterStateFunction::
    BluetoothPrivateSetAdapterStateFunction() {}
BluetoothPrivateSetAdapterStateFunction::
    ~BluetoothPrivateSetAdapterStateFunction() {}
bool BluetoothPrivateSetAdapterStateFunction::DoWork(
    scoped_refptr<device::BluetoothAdapter> adapter) {
  scoped_ptr<bt_private::SetAdapterState::Params> params(
      bt_private::SetAdapterState::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  const bt_private::NewAdapterState& new_state = params->adapter_state;
  
  std::string* name = new_state.name.get();
  bool* powered = new_state.powered.get();
  bool* discoverable = new_state.discoverable.get();
  if (name && adapter->GetName() != *name) {
    pending_properties_.insert(kNameProperty);
    adapter->SetName(*name,
                     CreatePropertySetCallback(kNameProperty),
                     CreatePropertyErrorCallback(kNameProperty));
  }
  if (powered && adapter->IsPowered() != *powered) {
    pending_properties_.insert(kPoweredProperty);
    adapter->SetPowered(*powered,
                        CreatePropertySetCallback(kPoweredProperty),
                        CreatePropertyErrorCallback(kPoweredProperty));
  }
  if (discoverable && adapter->IsDiscoverable() != *discoverable) {
    pending_properties_.insert(kDiscoverableProperty);
    adapter->SetDiscoverable(
        *discoverable,
        CreatePropertySetCallback(kDiscoverableProperty),
        CreatePropertyErrorCallback(kDiscoverableProperty));
  }
  if (pending_properties_.empty())
    SendResponse(true);
  return true;
}
base::Closure
BluetoothPrivateSetAdapterStateFunction::CreatePropertySetCallback(
    const std::string& property_name) {
  return base::Bind(
      &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet,
      this,
      property_name);
}
base::Closure
BluetoothPrivateSetAdapterStateFunction::CreatePropertyErrorCallback(
    const std::string& property_name) {
  return base::Bind(
      &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError,
      this,
      property_name);
}
void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet(
    const std::string& property) {
  DCHECK(pending_properties_.find(property) != pending_properties_.end());
  DCHECK(failed_properties_.find(property) != pending_properties_.end());
  pending_properties_.erase(property);
  if (pending_properties_.empty()) {
    if (failed_properties_.empty())
      SendResponse(true);
    else
      SendError();
  }
}
void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError(
    const std::string& property) {
  DCHECK(pending_properties_.find(property) != pending_properties_.end());
  DCHECK(failed_properties_.find(property) != pending_properties_.end());
  pending_properties_.erase(property);
  failed_properties_.insert(property);
  if (pending_properties_.empty())
    SendError();
}
void BluetoothPrivateSetAdapterStateFunction::SendError() {
  DCHECK(pending_properties_.empty());
  DCHECK(!failed_properties_.empty());
  std::vector<std::string> failed_vector;
  std::copy(failed_properties_.begin(),
            failed_properties_.end(),
            std::back_inserter(failed_vector));
  std::vector<std::string> replacements(1);
  replacements[0] = JoinString(failed_vector, ", ");
  std::string error =
      ReplaceStringPlaceholders(kSetAdapterPropertyError, replacements, NULL);
  SetError(error);
  SendResponse(false);
}
BluetoothPrivateSetPairingResponseFunction::
    BluetoothPrivateSetPairingResponseFunction() {}
BluetoothPrivateSetPairingResponseFunction::
    ~BluetoothPrivateSetPairingResponseFunction() {}
bool BluetoothPrivateSetPairingResponseFunction::DoWork(
    scoped_refptr<device::BluetoothAdapter> adapter) {
  scoped_ptr<bt_private::SetPairingResponse::Params> params(
      bt_private::SetPairingResponse::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  const bt_private::SetPairingResponseOptions& options = params->options;
  BluetoothEventRouter* router =
      BluetoothAPI::Get(browser_context())->bluetooth_event_router();
  if (!router->GetPairingDelegate(extension_id())) {
    SetError(kPairingNotEnabled);
    SendResponse(false);
    return true;
  }
  const std::string& device_address = options.device.address;
  device::BluetoothDevice* device = adapter->GetDevice(device_address);
  if (!device) {
    SetError(kDeviceNotFoundError);
    SendResponse(false);
    return true;
  }
  if (!ValidatePairingResponseOptions(device, options)) {
    SetError(kInvalidPairingResponseOptions);
    SendResponse(false);
    return true;
  }
  if (options.response != bt_private::PAIRING_RESPONSE_NONE) {
    switch (options.response) {
      case bt_private::PAIRING_RESPONSE_CONFIRM:
        device->ConfirmPairing();
        break;
      case bt_private::PAIRING_RESPONSE_REJECT:
        device->RejectPairing();
        break;
      case bt_private::PAIRING_RESPONSE_CANCEL:
        device->CancelPairing();
        break;
      default:
        NOTREACHED();
    }
  } else if (options.pincode.get()) {
    device->SetPinCode(*options.pincode.get());
  } else if (options.passkey.get()) {
    device->SetPasskey(*options.passkey.get());
  }
  SendResponse(true);
  return true;
}
}  
}