blob: 869692f84ff4999968a1467a20a6524124352f74 [file] [log] [blame]
// Copyright 2015 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_advertisement_bluez.h"
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/guid.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "dbus/bus.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter_bluez.h"
#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
void UnregisterFailure(device::BluetoothAdvertisement::ErrorCode error) {
LOG(ERROR)
<< "BluetoothAdvertisementBlueZ::Unregister failed with error code = "
<< error;
}
device::BluetoothAdvertisement::ErrorCode GetErrorCodeFromErrorStrings(
const std::string& error_name,
const std::string& error_message) {
if (error_name == bluetooth_advertising_manager::kErrorFailed ||
error_name == bluetooth_advertising_manager::kErrorAlreadyExists) {
return device::BluetoothAdvertisement::ErrorCode::
ERROR_ADVERTISEMENT_ALREADY_EXISTS;
} else if (error_name ==
bluetooth_advertising_manager::kErrorInvalidArguments) {
return device::BluetoothAdvertisement::ErrorCode::
ERROR_ADVERTISEMENT_INVALID_LENGTH;
} else if (error_name == bluetooth_advertising_manager::kErrorDoesNotExist) {
return device::BluetoothAdvertisement::ErrorCode::
ERROR_ADVERTISEMENT_DOES_NOT_EXIST;
}
return device::BluetoothAdvertisement::ErrorCode::
INVALID_ADVERTISEMENT_ERROR_CODE;
}
void RegisterErrorCallbackConnector(
const device::BluetoothAdapter::CreateAdvertisementErrorCallback&
error_callback,
const std::string& error_name,
const std::string& error_message) {
LOG(ERROR) << "Error while registering advertisement. error_name = "
<< error_name << ", error_message = " << error_message;
error_callback.Run(GetErrorCodeFromErrorStrings(error_name, error_message));
}
void UnregisterErrorCallbackConnector(
const device::BluetoothAdapter::CreateAdvertisementErrorCallback&
error_callback,
const std::string& error_name,
const std::string& error_message) {
LOG(WARNING) << "Error while unregistering advertisement. error_name = "
<< error_name << ", error_message = " << error_message;
error_callback.Run(GetErrorCodeFromErrorStrings(error_name, error_message));
}
} // namespace
namespace bluez {
BluetoothAdvertisementBlueZ::BluetoothAdvertisementBlueZ(
scoped_ptr<device::BluetoothAdvertisement::Data> data,
scoped_refptr<BluetoothAdapterBlueZ> adapter)
: adapter_(adapter) {
// Generate a new object path - make sure that we strip any -'s from the
// generated GUID string since object paths can only contain alphanumeric
// characters and _ characters.
std::string GuidString = base::GenerateGUID();
base::RemoveChars(GuidString, "-", &GuidString);
dbus::ObjectPath advertisement_object_path =
dbus::ObjectPath("/org/chromium/bluetooth_advertisement/" + GuidString);
DCHECK(bluez::BluezDBusManager::Get());
provider_ = bluez::BluetoothLEAdvertisementServiceProvider::Create(
bluez::BluezDBusManager::Get()->GetSystemBus(), advertisement_object_path,
this,
static_cast<
bluez::BluetoothLEAdvertisementServiceProvider::AdvertisementType>(
data->type()),
data->service_uuids(), data->manufacturer_data(), data->solicit_uuids(),
data->service_data());
}
void BluetoothAdvertisementBlueZ::Register(
const base::Closure& success_callback,
const device::BluetoothAdapter::CreateAdvertisementErrorCallback&
error_callback) {
DCHECK(bluez::BluezDBusManager::Get());
bluez::BluezDBusManager::Get()
->GetBluetoothLEAdvertisingManagerClient()
->RegisterAdvertisement(
adapter_->object_path(), provider_->object_path(), success_callback,
base::Bind(&RegisterErrorCallbackConnector, error_callback));
}
BluetoothAdvertisementBlueZ::~BluetoothAdvertisementBlueZ() {
Unregister(base::Bind(&base::DoNothing), base::Bind(&UnregisterFailure));
}
void BluetoothAdvertisementBlueZ::Unregister(
const SuccessCallback& success_callback,
const ErrorCallback& error_callback) {
// If we don't have a provider, that means we have already been unregistered,
// return an error.
if (!provider_) {
error_callback.Run(device::BluetoothAdvertisement::ErrorCode::
ERROR_ADVERTISEMENT_DOES_NOT_EXIST);
return;
}
DCHECK(bluez::BluezDBusManager::Get());
bluez::BluezDBusManager::Get()
->GetBluetoothLEAdvertisingManagerClient()
->UnregisterAdvertisement(
adapter_->object_path(), provider_->object_path(), success_callback,
base::Bind(&UnregisterErrorCallbackConnector, error_callback));
provider_.reset();
}
void BluetoothAdvertisementBlueZ::Released() {
LOG(WARNING) << "Advertisement released.";
provider_.reset();
FOR_EACH_OBSERVER(BluetoothAdvertisement::Observer, observers_,
AdvertisementReleased(this));
}
} // namespace bluez