| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_BLUETOOTH_WEB_BLUETOOTH_TEST_UTILS_H_ |
| #define CHROME_BROWSER_BLUETOOTH_WEB_BLUETOOTH_TEST_UTILS_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/functional/callback.h" |
| #include "chrome/browser/bluetooth/chrome_bluetooth_delegate.h" |
| #include "chrome/browser/chrome_content_browser_client.h" |
| #include "device/bluetooth/bluetooth_adapter.h" |
| #include "device/bluetooth/bluetooth_gatt_notify_session.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_service.h" |
| #include "device/bluetooth/public/cpp/bluetooth_uuid.h" |
| #include "device/bluetooth/test/mock_bluetooth_adapter.h" |
| #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| class FakeBluetoothAdapter |
| : public testing::NiceMock<device::MockBluetoothAdapter> { |
| public: |
| FakeBluetoothAdapter(); |
| |
| // Move-only class |
| FakeBluetoothAdapter(const FakeBluetoothAdapter&) = delete; |
| FakeBluetoothAdapter& operator=(const FakeBluetoothAdapter&) = delete; |
| |
| void SetIsPresent(bool is_present); |
| |
| void SimulateDeviceAdvertisementReceived( |
| const std::string& device_address, |
| const std::optional<std::string>& advertisement_name = |
| std::nullopt) const; |
| |
| // device::BluetoothAdapter implementation: |
| void AddObserver(device::BluetoothAdapter::Observer* observer) override; |
| |
| bool IsPresent() const override; |
| |
| bool IsPowered() const override; |
| |
| device::BluetoothAdapter::ConstDeviceList GetDevices() const override; |
| |
| device::BluetoothDevice* GetDevice(const std::string& address) override; |
| |
| void StartScanWithFilter( |
| std::unique_ptr<device::BluetoothDiscoveryFilter> filter, |
| base::OnceCallback<void(/*is_error*/ bool, |
| device::UMABluetoothDiscoverySessionOutcome)> |
| callback) override; |
| |
| protected: |
| ~FakeBluetoothAdapter() override; |
| |
| bool is_present_ = true; |
| }; |
| |
| class FakeBluetoothGattCharacteristic |
| : public testing::NiceMock<device::MockBluetoothGattCharacteristic> { |
| public: |
| FakeBluetoothGattCharacteristic(device::MockBluetoothGattService* service, |
| const std::string& identifier, |
| const device::BluetoothUUID& uuid, |
| Properties properties, |
| Permissions permissions); |
| |
| ~FakeBluetoothGattCharacteristic(); |
| |
| // Move-only class |
| FakeBluetoothGattCharacteristic(const FakeBluetoothGattCharacteristic&) = |
| delete; |
| FakeBluetoothGattCharacteristic operator=( |
| const FakeBluetoothGattCharacteristic&) = delete; |
| |
| void ReadRemoteCharacteristic(ValueCallback callback) override; |
| |
| void StartNotifySession(NotifySessionCallback callback, |
| ErrorCallback error_callback) override; |
| |
| void StopNotifySession(device::BluetoothGattNotifySession::Id session, |
| base::OnceClosure callback) override; |
| |
| bool IsNotifying() const override; |
| |
| // Do not call the readValue callback until midway through the completion |
| // of the startNotification callback registration. |
| // https://crbug.com/1153426 |
| void DeferReadUntilNotificationStart(); |
| |
| // Possibly trigger value characteristicvaluechanged events on the page |
| // during the setup of startNotifications. |
| // https://crbug.com/1153426. |
| void EmitChangeNotificationAtNotificationStart(); |
| |
| private: |
| std::vector<uint8_t> value_; |
| ValueCallback deferred_read_callback_; |
| bool defer_read_until_notification_start_ = false; |
| bool emit_value_change_at_notification_start_ = false; |
| std::set<device::BluetoothGattNotifySession::Id> active_notify_sessions_; |
| }; |
| |
| class FakeBluetoothGattConnection |
| : public testing::NiceMock<device::MockBluetoothGattConnection> { |
| public: |
| FakeBluetoothGattConnection(scoped_refptr<device::BluetoothAdapter> adapter, |
| const std::string& device_address); |
| |
| // Move-only class |
| FakeBluetoothGattConnection(const FakeBluetoothGattConnection&) = delete; |
| FakeBluetoothGattConnection operator=(const FakeBluetoothGattConnection&) = |
| delete; |
| }; |
| |
| class FakeBluetoothDevice |
| : public testing::NiceMock<device::MockBluetoothDevice> { |
| public: |
| FakeBluetoothDevice(device::MockBluetoothAdapter* adapter, |
| const std::string& address); |
| |
| void CreateGattConnection( |
| device::BluetoothDevice::GattConnectionCallback callback, |
| std::optional<device::BluetoothUUID> service_uuid = |
| std::nullopt) override; |
| |
| bool IsGattServicesDiscoveryComplete() const override; |
| |
| device::BluetoothRemoteGattService* GetGattService( |
| const std::string& identifier) const override; |
| |
| std::vector<device::BluetoothRemoteGattService*> GetGattServices() |
| const override; |
| |
| // Move-only class |
| FakeBluetoothDevice(const FakeBluetoothDevice&) = delete; |
| FakeBluetoothDevice& operator=(const FakeBluetoothDevice&) = delete; |
| |
| protected: |
| bool gatt_services_discovery_complete_ = false; |
| }; |
| |
| class FakeBluetoothChooser : public content::BluetoothChooser { |
| public: |
| FakeBluetoothChooser(content::BluetoothChooser::EventHandler event_handler, |
| const std::optional<std::string>& device_to_select); |
| ~FakeBluetoothChooser() override; |
| |
| // content::BluetoothChooser implementation: |
| void AddOrUpdateDevice(const std::string& device_id, |
| bool should_update_name, |
| const std::u16string& device_name, |
| bool is_gatt_connected, |
| bool is_paired, |
| int signal_strength_level) override; |
| |
| // Move-only class |
| FakeBluetoothChooser(const FakeBluetoothChooser&) = delete; |
| FakeBluetoothChooser& operator=(const FakeBluetoothChooser&) = delete; |
| |
| private: |
| content::BluetoothChooser::EventHandler event_handler_; |
| std::optional<std::string> device_to_select_; |
| }; |
| |
| class TestBluetoothDelegate : public ChromeBluetoothDelegate { |
| public: |
| TestBluetoothDelegate(); |
| ~TestBluetoothDelegate() override; |
| TestBluetoothDelegate(const TestBluetoothDelegate&) = delete; |
| TestBluetoothDelegate& operator=(const TestBluetoothDelegate&) = delete; |
| |
| void UseRealChooser(); |
| |
| void SetDeviceToSelect(const std::string& device_address); |
| |
| protected: |
| // content::BluetoothDelegate implementation: |
| std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser( |
| content::RenderFrameHost* frame, |
| const content::BluetoothChooser::EventHandler& event_handler) override; |
| |
| std::unique_ptr<content::BluetoothScanningPrompt> ShowBluetoothScanningPrompt( |
| content::RenderFrameHost* frame, |
| const content::BluetoothScanningPrompt::EventHandler& event_handler) |
| override; |
| |
| private: |
| std::optional<std::string> device_to_select_; |
| bool use_real_chooser_ = false; |
| }; |
| |
| class BluetoothTestContentBrowserClient : public ChromeContentBrowserClient { |
| public: |
| BluetoothTestContentBrowserClient(); |
| ~BluetoothTestContentBrowserClient() override; |
| BluetoothTestContentBrowserClient(const BluetoothTestContentBrowserClient&) = |
| delete; |
| BluetoothTestContentBrowserClient& operator=( |
| const BluetoothTestContentBrowserClient&) = delete; |
| |
| TestBluetoothDelegate* bluetooth_delegate(); |
| |
| protected: |
| // ChromeContentBrowserClient: |
| content::BluetoothDelegate* GetBluetoothDelegate() override; |
| |
| private: |
| TestBluetoothDelegate bluetooth_delegate_; |
| }; |
| |
| #endif // CHROME_BROWSER_BLUETOOTH_WEB_BLUETOOTH_TEST_UTILS_H_ |