summaryrefslogtreecommitdiffstats
path: root/chromeos/dbus
diff options
context:
space:
mode:
authorkeybuk@chromium.org <keybuk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-09 03:49:18 +0000
committerkeybuk@chromium.org <keybuk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-09 03:49:18 +0000
commite882d2cdf5ed5337d68f2b32ba0f885725ca8b3f (patch)
treec4ca06e4ad129b16aa1f04753db7ac4e98a55240 /chromeos/dbus
parentdc5d179b1e34c9147630adc9d20e43e7986f7feb (diff)
downloadchromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.zip
chromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.tar.gz
chromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.tar.bz2
Bluetooth: Profile support for Chrome OS
Implement support for the BluetoothProfile API for the BlueZ 5.x stack on Chrome OS, including BluetoothSocket support. BUG=229636 TEST=device_unittests Review URL: https://chromiumcodereview.appspot.com/14487002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199095 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/dbus')
-rw-r--r--chromeos/dbus/experimental_bluetooth_profile_service_provider.cc8
-rw-r--r--chromeos/dbus/experimental_bluetooth_profile_service_provider.h16
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.cc153
-rw-r--r--chromeos/dbus/fake_bluetooth_device_client.h12
-rw-r--r--chromeos/dbus/fake_bluetooth_profile_manager_client.cc66
-rw-r--r--chromeos/dbus/fake_bluetooth_profile_manager_client.h32
-rw-r--r--chromeos/dbus/fake_bluetooth_profile_service_provider.cc18
-rw-r--r--chromeos/dbus/fake_bluetooth_profile_service_provider.h5
8 files changed, 292 insertions, 18 deletions
diff --git a/chromeos/dbus/experimental_bluetooth_profile_service_provider.cc b/chromeos/dbus/experimental_bluetooth_profile_service_provider.cc
index a58c8bc..2b2384f 100644
--- a/chromeos/dbus/experimental_bluetooth_profile_service_provider.cc
+++ b/chromeos/dbus/experimental_bluetooth_profile_service_provider.cc
@@ -113,10 +113,10 @@ class ExperimentalBluetoothProfileServiceProviderImpl
dbus::MessageReader reader(method_call);
dbus::ObjectPath device_path;
- dbus::FileDescriptor fd;
+ scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor());
dbus::MessageReader array_reader(NULL);
if (!reader.PopObjectPath(&device_path) ||
- !reader.PopFileDescriptor(&fd) ||
+ !reader.PopFileDescriptor(fd.get()) ||
!reader.PopArray(&array_reader)) {
LOG(WARNING) << "NewConnection called with incorrect paramters: "
<< method_call->ToString();
@@ -145,9 +145,7 @@ class ExperimentalBluetoothProfileServiceProviderImpl
method_call,
response_sender);
- delegate_->NewConnection(device_path, &fd, options, callback);
-
- response_sender.Run(dbus::Response::FromMethodCall(method_call));
+ delegate_->NewConnection(device_path, fd.Pass(), options, callback);
}
// Called by dbus:: when the Bluetooth daemon is about to disconnect the
diff --git a/chromeos/dbus/experimental_bluetooth_profile_service_provider.h b/chromeos/dbus/experimental_bluetooth_profile_service_provider.h
index 71e09d5..4649696 100644
--- a/chromeos/dbus/experimental_bluetooth_profile_service_provider.h
+++ b/chromeos/dbus/experimental_bluetooth_profile_service_provider.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
#include "chromeos/chromeos_export.h"
#include "dbus/bus.h"
#include "dbus/file_descriptor.h"
@@ -74,13 +75,16 @@ class CHROMEOS_EXPORT ExperimentalBluetoothProfileServiceProvider {
//
// A file descriptor for the connection socket is provided in |fd|, and
// details about the specific implementation of the profile in |options|.
- // The delegate should take the value and ownership
-
- // The file descriptor is owned by the delegate after this call so must be
- // cleaned up if the connection is cancelled or rejected, the |options|
- // structure is not so information out of it must be copied if required.
+ //
+ // IMPORTANT: Ownership of the file descriptor object |fd| is passed to
+ // the delegate by this call. The delegate is responsible for checking the
+ // validity of |fd| on a thread where I/O is permitted before taking the
+ // value. If the value is not taken, the file descriptor is closed.
+ //
+ // Ownership of |options| is NOT passed so information out of it must be
+ // copied if required.
virtual void NewConnection(const dbus::ObjectPath& device_path,
- dbus::FileDescriptor* fd,
+ scoped_ptr<dbus::FileDescriptor> fd,
const Options& options,
const ConfirmationCallback& callback) = 0;
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc
index 4d3e189..b1ed840 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.cc
+++ b/chromeos/dbus/fake_bluetooth_device_client.cc
@@ -4,6 +4,11 @@
#include "chromeos/dbus/fake_bluetooth_device_client.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
#include <algorithm>
#include <map>
#include <string>
@@ -12,14 +17,19 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
+#include "base/threading/worker_pool.h"
#include "base/time.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
#include "chromeos/dbus/fake_bluetooth_input_client.h"
+#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
+#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
+#include "dbus/file_descriptor.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -28,6 +38,30 @@ namespace {
// Default interval between simulated events.
const int kSimulationIntervalMs = 750;
+
+void SimulatedProfileSocket(int fd) {
+ // Simulate a server-side socket of a profile; read data from the socket,
+ // write it back, and then close.
+ char buf[1024];
+ ssize_t len;
+ ssize_t count;
+
+ len = read(fd, buf, sizeof buf);
+ if (len < 0) {
+ close(fd);
+ return;
+ }
+
+ count = len;
+ len = write(fd, buf, count);
+ if (len < 0) {
+ close(fd);
+ return;
+ }
+
+ close(fd);
+}
+
}
namespace chromeos {
@@ -267,7 +301,63 @@ void FakeBluetoothDeviceClient::ConnectProfile(
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid;
- error_callback.Run(kNoResponseError, "");
+
+ FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothProfileManagerClient*>(
+ DBusThreadManager::Get()->
+ GetExperimentalBluetoothProfileManagerClient());
+ FakeBluetoothProfileServiceProvider* profile_service_provider =
+ fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
+ if (profile_service_provider == NULL) {
+ error_callback.Run(kNoResponseError, "Missing profile");
+ return;
+ }
+
+ // Make a socket pair of a compatible type with the type used by Bluetooth;
+ // spin up a thread to simulate the server side and wrap the client side in
+ // a D-Bus file descriptor object.
+ int socket_type = SOCK_STREAM;
+ if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid)
+ socket_type = SOCK_SEQPACKET;
+
+ int fds[2];
+ if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) {
+ error_callback.Run(kNoResponseError, "socketpair call failed");
+ return;
+ }
+
+ int args;
+ args = fcntl(fds[1], F_GETFL, NULL);
+ if (args < 0) {
+ error_callback.Run(kNoResponseError, "failed to get socket flags");
+ return;
+ }
+
+ args |= O_NONBLOCK;
+ if (fcntl(fds[1], F_SETFL, args) < 0) {
+ error_callback.Run(kNoResponseError, "failed to set socket non-blocking");
+ return;
+ }
+
+ base::WorkerPool::GetTaskRunner(false)->PostTask(
+ FROM_HERE,
+ base::Bind(&SimulatedProfileSocket,
+ fds[0]));
+
+ scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));
+
+ // Post the new connection to the service provider.
+ ExperimentalBluetoothProfileServiceProvider::Delegate::Options options;
+
+ profile_service_provider->NewConnection(
+ object_path,
+ fd.Pass(),
+ options,
+ base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
+ base::Unretained(this),
+ object_path,
+ callback,
+ error_callback));
}
void FakeBluetoothDeviceClient::DisconnectProfile(
@@ -276,7 +366,25 @@ void FakeBluetoothDeviceClient::DisconnectProfile(
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid;
- error_callback.Run(kNoResponseError, "");
+
+ FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothProfileManagerClient*>(
+ DBusThreadManager::Get()->
+ GetExperimentalBluetoothProfileManagerClient());
+ FakeBluetoothProfileServiceProvider* profile_service_provider =
+ fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
+ if (profile_service_provider == NULL) {
+ error_callback.Run(kNoResponseError, "Missing profile");
+ return;
+ }
+
+ profile_service_provider->RequestDisconnection(
+ object_path,
+ base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
+ base::Unretained(this),
+ object_path,
+ callback,
+ error_callback));
}
void FakeBluetoothDeviceClient::Pair(
@@ -920,4 +1028,45 @@ void FakeBluetoothDeviceClient::SimulateKeypress(
}
}
+void FakeBluetoothDeviceClient::ConnectionCallback(
+ const dbus::ObjectPath& object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback,
+ ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) {
+ VLOG(1) << "ConnectionCallback: " << object_path.value();
+
+ if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) {
+ callback.Run();
+ } else if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) {
+ // TODO(keybuk): tear down this side of the connection
+ error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled");
+ } else if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) {
+ // TODO(keybuk): tear down this side of the connection
+ error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected");
+ }
+}
+
+void FakeBluetoothDeviceClient::DisconnectionCallback(
+ const dbus::ObjectPath& object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback,
+ ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) {
+ VLOG(1) << "DisconnectionCallback: " << object_path.value();
+
+ if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) {
+ // TODO(keybuk): tear down this side of the connection
+ callback.Run();
+ } else if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) {
+ error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled");
+ } else if (status ==
+ ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) {
+ error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected");
+ }
+}
+
} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/chromeos/dbus/fake_bluetooth_device_client.h
index 9ce85b2..6a90863 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.h
+++ b/chromeos/dbus/fake_bluetooth_device_client.h
@@ -15,6 +15,7 @@
#include "chromeos/dbus/dbus_client_implementation_type.h"
#include "chromeos/dbus/experimental_bluetooth_agent_service_provider.h"
#include "chromeos/dbus/experimental_bluetooth_device_client.h"
+#include "chromeos/dbus/experimental_bluetooth_profile_service_provider.h"
#include "dbus/object_path.h"
#include "dbus/property.h"
@@ -186,6 +187,17 @@ class CHROMEOS_EXPORT FakeBluetoothDeviceClient
const base::Closure& callback,
const ErrorCallback& error_callback);
+ void ConnectionCallback(
+ const dbus::ObjectPath& object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback,
+ ExperimentalBluetoothProfileServiceProvider::Delegate::Status status);
+ void DisconnectionCallback(
+ const dbus::ObjectPath& object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback,
+ ExperimentalBluetoothProfileServiceProvider::Delegate::Status status);
+
// List of observers interested in event notifications from us.
ObserverList<Observer> observers_;
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc b/chromeos/dbus/fake_bluetooth_profile_manager_client.cc
index 0547e4b1..2f2fb8e 100644
--- a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc
+++ b/chromeos/dbus/fake_bluetooth_profile_manager_client.cc
@@ -4,8 +4,12 @@
#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
+#include <map>
+#include <string>
+
#include "base/bind.h"
#include "base/logging.h"
+#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
@@ -14,6 +18,11 @@
namespace chromeos {
+const char FakeBluetoothProfileManagerClient::kL2capUuid[] =
+ "4d995052-33cc-4fdf-b446-75f32942a076";
+const char FakeBluetoothProfileManagerClient::kRfcommUuid[] =
+ "3f6d6dbf-a6ad-45fc-9653-47dc912ef70e";
+
FakeBluetoothProfileManagerClient::FakeBluetoothProfileManagerClient() {
}
@@ -27,7 +36,23 @@ void FakeBluetoothProfileManagerClient::RegisterProfile(
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "RegisterProfile: " << profile_path.value() << ": " << uuid;
- callback.Run();
+
+ // check options for channel & psm
+
+ ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path);
+ if (iter == service_provider_map_.end()) {
+ error_callback.Run(bluetooth_adapter::kErrorFailed,
+ "No profile created");
+ } else {
+ ProfileMap::iterator piter = profile_map_.find(uuid);
+ if (piter != profile_map_.end()) {
+ error_callback.Run(bluetooth_adapter::kErrorAlreadyExists,
+ "Profile already registered");
+ } else {
+ profile_map_[uuid] = profile_path;
+ callback.Run();
+ }
+ }
}
void FakeBluetoothProfileManagerClient::UnregisterProfile(
@@ -35,7 +60,44 @@ void FakeBluetoothProfileManagerClient::UnregisterProfile(
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "UnregisterProfile: " << profile_path.value();
- callback.Run();
+
+ ServiceProviderMap::iterator iter = service_provider_map_.find(profile_path);
+ if (iter != service_provider_map_.end()) {
+ error_callback.Run(bluetooth_adapter::kErrorFailed,
+ "Profile still registered");
+ } else {
+ for (ProfileMap::iterator piter = profile_map_.begin();
+ piter != profile_map_.end(); ++piter) {
+ if (piter->second == profile_path) {
+ profile_map_.erase(piter);
+ break;
+ }
+ }
+
+ callback.Run();
+ }
+}
+
+void FakeBluetoothProfileManagerClient::RegisterProfileServiceProvider(
+ FakeBluetoothProfileServiceProvider* service_provider) {
+ service_provider_map_[service_provider->object_path_] = service_provider;
+}
+
+void FakeBluetoothProfileManagerClient::UnregisterProfileServiceProvider(
+ FakeBluetoothProfileServiceProvider* service_provider) {
+ ServiceProviderMap::iterator iter =
+ service_provider_map_.find(service_provider->object_path_);
+ if (iter != service_provider_map_.end() && iter->second == service_provider)
+ service_provider_map_.erase(iter);
+}
+
+FakeBluetoothProfileServiceProvider*
+FakeBluetoothProfileManagerClient::GetProfileServiceProvider(
+ const std::string& uuid) {
+ ProfileMap::iterator iter = profile_map_.find(uuid);
+ if (iter == profile_map_.end())
+ return NULL;
+ return service_provider_map_[iter->second];
}
} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.h b/chromeos/dbus/fake_bluetooth_profile_manager_client.h
index e3cfcd4..bba6732 100644
--- a/chromeos/dbus/fake_bluetooth_profile_manager_client.h
+++ b/chromeos/dbus/fake_bluetooth_profile_manager_client.h
@@ -5,6 +5,9 @@
#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
#define CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
+#include <map>
+#include <string>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/observer_list.h"
@@ -16,6 +19,8 @@
namespace chromeos {
+class FakeBluetoothProfileServiceProvider;
+
// FakeBluetoothProfileManagerClient simulates the behavior of the Bluetooth
// Daemon's profile manager object and is used both in test cases in place of a
// mock and on the Linux desktop.
@@ -34,6 +39,33 @@ class CHROMEOS_EXPORT FakeBluetoothProfileManagerClient
virtual void UnregisterProfile(const dbus::ObjectPath& profile_path,
const base::Closure& callback,
const ErrorCallback& error_callback) OVERRIDE;
+
+ // Register, unregister and retrieve pointers to profile server providers.
+ void RegisterProfileServiceProvider(
+ FakeBluetoothProfileServiceProvider* service_provider);
+ void UnregisterProfileServiceProvider(
+ FakeBluetoothProfileServiceProvider* service_provider);
+ FakeBluetoothProfileServiceProvider* GetProfileServiceProvider(
+ const std::string& uuid);
+
+ // UUIDs recognised for testing.
+ static const char kL2capUuid[];
+ static const char kRfcommUuid[];
+
+ private:
+ // Map of a D-Bus object path to the FakeBluetoothProfileServiceProvider
+ // registered for it; maintained by RegisterProfileServiceProvider() and
+ // UnregisterProfileServiceProvicer() called by the constructor and
+ // destructor of FakeBluetoothProfileServiceProvider.
+ typedef std::map<dbus::ObjectPath, FakeBluetoothProfileServiceProvider*>
+ ServiceProviderMap;
+ ServiceProviderMap service_provider_map_;
+
+ // Map of Profile UUID to the D-Bus object path of the service provider
+ // in |service_provider_map_|. Maintained by RegisterProfile() and
+ // UnregisterProfile() in response to BluetoothProfile methods.
+ typedef std::map<std::string, dbus::ObjectPath> ProfileMap;
+ ProfileMap profile_map_;
};
} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc b/chromeos/dbus/fake_bluetooth_profile_service_provider.cc
index 999da6f..a021464 100644
--- a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc
+++ b/chromeos/dbus/fake_bluetooth_profile_service_provider.cc
@@ -4,6 +4,8 @@
#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
#include "dbus/object_path.h"
namespace chromeos {
@@ -14,10 +16,22 @@ FakeBluetoothProfileServiceProvider::FakeBluetoothProfileServiceProvider(
: object_path_(object_path),
delegate_(delegate) {
VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value();
+
+ FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothProfileManagerClient*>(
+ DBusThreadManager::Get()->
+ GetExperimentalBluetoothProfileManagerClient());
+ fake_bluetooth_profile_manager_client->RegisterProfileServiceProvider(this);
}
FakeBluetoothProfileServiceProvider::~FakeBluetoothProfileServiceProvider() {
VLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value();
+
+ FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothProfileManagerClient*>(
+ DBusThreadManager::Get()->
+ GetExperimentalBluetoothProfileManagerClient());
+ fake_bluetooth_profile_manager_client->UnregisterProfileServiceProvider(this);
}
void FakeBluetoothProfileServiceProvider::Release() {
@@ -27,12 +41,12 @@ void FakeBluetoothProfileServiceProvider::Release() {
void FakeBluetoothProfileServiceProvider::NewConnection(
const dbus::ObjectPath& device_path,
- dbus::FileDescriptor* fd,
+ scoped_ptr<dbus::FileDescriptor> fd,
const Delegate::Options& options,
const Delegate::ConfirmationCallback& callback) {
VLOG(1) << object_path_.value() << ": NewConnection for "
<< device_path.value();
- delegate_->NewConnection(device_path, fd, options, callback);
+ delegate_->NewConnection(device_path, fd.Pass(), options, callback);
}
void FakeBluetoothProfileServiceProvider::RequestDisconnection(
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.h b/chromeos/dbus/fake_bluetooth_profile_service_provider.h
index 5af7382..c886f71 100644
--- a/chromeos/dbus/fake_bluetooth_profile_service_provider.h
+++ b/chromeos/dbus/fake_bluetooth_profile_service_provider.h
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_client_implementation_type.h"
#include "chromeos/dbus/experimental_bluetooth_profile_service_provider.h"
@@ -31,7 +32,7 @@ class CHROMEOS_EXPORT FakeBluetoothProfileServiceProvider
virtual void Release();
virtual void NewConnection(
const dbus::ObjectPath& device_path,
- dbus::FileDescriptor* fd,
+ scoped_ptr<dbus::FileDescriptor> fd,
const Delegate::Options& options,
const Delegate::ConfirmationCallback& callback);
virtual void RequestDisconnection(
@@ -40,6 +41,8 @@ class CHROMEOS_EXPORT FakeBluetoothProfileServiceProvider
virtual void Cancel();
private:
+ friend class FakeBluetoothProfileManagerClient;
+
// D-Bus object path we are faking.
dbus::ObjectPath object_path_;