Chromium Code Reviews| Index: device/bluetooth/bluetooth_socket_chromeos.cc |
| diff --git a/device/bluetooth/bluetooth_socket_chromeos.cc b/device/bluetooth/bluetooth_socket_chromeos.cc |
| index c281a595100d29a1905ed956431ddaccae168dd7..b9ac9acd966ee08ac2aad02979c4b02df9648b97 100644 |
| --- a/device/bluetooth/bluetooth_socket_chromeos.cc |
| +++ b/device/bluetooth/bluetooth_socket_chromeos.cc |
| @@ -4,22 +4,49 @@ |
| #include "device/bluetooth/bluetooth_socket_chromeos.h" |
| +#include <queue> |
| #include <string> |
| +#include "base/basictypes.h" |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| #include "base/logging.h" |
| +#include "base/memory/linked_ptr.h" |
| #include "base/memory/ref_counted.h" |
| +#include "base/memory/scoped_ptr.h" |
| #include "base/sequenced_task_runner.h" |
| +#include "base/strings/string_util.h" |
| +#include "base/task_runner_util.h" |
| #include "base/threading/thread_restrictions.h" |
| +#include "base/threading/worker_pool.h" |
| +#include "chromeos/dbus/bluetooth_device_client.h" |
| +#include "chromeos/dbus/bluetooth_profile_manager_client.h" |
| +#include "chromeos/dbus/bluetooth_profile_service_provider.h" |
| +#include "chromeos/dbus/dbus_thread_manager.h" |
| +#include "dbus/bus.h" |
| #include "dbus/file_descriptor.h" |
| +#include "dbus/object_path.h" |
| +#include "device/bluetooth/bluetooth_adapter.h" |
| +#include "device/bluetooth/bluetooth_adapter_chromeos.h" |
| +#include "device/bluetooth/bluetooth_device.h" |
| +#include "device/bluetooth/bluetooth_device_chromeos.h" |
| #include "device/bluetooth/bluetooth_socket.h" |
| #include "device/bluetooth/bluetooth_socket_net.h" |
| #include "device/bluetooth/bluetooth_socket_thread.h" |
| #include "net/base/ip_endpoint.h" |
| #include "net/base/net_errors.h" |
| +#include "third_party/cros_system_api/dbus/service_constants.h" |
| + |
| +using device::BluetoothAdapter; |
| +using device::BluetoothDevice; |
| +using device::BluetoothSocketThread; |
| +using device::BluetoothUUID; |
| namespace { |
| -const char kSocketAlreadyConnected[] = "Socket is already connected."; |
| +const char kAcceptFailed[] = "Failed to accept connection."; |
| +const char kInvalidUUID[] = "Invalid UUID"; |
| +const char kSocketNotListening[] = "Socket is not listening."; |
| } // namespace |
| @@ -29,7 +56,7 @@ namespace chromeos { |
| scoped_refptr<BluetoothSocketChromeOS> |
| BluetoothSocketChromeOS::CreateBluetoothSocket( |
| scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| - scoped_refptr<device::BluetoothSocketThread> socket_thread, |
| + scoped_refptr<BluetoothSocketThread> socket_thread, |
| net::NetLog* net_log, |
| const net::NetLog::Source& source) { |
| DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); |
| @@ -39,53 +66,425 @@ BluetoothSocketChromeOS::CreateBluetoothSocket( |
| ui_task_runner, socket_thread, net_log, source)); |
| } |
| +BluetoothSocketChromeOS::AcceptRequest::AcceptRequest() {} |
| + |
| +BluetoothSocketChromeOS::AcceptRequest::~AcceptRequest() {} |
| + |
| +BluetoothSocketChromeOS::ConnectionRequest::ConnectionRequest() |
| + : accepting(false), |
| + cancelled(false) {} |
| + |
| +BluetoothSocketChromeOS::ConnectionRequest::~ConnectionRequest() {} |
| + |
| BluetoothSocketChromeOS::BluetoothSocketChromeOS( |
| scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| - scoped_refptr<device::BluetoothSocketThread> socket_thread, |
| + scoped_refptr<BluetoothSocketThread> socket_thread, |
| net::NetLog* net_log, |
| const net::NetLog::Source& source) |
| : BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source) { |
| } |
| BluetoothSocketChromeOS::~BluetoothSocketChromeOS() { |
| + DCHECK(object_path_.value().empty()); |
| + DCHECK(profile_.get() == NULL); |
| + |
| + if (adapter_.get()) { |
| + adapter_->RemoveObserver(this); |
| + adapter_ = NULL; |
| + } |
| } |
| void BluetoothSocketChromeOS::Connect( |
| - scoped_ptr<dbus::FileDescriptor> fd, |
| + const BluetoothDeviceChromeOS* device, |
| + const BluetoothUUID& uuid, |
| const base::Closure& success_callback, |
| const ErrorCompletionCallback& error_callback) { |
| DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK (object_path_.value().empty()); |
| + DCHECK (!profile_.get()); |
| - socket_thread()->task_runner()->PostTask( |
| - FROM_HERE, |
| - base::Bind( |
| - &BluetoothSocketChromeOS::DoConnect, |
| - this, |
| - base::Passed(&fd), |
| - base::Bind(&BluetoothSocketChromeOS::PostSuccess, |
| - this, |
| - success_callback), |
| - base::Bind(&BluetoothSocketChromeOS::PostErrorCompletion, |
| - this, |
| - error_callback))); |
| + if (!uuid.IsValid()) { |
| + error_callback.Run(kInvalidUUID); |
| + return; |
| + } |
| + |
| + device_address_ = device->GetAddress(); |
| + device_path_ = device->object_path(); |
| + uuid_ = uuid; |
| + options_.reset(new BluetoothProfileManagerClient::Options()); |
| + |
| + RegisterProfile(success_callback, error_callback); |
| +} |
| + |
| +void BluetoothSocketChromeOS::Listen( |
| + scoped_refptr<BluetoothAdapter> adapter, |
| + SocketType socket_type, |
| + const BluetoothUUID& uuid, |
| + int psm_or_channel, |
| + bool insecure, |
| + const base::Closure& success_callback, |
| + const ErrorCompletionCallback& error_callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK (object_path_.value().empty()); |
| + DCHECK (!profile_.get()); |
|
armansito
2014/05/13 19:44:59
nit: no space after DCHECK
keybuk
2014/05/13 20:14:53
Done.
|
| + |
| + if (!uuid.IsValid()) { |
| + error_callback.Run(kInvalidUUID); |
| + return; |
| + } |
| + |
| + adapter_ = adapter; |
| + adapter_->AddObserver(this); |
| + |
| + uuid_ = uuid; |
| + options_.reset(new BluetoothProfileManagerClient::Options()); |
| + |
| + switch (socket_type) { |
| + case kRfcomm: |
| + options_->channel.reset(new uint16( |
| + psm_or_channel == BluetoothAdapter::kChannelAuto |
| + ? 0 : psm_or_channel)); |
| + break; |
| + case kL2cap: |
| + options_->psm.reset(new uint16( |
| + psm_or_channel == BluetoothAdapter::kPsmAuto |
| + ? 0 : psm_or_channel)); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| + |
| + if (insecure) |
| + options_->require_authentication.reset(new bool(false)); |
| + |
| + RegisterProfile(success_callback, error_callback); |
| +} |
| + |
| +void BluetoothSocketChromeOS::Close() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + if (profile_) |
| + UnregisterProfile(); |
| + |
| + if (!device_path_.value().empty()) { |
| + BluetoothSocketNet::Close(); |
| + } else { |
| + DoCloseListening(); |
| + } |
| +} |
| + |
| +void BluetoothSocketChromeOS::Disconnect(const base::Closure& callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + if (profile_) |
| + UnregisterProfile(); |
| + |
| + if (!device_path_.value().empty()) { |
| + BluetoothSocketNet::Disconnect(callback); |
| + } else { |
| + DoCloseListening(); |
| + callback.Run(); |
| + } |
| } |
| void BluetoothSocketChromeOS::Accept( |
| const AcceptCompletionCallback& success_callback, |
| const ErrorCompletionCallback& error_callback) { |
| - NOTIMPLEMENTED(); |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + if (!device_path_.value().empty()) { |
| + error_callback.Run(kSocketNotListening); |
| + return; |
| + } |
| + |
| + // Only one pending accept at a time |
| + if (accept_request_.get()) { |
| + error_callback.Run(net::ErrorToString(net::ERR_IO_PENDING)); |
| + return; |
| + } |
| + |
| + accept_request_.reset(new AcceptRequest); |
| + accept_request_->success_callback = success_callback; |
| + accept_request_->error_callback = error_callback; |
| + |
| + if (connection_request_queue_.size() >= 1) { |
| + AcceptConnectionRequest(); |
| + } |
| } |
| -void BluetoothSocketChromeOS::DoConnect( |
| - scoped_ptr<dbus::FileDescriptor> fd, |
| +void BluetoothSocketChromeOS::RegisterProfile( |
| const base::Closure& success_callback, |
| const ErrorCompletionCallback& error_callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK(object_path_.value().empty()); |
| + DCHECK(!profile_.get()); |
| + |
| + // The object path is relatively meaningless, but has to be unique, so for |
| + // connecting profiles use a combination of the device address and profile |
| + // UUID. |
| + std::string device_address_path, uuid_path; |
| + base::ReplaceChars(device_address_, ":-", "_", &device_address_path); |
| + base::ReplaceChars(uuid_.canonical_value(), ":-", "_", &uuid_path); |
| + if (!device_address_path.empty()) { |
| + object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" + |
| + device_address_path + "/" + uuid_path); |
| + } else { |
| + object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" + |
| + uuid_path); |
| + } |
| + |
| + // Create the service provider for the profile object. |
| + dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); |
| + profile_.reset(BluetoothProfileServiceProvider::Create( |
| + system_bus, object_path_, this)); |
| + DCHECK(profile_.get()); |
| + |
| + // Before reaching out to the Bluetooth Daemon to register a listening socket, |
| + // make sure it's actually running. If not, report success and carry on; |
| + // the profile will be registered when the daemon becomes available. |
| + if (adapter_ && !adapter_->IsPresent()) { |
| + VLOG(1) << object_path_.value() << ": Delaying profile registration."; |
| + success_callback.Run(); |
| + return; |
| + } |
| + |
| + VLOG(1) << object_path_.value() << ": Registering profile."; |
| + DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> |
| + RegisterProfile( |
| + object_path_, |
| + uuid_.canonical_value(), |
| + *options_, |
| + base::Bind(&BluetoothSocketChromeOS::OnRegisterProfile, |
| + this, |
| + success_callback, |
| + error_callback), |
| + base::Bind(&BluetoothSocketChromeOS::OnRegisterProfileError, |
| + this, |
| + error_callback)); |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnRegisterProfile( |
| + const base::Closure& success_callback, |
| + const ErrorCompletionCallback& error_callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + if (!device_path_.value().empty()) { |
| + VLOG(1) << object_path_.value() << ": Profile registered, connecting to " |
| + << device_path_.value(); |
| + |
| + DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
| + ConnectProfile( |
| + device_path_, |
| + uuid_.canonical_value(), |
| + base::Bind( |
| + &BluetoothSocketChromeOS::OnConnectProfile, |
| + this, |
| + success_callback), |
| + base::Bind( |
| + &BluetoothSocketChromeOS::OnConnectProfileError, |
| + this, |
| + error_callback)); |
| + } else { |
| + VLOG(1) << object_path_.value() << ": Profile registered."; |
| + success_callback.Run(); |
| + } |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnRegisterProfileError( |
| + const ErrorCompletionCallback& error_callback, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + LOG(WARNING) << object_path_.value() << ": Failed to register profile: " |
| + << error_name << ": " << error_message; |
| + error_callback.Run(error_message); |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnConnectProfile( |
| + const base::Closure& success_callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + VLOG(1) << object_path_.value() << ": Profile connected."; |
| + UnregisterProfile(); |
|
armansito
2014/05/13 19:44:59
Is the call to UnregisterProfile here intended?
keybuk
2014/05/13 20:03:53
Yes, the connection has been accepted, there is no
|
| + success_callback.Run(); |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnConnectProfileError( |
| + const ErrorCompletionCallback& error_callback, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + LOG(WARNING) << object_path_.value() << ": Failed to connect profile: " |
| + << error_name << ": " << error_message; |
| + UnregisterProfile(); |
| + error_callback.Run(error_message); |
| +} |
| + |
| +void BluetoothSocketChromeOS::AdapterPresentChanged(BluetoothAdapter* adapter, |
| + bool present) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK(!object_path_.value().empty()); |
| + DCHECK(profile_.get()); |
| + |
| + if (!present) |
| + return; |
| + |
| + VLOG(1) << object_path_.value() << ": Re-register profile."; |
| + DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> |
| + RegisterProfile( |
| + object_path_, |
| + uuid_.canonical_value(), |
| + *options_, |
| + base::Bind(&BluetoothSocketChromeOS::OnInternalRegisterProfile, |
| + this), |
| + base::Bind(&BluetoothSocketChromeOS::OnInternalRegisterProfileError, |
| + this)); |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnInternalRegisterProfile() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + VLOG(1) << object_path_.value() << ": Profile re-registered"; |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnInternalRegisterProfileError( |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + // It's okay if the profile already exists, it means we registered it on |
| + // initialization. |
| + if (error_name == bluetooth_profile_manager::kErrorAlreadyExists) |
| + return; |
| + |
| + LOG(WARNING) << object_path_.value() << ": Failed to re-register profile: " |
| + << error_name << ": " << error_message; |
| +} |
| + |
| +void BluetoothSocketChromeOS::Released() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + VLOG(1) << object_path_.value() << ": Release"; |
| +} |
| + |
| +void BluetoothSocketChromeOS::NewConnection( |
| + const dbus::ObjectPath& device_path, |
| + scoped_ptr<dbus::FileDescriptor> fd, |
| + const BluetoothProfileServiceProvider::Delegate::Options& options, |
| + const ConfirmationCallback& callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + VLOG(1) << object_path_.value() << ": New connection from device: " |
| + << device_path.value(); |
| + |
| + if (!device_path_.value().empty()) { |
| + DCHECK(device_path_ == device_path); |
| + |
| + socket_thread()->task_runner()->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &BluetoothSocketChromeOS::DoNewConnection, |
| + this, |
| + device_path_, |
| + base::Passed(&fd), |
| + options, |
| + callback)); |
| + } else { |
| + linked_ptr<ConnectionRequest> request(new ConnectionRequest()); |
| + request->device_path = device_path; |
| + request->fd = fd.Pass(); |
| + request->options = options; |
| + request->callback = callback; |
| + |
| + connection_request_queue_.push(request); |
| + VLOG(1) << object_path_.value() << ": Connection is now pending."; |
| + if (accept_request_) { |
| + AcceptConnectionRequest(); |
| + } |
| + } |
| +} |
| + |
| +void BluetoothSocketChromeOS::RequestDisconnection( |
| + const dbus::ObjectPath& device_path, |
| + const ConfirmationCallback& callback) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + VLOG(1) << object_path_.value() << ": Request disconnection"; |
| + callback.Run(SUCCESS); |
| +} |
| + |
| +void BluetoothSocketChromeOS::Cancel() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + VLOG(1) << object_path_.value() << ": Cancel"; |
| + |
| + if (!connection_request_queue_.size()) |
| + return; |
| + |
| + // If the front request is being accepted mark it as cancelled, otherwise |
| + // just pop it from the queue. |
| + linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); |
| + if (!request->accepting) { |
| + request->cancelled = true; |
| + } else { |
| + connection_request_queue_.pop(); |
| + } |
| +} |
| + |
| +void BluetoothSocketChromeOS::AcceptConnectionRequest() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK(accept_request_.get()); |
| + DCHECK(connection_request_queue_.size() >= 1); |
| + |
| + VLOG(1) << object_path_.value() << ": Accepting pending connection."; |
| + |
| + linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); |
| + request->accepting = true; |
| + |
| + BluetoothDeviceChromeOS* device = |
| + static_cast<BluetoothAdapterChromeOS*>(adapter_.get())-> |
| + GetDeviceWithPath(request->device_path); |
| + DCHECK(device); |
| + |
| + scoped_refptr<BluetoothSocketChromeOS> client_socket = |
| + BluetoothSocketChromeOS::CreateBluetoothSocket( |
| + ui_task_runner(), |
| + socket_thread(), |
| + net_log(), |
| + source()); |
| + |
| + client_socket->device_address_ = device->GetAddress(); |
| + client_socket->device_path_ = request->device_path; |
| + client_socket->uuid_ = uuid_; |
| + |
| + socket_thread()->task_runner()->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &BluetoothSocketChromeOS::DoNewConnection, |
| + client_socket, |
| + request->device_path, |
| + base::Passed(&request->fd), |
| + request->options, |
| + base::Bind(&BluetoothSocketChromeOS::OnNewConnection, |
| + this, |
| + client_socket, |
| + request->callback))); |
| +} |
| + |
| +void BluetoothSocketChromeOS::DoNewConnection( |
| + const dbus::ObjectPath& device_path, |
| + scoped_ptr<dbus::FileDescriptor> fd, |
| + const BluetoothProfileServiceProvider::Delegate::Options& options, |
| + const ConfirmationCallback& callback) { |
| DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
| base::ThreadRestrictions::AssertIOAllowed(); |
| - DCHECK(fd->is_valid()); |
| + fd->CheckValidity(); |
| + |
| + VLOG(1) << object_path_.value() << ": Validity check complete."; |
| + if (!fd->is_valid()) { |
| + ui_task_runner()->PostTask(FROM_HERE, |
| + base::Bind(callback, REJECTED));; |
| + return; |
| + } |
| if (tcp_socket()) { |
| - error_callback.Run(kSocketAlreadyConnected); |
| + LOG(WARNING) << object_path_.value() << ": Already connected"; |
| + ui_task_runner()->PostTask(FROM_HERE, |
| + base::Bind(callback, REJECTED));; |
| return; |
| } |
| @@ -96,13 +495,96 @@ void BluetoothSocketChromeOS::DoConnect( |
| int net_result = tcp_socket()->AdoptConnectedSocket(fd->value(), |
| net::IPEndPoint()); |
| if (net_result != net::OK) { |
| - error_callback.Run("Error connecting to socket: " + |
| - std::string(net::ErrorToString(net_result))); |
| + LOG(WARNING) << object_path_.value() << ": Error adopting socket: " |
| + << std::string(net::ErrorToString(net_result)); |
| + ui_task_runner()->PostTask(FROM_HERE, |
| + base::Bind(callback, REJECTED));; |
| return; |
| } |
| fd->TakeValue(); |
| - success_callback.Run(); |
| + ui_task_runner()->PostTask(FROM_HERE, |
| + base::Bind(callback, SUCCESS));; |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnNewConnection( |
| + scoped_refptr<BluetoothSocket> socket, |
| + const ConfirmationCallback& callback, |
| + Status status) { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK(accept_request_.get()); |
| + DCHECK(connection_request_queue_.size() >= 1); |
| + |
| + linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); |
| + if (status == SUCCESS && !request->cancelled) { |
| + BluetoothDeviceChromeOS* device = |
| + static_cast<BluetoothAdapterChromeOS*>(adapter_.get())-> |
| + GetDeviceWithPath(request->device_path); |
| + DCHECK(device); |
| + |
| + accept_request_->success_callback.Run(device, socket); |
| + } else { |
| + accept_request_->error_callback.Run(kAcceptFailed); |
| + } |
| + |
| + accept_request_.reset(NULL); |
| + connection_request_queue_.pop(); |
| + |
| + callback.Run(status); |
| +} |
| + |
| +void BluetoothSocketChromeOS::DoCloseListening() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + |
| + if (accept_request_) { |
| + accept_request_->error_callback.Run( |
| + net::ErrorToString(net::ERR_CONNECTION_CLOSED)); |
| + accept_request_.reset(NULL); |
| + } |
| + |
| + while (connection_request_queue_.size() > 0) { |
| + linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); |
| + request->callback.Run(REJECTED); |
| + connection_request_queue_.pop(); |
| + } |
| +} |
| + |
| +void BluetoothSocketChromeOS::UnregisterProfile() { |
| + DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| + DCHECK(!object_path_.value().empty()); |
| + DCHECK(profile_.get()); |
| + |
| + VLOG(1) << object_path_.value() << ": Unregister profile"; |
| + DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> |
| + UnregisterProfile( |
| + object_path_, |
| + base::Bind(&BluetoothSocketChromeOS::OnUnregisterProfile, |
| + this, |
| + object_path_), |
| + base::Bind(&BluetoothSocketChromeOS::OnUnregisterProfileError, |
| + this, |
| + object_path_)); |
| + |
| + profile_.reset(); |
| + object_path_ = dbus::ObjectPath(""); |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnUnregisterProfile( |
| + const dbus::ObjectPath& object_path) { |
| + VLOG(1) << object_path.value() << ": Profile unregistered"; |
| +} |
| + |
| +void BluetoothSocketChromeOS::OnUnregisterProfileError( |
| + const dbus::ObjectPath& object_path, |
| + const std::string& error_name, |
| + const std::string& error_message) { |
| + // It's okay if the profile doesn't exist, it means we haven't registered it |
| + // yet. |
| + if (error_name == bluetooth_profile_manager::kErrorDoesNotExist) |
| + return; |
| + |
| + LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: " |
| + << error_name << ": " << error_message; |
| } |
| } // namespace chromeos |