Migrate chrome.bluetooth API backend to use device::BluetoothDiscoverySession.

Modified chrome.bluetooth API code to use the new discovery session API for
device discovery.

This CL is the same as r255262 which was reverted due to a memory leak. The leak
has been addressed in this patch.

BUG=346982,349942
TEST=1. Run unit_tests and browser_tests with LSan.
     2. Use multiple running extension instances with the bluetooth permission
        and check for the following behavior:
        - Only one session per extension. Calling chrome.bluetooth.stopDiscovery
          from one running app should fail if that app never called
          chrome.bluetooth.startDiscovery.
        - An app's discovery sessions should get cleaned up if that app crashes
          or unloads.
        - Use bt_console and run "power off". This should cause all discovery
          sessions that have been assigned to apps to get marked as inactive.
          Verify by requesting a new discovery session from apps, which should
          succeed.

Review URL: https://codereview.chromium.org/189463002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255609 0039d316-1c4b-4281-b951-d872f2087c98
parent a2093312
......@@ -636,24 +636,18 @@ void BluetoothStartDiscoveryFunction::OnSuccessCallback() {
void BluetoothStartDiscoveryFunction::OnErrorCallback() {
SetError(kStartDiscoveryFailed);
GetEventRouter(browser_context())->SetResponsibleForDiscovery(false);
SendResponse(false);
GetEventRouter(browser_context())->OnListenerRemoved();
}
bool BluetoothStartDiscoveryFunction::DoWork(
scoped_refptr<BluetoothAdapter> adapter) {
GetEventRouter(browser_context())->SetSendDiscoveryEvents(true);
// If this profile is already discovering devices, there should be nothing
// else to do.
if (!GetEventRouter(browser_context())->IsResponsibleForDiscovery()) {
GetEventRouter(browser_context())->SetResponsibleForDiscovery(true);
GetEventRouter(browser_context())->OnListenerAdded();
adapter->StartDiscovering(
base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this),
base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this));
}
GetEventRouter(browser_context())->OnListenerAdded();
GetEventRouter(browser_context())->StartDiscoverySession(
adapter,
extension_id(),
base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this),
base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this));
return true;
}
......@@ -665,19 +659,17 @@ void BluetoothStopDiscoveryFunction::OnSuccessCallback() {
void BluetoothStopDiscoveryFunction::OnErrorCallback() {
SetError(kStopDiscoveryFailed);
GetEventRouter(browser_context())->SetResponsibleForDiscovery(true);
SendResponse(false);
GetEventRouter(browser_context())->OnListenerRemoved();
}
bool BluetoothStopDiscoveryFunction::DoWork(
scoped_refptr<BluetoothAdapter> adapter) {
GetEventRouter(browser_context())->SetSendDiscoveryEvents(false);
if (GetEventRouter(browser_context())->IsResponsibleForDiscovery()) {
adapter->StopDiscovering(
base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this),
base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this));
}
GetEventRouter(browser_context())->StopDiscoverySession(
adapter,
extension_id(),
base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this),
base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this));
return true;
}
......
......@@ -17,16 +17,19 @@
#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
#include "device/bluetooth/test/mock_bluetooth_profile.h"
#include "device/bluetooth/test/mock_bluetooth_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
using device::BluetoothAdapter;
using device::BluetoothDevice;
using device::BluetoothDiscoverySession;
using device::BluetoothOutOfBandPairingData;
using device::BluetoothProfile;
using device::MockBluetoothAdapter;
using device::MockBluetoothDevice;
using device::MockBluetoothDiscoverySession;
using device::MockBluetoothProfile;
using extensions::Extension;
......@@ -65,6 +68,17 @@ class BluetoothApiTest : public ExtensionApiTest {
false /* paired */, false /* connected */));
}
void DiscoverySessionCallback(
const BluetoothAdapter::DiscoverySessionCallback& callback,
const BluetoothAdapter::ErrorCallback& error_callback) {
if (mock_session_.get()) {
callback.Run(
scoped_ptr<BluetoothDiscoverySession>(mock_session_.release()));
return;
}
error_callback.Run();
}
template <class T>
T* setupFunction(T* function) {
function->set_extension(empty_extension_.get());
......@@ -74,6 +88,7 @@ class BluetoothApiTest : public ExtensionApiTest {
protected:
testing::StrictMock<MockBluetoothAdapter>* mock_adapter_;
scoped_ptr<testing::NiceMock<MockBluetoothDiscoverySession> > mock_session_;
scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device1_;
scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device2_;
scoped_ptr<testing::NiceMock<MockBluetoothProfile> > profile1_;
......@@ -129,18 +144,11 @@ static bool CallClosure(const base::Closure& callback) {
return true;
}
static void CallDiscoveryCallback(
const base::Closure& callback,
const BluetoothAdapter::ErrorCallback& error_callback) {
static void StopDiscoverySessionCallback(const base::Closure& callback,
const base::Closure& error_callback) {
callback.Run();
}
static void CallDiscoveryErrorCallback(
const base::Closure& callback,
const BluetoothAdapter::ErrorCallback& error_callback) {
error_callback.Run();
}
static void CallOutOfBandPairingDataCallback(
const BluetoothAdapter::BluetoothOutOfBandPairingDataCallback& callback,
const BluetoothAdapter::ErrorCallback& error_callback) {
......@@ -316,9 +324,12 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, SetOutOfBandPairingData) {
}
IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Discovery) {
// Try with a failure to start
EXPECT_CALL(*mock_adapter_, StartDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryErrorCallback));
// Try with a failure to start. This will return an error as we haven't
// initialied a session object.
EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_))
.WillOnce(
testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback));
// StartDiscovery failure will remove the adapter that is no longer used.
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_));
scoped_refptr<api::BluetoothStartDiscoveryFunction> start_function;
......@@ -327,19 +338,28 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Discovery) {
utils::RunFunctionAndReturnError(start_function.get(), "[]", browser()));
ASSERT_FALSE(error.empty());
// Reset for a successful start
// Reset the adapter and initiate a discovery session. The ownership of the
// mock session will be passed to the event router.
ASSERT_FALSE(mock_session_.get());
SetUpMockAdapter();
EXPECT_CALL(*mock_adapter_, StartDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
// Create a mock session to be returned as a result. Get a handle to it as
// its ownership will be passed and |mock_session_| will be reset.
mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>());
MockBluetoothDiscoverySession* session = mock_session_.get();
EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_))
.WillOnce(
testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback));
start_function = setupFunction(new api::BluetoothStartDiscoveryFunction);
(void)
utils::RunFunctionAndReturnError(start_function.get(), "[]", browser());
// Reset to try stopping
// End the discovery session. The StopDiscovery function should succeed.
testing::Mock::VerifyAndClearExpectations(mock_adapter_);
EXPECT_CALL(*mock_adapter_, StopDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true));
EXPECT_CALL(*session, Stop(testing::_, testing::_))
.WillOnce(testing::Invoke(StopDiscoverySessionCallback));
// StopDiscovery success will remove the adapter that is no longer used.
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_));
scoped_refptr<api::BluetoothStopDiscoveryFunction> stop_function;
......@@ -347,10 +367,10 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Discovery) {
(void) utils::RunFunctionAndReturnSingleResult(
stop_function.get(), "[]", browser());
// Reset to try stopping with an error
// Reset the adapter. Simulate failure for stop discovery. The event router
// still owns the session. Make it appear inactive.
SetUpMockAdapter();
EXPECT_CALL(*mock_adapter_, StopDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryErrorCallback));
EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(false));
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_));
stop_function = setupFunction(new api::BluetoothStopDiscoveryFunction);
error =
......@@ -360,10 +380,14 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, Discovery) {
}
IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DiscoveryCallback) {
EXPECT_CALL(*mock_adapter_, StartDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
EXPECT_CALL(*mock_adapter_, StopDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>());
MockBluetoothDiscoverySession* session = mock_session_.get();
EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_))
.WillOnce(
testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback));
EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true));
EXPECT_CALL(*session, Stop(testing::_, testing::_))
.WillOnce(testing::Invoke(StopDiscoverySessionCallback));
ResultCatcher catcher;
catcher.RestrictToProfile(browser()->profile());
......@@ -408,17 +432,22 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DiscoveryInProgress) {
ResultCatcher catcher;
catcher.RestrictToProfile(browser()->profile());
EXPECT_CALL(*mock_adapter_, StartDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
EXPECT_CALL(*mock_adapter_, StopDiscovering(testing::_, testing::_))
.WillOnce(testing::Invoke(CallDiscoveryCallback));
mock_session_.reset(new testing::NiceMock<MockBluetoothDiscoverySession>());
MockBluetoothDiscoverySession* session = mock_session_.get();
EXPECT_CALL(*mock_adapter_, StartDiscoverySession(testing::_, testing::_))
.WillOnce(
testing::Invoke(this, &BluetoothApiTest::DiscoverySessionCallback));
EXPECT_CALL(*session, IsActive()).WillOnce(testing::Return(true));
EXPECT_CALL(*session, Stop(testing::_, testing::_))
.WillOnce(testing::Invoke(StopDiscoverySessionCallback));
ExtensionTestMessageListener discovery_started("ready", true);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth/discovery_in_progress")));
EXPECT_TRUE(discovery_started.WaitUntilSatisfied());
// This should be received in addition to the cached device above.
// Only this should be received. No additional notification should be sent for
// devices discovered before the discovery session started.
event_router()->DeviceAdded(mock_adapter_, device2_.get());
discovery_started.Reply("go");
......
......@@ -22,6 +22,7 @@
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_profile.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "extensions/browser/event_router.h"
......@@ -45,9 +46,7 @@ struct ExtensionBluetoothProfileRecord {
ExtensionBluetoothEventRouter::ExtensionBluetoothEventRouter(
content::BrowserContext* context)
: send_discovery_events_(false),
responsible_for_discovery_(false),
browser_context_(context),
: browser_context_(context),
adapter_(NULL),
num_event_listeners_(0),
next_socket_id_(1),
......@@ -72,6 +71,11 @@ ExtensionBluetoothEventRouter::~ExtensionBluetoothEventRouter() {
++iter) {
iter->second.profile->Unregister();
}
for (DiscoverySessionMap::iterator iter = discovery_session_map_.begin();
iter != discovery_session_map_.end();
++iter) {
delete iter->second;
}
}
bool ExtensionBluetoothEventRouter::IsBluetoothSupported() const {
......@@ -145,6 +149,50 @@ bool ExtensionBluetoothEventRouter::HasProfile(const std::string& uuid) const {
return bluetooth_profile_map_.find(uuid) != bluetooth_profile_map_.end();
}
void ExtensionBluetoothEventRouter::StartDiscoverySession(
device::BluetoothAdapter* adapter,
const std::string& extension_id,
const base::Closure& callback,
const base::Closure& error_callback) {
if (adapter != adapter_.get()) {
error_callback.Run();
return;
}
DiscoverySessionMap::iterator iter =
discovery_session_map_.find(extension_id);
if (iter != discovery_session_map_.end() && iter->second->IsActive()) {
DVLOG(1) << "An active discovery session exists for extension.";
error_callback.Run();
return;
}
adapter->StartDiscoverySession(
base::Bind(&ExtensionBluetoothEventRouter::OnStartDiscoverySession,
weak_ptr_factory_.GetWeakPtr(),
extension_id,
callback),
error_callback);
}
void ExtensionBluetoothEventRouter::StopDiscoverySession(
device::BluetoothAdapter* adapter,
const std::string& extension_id,
const base::Closure& callback,
const base::Closure& error_callback) {
if (adapter != adapter_.get()) {
error_callback.Run();
return;
}
DiscoverySessionMap::iterator iter =
discovery_session_map_.find(extension_id);
if (iter == discovery_session_map_.end() || !iter->second->IsActive()) {
DVLOG(1) << "No active discovery session exists for extension.";
error_callback.Run();
return;
}
device::BluetoothDiscoverySession* session = iter->second;
session->Stop(callback, error_callback);
}
device::BluetoothProfile* ExtensionBluetoothEventRouter::GetProfile(
const std::string& uuid) const {
BluetoothProfileMap::const_iterator iter = bluetooth_profile_map_.find(uuid);
......@@ -162,29 +210,6 @@ ExtensionBluetoothEventRouter::GetSocket(int id) {
return socket_entry->second.socket;
}
void ExtensionBluetoothEventRouter::SetResponsibleForDiscovery(
bool responsible) {
responsible_for_discovery_ = responsible;
}
bool ExtensionBluetoothEventRouter::IsResponsibleForDiscovery() const {
return responsible_for_discovery_;
}
void ExtensionBluetoothEventRouter::SetSendDiscoveryEvents(bool should_send) {
// At the transition into sending devices, also send past devices that
// were discovered as they will not be discovered again.
if (should_send && !send_discovery_events_) {
for (DeviceList::const_iterator i = discovered_devices_.begin();
i != discovered_devices_.end(); ++i) {
DispatchDeviceEvent(extensions::event_names::kBluetoothOnDeviceDiscovered,
**i);
}
}
send_discovery_events_ = should_send;
}
void ExtensionBluetoothEventRouter::DispatchDeviceEvent(
const std::string& event_name, const bluetooth::Device& device) {
scoped_ptr<base::ListValue> args(new base::ListValue());
......@@ -243,9 +268,19 @@ void ExtensionBluetoothEventRouter::AdapterDiscoveringChanged(
}
if (!discovering) {
send_discovery_events_ = false;
responsible_for_discovery_ = false;
discovered_devices_.clear();
// If any discovery sessions are inactive, clean them up.
DiscoverySessionMap active_session_map;
for (DiscoverySessionMap::iterator iter = discovery_session_map_.begin();
iter != discovery_session_map_.end();
++iter) {
device::BluetoothDiscoverySession* session = iter->second;
if (session->IsActive()) {
active_session_map[iter->first] = session;
continue;
}
delete session;
}
discovery_session_map_.swap(active_session_map);
}
DispatchAdapterStateEvent();
......@@ -259,17 +294,11 @@ void ExtensionBluetoothEventRouter::DeviceAdded(
return;
}
bluetooth::Device* extension_device =
new bluetooth::Device();
bluetooth::BluetoothDeviceToApiDevice(
*device, extension_device);
discovered_devices_.push_back(extension_device);
if (!send_discovery_events_)
return;
bluetooth::Device extension_device;
bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device);
DispatchDeviceEvent(extensions::event_names::kBluetoothOnDeviceDiscovered,
*extension_device);
extension_device);
}
void ExtensionBluetoothEventRouter::InitializeAdapterIfNeeded() {
......@@ -331,6 +360,27 @@ void ExtensionBluetoothEventRouter::CleanUpForExtension(
ReleaseSocket(socket_id);
}
}
// Remove any discovery session initiated by the extension.
DiscoverySessionMap::iterator session_iter =
discovery_session_map_.find(extension_id);
if (session_iter == discovery_session_map_.end())
return;
delete session_iter->second;
discovery_session_map_.erase(session_iter);
}
void ExtensionBluetoothEventRouter::OnStartDiscoverySession(
const std::string& extension_id,
const base::Closure& callback,
scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
// Clean up any existing session instance for the extension.
DiscoverySessionMap::iterator iter =
discovery_session_map_.find(extension_id);
if (iter != discovery_session_map_.end())
delete iter->second;
discovery_session_map_[extension_id] = discovery_session.release();
callback.Run();
}
void ExtensionBluetoothEventRouter::Observe(
......
......@@ -24,6 +24,7 @@ class BrowserContext;
namespace device {
class BluetoothDevice;
class BluetoothDiscoverySession;
class BluetoothProfile;
} // namespace device
......@@ -81,6 +82,25 @@ class ExtensionBluetoothEventRouter
// registered.
bool HasProfile(const std::string& uuid) const;
// Requests that a new device discovery session be initiated for extension
// with id |extension_id|. |callback| is called, if a session has been
// initiated. |error_callback| is called, if the adapter failed to initiate
// the session or if an active session already exists for the extension.
void StartDiscoverySession(device::BluetoothAdapter* adapter,
const std::string& extension_id,
const base::Closure& callback,
const base::Closure& error_callback);
// Requests that the active discovery session that belongs to the extension
// with id |extension_id| be terminated. |callback| is called, if the session
// successfully ended. |error_callback| is called, if the adapter failed to
// terminate the session or if no active discovery session exists for the
// extension.
void StopDiscoverySession(device::BluetoothAdapter* adapter,
const std::string& extension_id,
const base::Closure& callback,
const base::Closure& error_callback);
// Returns the BluetoothProfile that corresponds to |uuid|. It returns NULL
// if the BluetoothProfile with |uuid| does not exist.
device::BluetoothProfile* GetProfile(const std::string& uuid) const;
......@@ -88,14 +108,6 @@ class ExtensionBluetoothEventRouter
// Get the BluetoothSocket corresponding to |id|.
scoped_refptr<device::BluetoothSocket> GetSocket(int id);
// Sets whether this Profile is responsible for the discovering state of the
// adapter.
void SetResponsibleForDiscovery(bool responsible);
bool IsResponsibleForDiscovery() const;
// Sets whether or not DeviceAdded events will be dispatched to extensions.
void SetSendDiscoveryEvents(bool should_send);
// Dispatch an event that takes a device as a parameter to all renderers.
void DispatchDeviceEvent(
const std::string& event_name,
......@@ -127,15 +139,17 @@ class ExtensionBluetoothEventRouter
void SetAdapterForTest(device::BluetoothAdapter* adapter) {
adapter_ = adapter;
}
private:
void InitializeAdapterIfNeeded();
void InitializeAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
void MaybeReleaseAdapter();
void DispatchAdapterStateEvent();
void CleanUpForExtension(const std::string& extension_id);
bool send_discovery_events_;
bool responsible_for_discovery_;
void OnStartDiscoverySession(
const std::string& extension_id,
const base::Closure& callback,
scoped_ptr<device::BluetoothDiscoverySession> discovery_session);
content::BrowserContext* browser_context_;
scoped_refptr<device::BluetoothAdapter> adapter_;
......@@ -150,15 +164,16 @@ class ExtensionBluetoothEventRouter
typedef std::map<int, ExtensionBluetoothSocketRecord> SocketMap;
SocketMap socket_map_;
typedef ScopedVector<extensions::api::bluetooth::Device>
DeviceList;
DeviceList discovered_devices_;
// A map that maps uuids to ExtensionBluetoothProfileRecord.
typedef std::map<std::string, ExtensionBluetoothProfileRecord>
BluetoothProfileMap;
BluetoothProfileMap bluetooth_profile_map_;
// A map that maps extension ids to BluetoothDiscoverySession pointers.
typedef std::map<std::string, device::BluetoothDiscoverySession*>
DiscoverySessionMap;
DiscoverySessionMap discovery_session_map_;
content::NotificationRegistrar registrar_;
base::WeakPtrFactory<ExtensionBluetoothEventRouter> weak_ptr_factory_;
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var kExpectedDeviceNames = ["d1", "d2"];
var kExpectedDeviceNames = ["d2"];
function testDiscovery() {
chrome.test.assertEq(kExpectedDeviceNames.length,
......
......@@ -123,6 +123,8 @@
'test/mock_bluetooth_adapter.h',
'test/mock_bluetooth_device.cc',
'test/mock_bluetooth_device.h',
'test/mock_bluetooth_discovery_session.cc',
'test/mock_bluetooth_discovery_session.h',
'test/mock_bluetooth_profile.cc',
'test/mock_bluetooth_profile.h',
'test/mock_bluetooth_socket.cc',
......
......@@ -113,7 +113,7 @@ void BluetoothAdapter::OnStartDiscoverySession(
const DiscoverySessionCallback& callback) {
VLOG(1) << "Discovery session started!";
scoped_ptr<BluetoothDiscoverySession> discovery_session(
new BluetoothDiscoverySession(this));
new BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter>(this)));
discovery_sessions_.insert(discovery_session.get());
callback.Run(discovery_session.Pass());
}
......
......@@ -9,13 +9,21 @@
namespace device {
BluetoothDiscoverySession::BluetoothDiscoverySession(BluetoothAdapter* adapter)
: active_(true),
adapter_(adapter),
weak_ptr_factory_(this) {
BluetoothDiscoverySession::BluetoothDiscoverySession(
scoped_refptr<BluetoothAdapter> adapter)
: active_(true), adapter_(adapter), weak_ptr_factory_(this) {
DCHECK(adapter_.get());
}
BluetoothDiscoverySession::BluetoothDiscoverySession()
: active_(false), weak_ptr_factory_(this) {}
BluetoothDiscoverySession::~BluetoothDiscoverySession() {
// |adapter_| may be NULL if this instance was initialized as a mock.
if (!adapter_.get()) {
DCHECK(!active_);
return;
}
Stop(base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
adapter_->DiscoverySessionDestroyed(this);
}
......@@ -28,11 +36,12 @@ void BluetoothDiscoverySession::Stop(
const base::Closure& callback,
const ErrorCallback& error_callback) {
if (!active_) {
LOG(ERROR) << "Discovery session not active. Cannot stop.";
LOG(WARNING) << "Discovery session not active. Cannot stop.";
error_callback.Run();
return;
}
VLOG(1) << "Stopping device discovery session.";
DCHECK(adapter_.get());
adapter_->RemoveDiscoverySession(
base::Bind(&BluetoothDiscoverySession::OnStop,
weak_ptr_factory_.GetWeakPtr(),
......
......@@ -58,10 +58,12 @@ class BluetoothDiscoverySession {
const ErrorCallback& error_callback);
protected:
friend class BluetoothAdapter;
explicit BluetoothDiscoverySession(BluetoothAdapter* adapter);
BluetoothDiscoverySession(); // Called by mock.
private:
friend class BluetoothAdapter;
explicit BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter> adapter);
// Internal callback invoked when a call to Stop has succeeded.
void OnStop(const base::Closure& callback);
......
......@@ -14,4 +14,12 @@ MockBluetoothAdapter::MockBluetoothAdapter() {
MockBluetoothAdapter::~MockBluetoothAdapter() {}
void MockBluetoothAdapter::AddDiscoverySession(
const base::Closure& callback,
const ErrorCallback& error_callback) {}
void MockBluetoothAdapter::RemoveDiscoverySession(
const base::Closure& callback,
const ErrorCallback& error_callback) {}
} // namespace device
......@@ -52,6 +52,9 @@ class MockBluetoothAdapter : public BluetoothAdapter {
const base::Closure& callback,
const ErrorCallback& error_callback));
MOCK_CONST_METHOD0(IsDiscovering, bool());
MOCK_METHOD2(StartDiscoverySession,
void(const DiscoverySessionCallback& callback,
const ErrorCallback& error_callback));
MOCK_METHOD2(StartDiscovering,
void(const base::Closure& callback,
const ErrorCallback& error_callback));
......@@ -74,12 +77,10 @@ class MockBluetoothAdapter : public BluetoothAdapter {
MOCK_METHOD0(DefaultPairingDelegate, BluetoothDevice::PairingDelegate*());
protected:
MOCK_METHOD2(AddDiscoverySession,
void(const base::Closure& callback,
const ErrorCallback& error_callback));
MOCK_METHOD2(RemoveDiscoverySession,
void(const base::Closure& callback,
const ErrorCallback& error_callback));
virtual void AddDiscoverySession(const base::Closure& callback,
const ErrorCallback& error_callback);
virtual void RemoveDiscoverySession(const base::Closure& callback,
const ErrorCallback& error_callback);
virtual ~MockBluetoothAdapter();
MOCK_METHOD1(RemovePairingDelegateInternal,
......
// Copyright 2014 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/test/mock_bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_adapter.h"
namespace device {
MockBluetoothDiscoverySession::MockBluetoothDiscoverySession() {}
MockBluetoothDiscoverySession::~MockBluetoothDiscoverySession() {}
} // namespace device
// Copyright 2014 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.
#ifndef DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_DISCOVERY_SESSION_H_
#define DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_DISCOVERY_SESSION_H_
#include "base/callback.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace device {
class BluetoothAdapter;
class MockBluetoothDiscoverySession : public BluetoothDiscoverySession {
public:
MockBluetoothDiscoverySession();
virtual ~MockBluetoothDiscoverySession();
MOCK_CONST_METHOD0(IsActive, bool());
MOCK_METHOD2(Stop,
void(const base::Closure& callback,
const ErrorCallback& error_callback));
private:
DISALLOW_COPY_AND_ASSIGN(MockBluetoothDiscoverySession);
};
} // namespac device
#endif // DEVICE_BLUETOOTH_TEST_MOCK_BLUETOOTH_DISCOVERY_SESSION_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment