blob: 6057fca601f18da3caddaee32410abef8d3cd85a [file] [log] [blame]
// Copyright (c) 2012 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 "extensions/browser/api/bluetooth/bluetooth_event_router.h"
#include <memory>
#include <string>
#include <utility>
#include "base/callback_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_context.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extensions_test.h"
#include "extensions/browser/unloaded_extension_reason.h"
#include "extensions/common/api/bluetooth.h"
#include "extensions/common/extension_builder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kTestExtensionId[] = "test extension id";
const device::BluetoothUUID kAudioProfileUuid("1234");
const device::BluetoothUUID kHealthProfileUuid("4321");
MATCHER_P(IsFilterEqual, a, "") {
return arg.Equals(*a);
}
} // namespace
namespace extensions {
namespace bluetooth = api::bluetooth;
class BluetoothEventRouterTest : public ExtensionsTest {
public:
BluetoothEventRouterTest()
: mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()) {
}
void SetUp() override {
ExtensionsTest::SetUp();
router_ = std::make_unique<BluetoothEventRouter>(browser_context());
router_->SetAdapterForTest(mock_adapter_);
}
void TearDown() override {
// It's important to destroy the router before the browser context keyed
// services so it removes itself as an ExtensionRegistry observer.
router_.reset(NULL);
ExtensionsTest::TearDown();
}
protected:
testing::StrictMock<device::MockBluetoothAdapter>* mock_adapter_;
std::unique_ptr<BluetoothEventRouter> router_;
};
TEST_F(BluetoothEventRouterTest, BluetoothEventListener) {
EventListenerInfo info("", "", GURL(), nullptr);
router_->OnListenerAdded(info);
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
router_->OnListenerRemoved(info);
}
TEST_F(BluetoothEventRouterTest, MultipleBluetoothEventListeners) {
// TODO(rkc/stevenjb): Test multiple extensions and WebUI.
EventListenerInfo info("", "", GURL(), nullptr);
router_->OnListenerAdded(info);
router_->OnListenerAdded(info);
router_->OnListenerAdded(info);
router_->OnListenerRemoved(info);
router_->OnListenerRemoved(info);
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
router_->OnListenerRemoved(info);
}
TEST_F(BluetoothEventRouterTest, UnloadExtension) {
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
.Set("name", "BT event router test")
.Set("version", "1.0")
.Set("manifest_version", 2)
.Build())
.SetID(kTestExtensionId)
.Build();
ExtensionRegistry::Get(browser_context())
->TriggerOnUnloaded(extension.get(), UnloadedExtensionReason::DISABLE);
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
}
// This test check that calling SetDiscoveryFilter before StartDiscoverySession
// for given extension will start session with proper filter.
TEST_F(BluetoothEventRouterTest, SetDiscoveryFilter) {
auto discovery_filter = std::make_unique<device::BluetoothDiscoveryFilter>(
device::BLUETOOTH_TRANSPORT_LE);
discovery_filter->SetRSSI(-80);
device::BluetoothDiscoveryFilter::DeviceInfoFilter device_filter;
device_filter.uuids.insert(device::BluetoothUUID("1000"));
discovery_filter->AddDeviceFilter(std::move(device_filter));
device::BluetoothDiscoveryFilter df(device::BLUETOOTH_TRANSPORT_LE);
df.CopyFrom(*discovery_filter);
router_->SetDiscoveryFilter(std::move(discovery_filter), mock_adapter_,
kTestExtensionId, base::DoNothing(),
base::DoNothing());
EXPECT_CALL(
*mock_adapter_,
StartScanWithFilter_(testing::Pointee(IsFilterEqual(&df)), testing::_))
.WillOnce(testing::Invoke(
[](const device::BluetoothDiscoveryFilter* filter,
base::OnceCallback<void(
/*is_error*/ bool,
device::UMABluetoothDiscoverySessionOutcome)>& callback) {
std::move(callback).Run(
false, device::UMABluetoothDiscoverySessionOutcome::SUCCESS);
}));
// RemoveDiscoverySession will be called when the BluetoothDiscoverySession
// is destroyed
EXPECT_CALL(*mock_adapter_, StopScan(testing::_)).Times(1);
router_->StartDiscoverySession(mock_adapter_, kTestExtensionId,
base::DoNothing(), base::DoNothing());
EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
}
} // namespace extensions