chromium/ash/webui/eche_app_ui/eche_app_manager_unittest.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/webui/eche_app_ui/eche_app_manager.h"

#include <memory>

#include "ash/test/ash_test_base.h"
#include "ash/test/test_ash_web_view_factory.h"
#include "ash/webui/eche_app_ui/accessibility_provider.h"
#include "ash/webui/eche_app_ui/eche_connection_status_handler.h"
#include "ash/webui/eche_app_ui/eche_keyboard_layout_handler.h"
#include "ash/webui/eche_app_ui/eche_stream_orientation_observer.h"
#include "ash/webui/eche_app_ui/eche_stream_status_change_handler.h"
#include "ash/webui/eche_app_ui/launch_app_helper.h"
#include "ash/webui/eche_app_ui/system_info.h"
#include "base/functional/bind.h"
#include "base/test/task_environment.h"
#include "chromeos/ash/components/multidevice/remote_device_test_util.h"
#include "chromeos/ash/components/phonehub/fake_phone_hub_manager.h"
#include "chromeos/ash/components/phonehub/phone_hub_manager.h"
#include "chromeos/ash/components/test/ash_test_suite.h"
#include "chromeos/ash/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
#include "chromeos/ash/services/secure_channel/public/cpp/client/fake_secure_channel_client.h"
#include "chromeos/ash/services/secure_channel/public/cpp/client/presence_monitor_client.h"
#include "chromeos/ash/services/secure_channel/public/cpp/client/presence_monitor_client_impl.h"
#include "components/prefs/testing_pref_service.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_debug_manager_client.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"

namespace ash::eche_app {

namespace {

void LaunchEcheAppFunction(
    const std::optional<int64_t>& notification_id,
    const std::string& package_name,
    const std::u16string& visible_name,
    const std::optional<int64_t>& user_id,
    const gfx::Image& icon,
    const std::u16string& phone_name,
    AppsLaunchInfoProvider* apps_launcher_info_provider) {}

void LaunchNotificationFunction(
    const std::optional<std::u16string>& title,
    const std::optional<std::u16string>& message,
    std::unique_ptr<LaunchAppHelper::NotificationInfo> info) {}

void CloseNotificationFunction(const std::string& notification_id) {}

class FakePresenceMonitorClient : public secure_channel::PresenceMonitorClient {
 public:
  FakePresenceMonitorClient() = default;
  ~FakePresenceMonitorClient() override = default;

 private:
  // secure_channel::PresenceMonitorClient:
  void SetPresenceMonitorCallbacks(
      secure_channel::PresenceMonitor::ReadyCallback ready_callback,
      secure_channel::PresenceMonitor::DeviceSeenCallback device_seen_callback)
      override {}
  void StartMonitoring(
      const multidevice::RemoteDeviceRef& remote_device_ref,
      const multidevice::RemoteDeviceRef& local_device_ref) override {}
  void StopMonitoring() override {}
};

class FakeAccessibilityProviderProxy : public AccessibilityProviderProxy {
 public:
  FakeAccessibilityProviderProxy() = default;
  ~FakeAccessibilityProviderProxy() override = default;

  bool UseFullFocusMode() override { return false; }
  ax::android::mojom::AccessibilityFilterType GetFilterType() override {
    return ax::android::mojom::AccessibilityFilterType::ALL;
  }
  void OnViewTracked() override {}

  bool IsAccessibilityEnabled() override { return true; }

  void SetAccessibilityEnabledStateChangedCallback(
      base::RepeatingCallback<void(bool)> callback) override {}
  void SetExploreByTouchEnabledStateChangedCallback(
      base::RepeatingCallback<void(bool)> callback) override {}
};

}  // namespace

const char kFakeDeviceName[] = "Someone's Chromebook";
const char kFakeBoardName[] = "atlas";
const char kFakeGaiaId[] = "123";
const size_t kNumTestDevices = 3;
const char kFakeDeviceType[] = "Chromebook";

class EcheAppManagerTest : public AshTestBase {
 public:
  EcheAppManagerTest(const EcheAppManagerTest&) = delete;
  EcheAppManagerTest& operator=(const EcheAppManagerTest&) = delete;

 protected:
  EcheAppManagerTest()
      : test_devices_(
            multidevice::CreateRemoteDeviceRefListForTest(kNumTestDevices)) {}
  ~EcheAppManagerTest() override = default;

  // AshTestBase:
  void SetUp() override {
    std::unique_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
        bluez::BluezDBusManager::GetSetterForTesting();
    auto fake_bluetooth_debug_manager_client =
        std::make_unique<bluez::FakeBluetoothDebugManagerClient>();

    // We need to initialize BluezDBusManager early to prevent
    // Bluetooth*::Create() methods from picking the real instead of fake
    // implementations.
    dbus_setter->SetBluetoothDebugManagerClient(
        std::unique_ptr<bluez::BluetoothDebugManagerClient>(
            std::move(fake_bluetooth_debug_manager_client)));

    DCHECK(test_web_view_factory_.get());
    ui::ResourceBundle::CleanupSharedInstance();
    AshTestSuite::LoadTestResources();
    AshTestBase::SetUp();

    fake_phone_hub_manager_ = std::make_unique<phonehub::FakePhoneHubManager>();
    fake_device_sync_client_ =
        std::make_unique<device_sync::FakeDeviceSyncClient>();
    fake_device_sync_client_->set_local_device_metadata(test_devices_[0]);
    fake_device_sync_client_->NotifyReady();
    fake_multidevice_setup_client_ =
        std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>();
    fake_secure_channel_client_ =
        std::make_unique<secure_channel::FakeSecureChannelClient>();

    std::unique_ptr<FakePresenceMonitorClient> fake_presence_monitor_client =
        std::make_unique<FakePresenceMonitorClient>();

    manager_ = std::make_unique<EcheAppManager>(
        &test_pref_service_,
        SystemInfo::Builder()
            .SetDeviceName(kFakeDeviceName)
            .SetBoardName(kFakeBoardName)
            .SetGaiaId(kFakeGaiaId)
            .SetDeviceType(kFakeDeviceType)
            .Build(),
        fake_phone_hub_manager_.get(), fake_device_sync_client_.get(),
        fake_multidevice_setup_client_.get(), fake_secure_channel_client_.get(),
        std::move(fake_presence_monitor_client),
        std::make_unique<FakeAccessibilityProviderProxy>(),
        base::BindRepeating(&LaunchEcheAppFunction),
        base::BindRepeating(&LaunchNotificationFunction),
        base::BindRepeating(&CloseNotificationFunction));
  }

  void TearDown() override {
    manager_.reset();
    fake_secure_channel_client_.reset();
    fake_multidevice_setup_client_.reset();
    fake_device_sync_client_.reset();
    fake_phone_hub_manager_.reset();
    AshTestBase::TearDown();
  }

  mojo::Remote<mojom::SignalingMessageExchanger>&
  signaling_message_exchanger_remote() {
    return signaling_message_exchanger_remote_;
  }

  mojo::Remote<mojom::SystemInfoProvider>& system_info_provider_remote() {
    return system_info_provider_remote_;
  }

  mojo::Remote<mojom::UidGenerator>& uid_generator_remote() {
    return uid_generator_remote_;
  }

  mojo::Remote<mojom::NotificationGenerator>& notification_generator_remote() {
    return notification_generator_remote_;
  }

  mojo::Remote<mojom::DisplayStreamHandler>& display_stream_handler_remote() {
    return display_stream_handler_remote_;
  }

  mojo::Remote<mojom::StreamOrientationObserver>&
  stream_orientation_observer_remote() {
    return stream_orientation_observer_remote_;
  }

  mojo::Remote<mojom::ConnectionStatusObserver>&
  connection_status_observer_remote() {
    return connection_status_observer_remote_;
  }

  mojo::Remote<mojom::KeyboardLayoutHandler>& keyboard_layout_handler_remote() {
    return keyboard_layout_handler_remote_;
  }

  void Bind() {
    manager_->BindSignalingMessageExchangerInterface(
        signaling_message_exchanger_remote_.BindNewPipeAndPassReceiver());
    manager_->BindSystemInfoProviderInterface(
        system_info_provider_remote_.BindNewPipeAndPassReceiver());
    manager_->BindUidGeneratorInterface(
        uid_generator_remote_.BindNewPipeAndPassReceiver());
    manager_->BindNotificationGeneratorInterface(
        notification_generator_remote_.BindNewPipeAndPassReceiver());
    manager_->BindDisplayStreamHandlerInterface(
        display_stream_handler_remote_.BindNewPipeAndPassReceiver());
    manager_->BindStreamOrientationObserverInterface(
        stream_orientation_observer_remote_.BindNewPipeAndPassReceiver());
    manager_->BindConnectionStatusObserverInterface(
        connection_status_observer_remote_.BindNewPipeAndPassReceiver());
    manager_->BindKeyboardLayoutHandlerInterface(
        keyboard_layout_handler_remote_.BindNewPipeAndPassReceiver());
  }

 private:
  const multidevice::RemoteDeviceRefList test_devices_;

  TestingPrefServiceSimple test_pref_service_;
  std::unique_ptr<phonehub::FakePhoneHubManager> fake_phone_hub_manager_;
  std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
  std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient>
      fake_multidevice_setup_client_;
  std::unique_ptr<secure_channel::FakeSecureChannelClient>
      fake_secure_channel_client_;
  std::unique_ptr<EcheAppManager> manager_;
  std::unique_ptr<TestAshWebViewFactory> test_web_view_factory_ =
      std::make_unique<TestAshWebViewFactory>();

  mojo::Remote<mojom::SignalingMessageExchanger>
      signaling_message_exchanger_remote_;
  mojo::Remote<mojom::SystemInfoProvider> system_info_provider_remote_;
  mojo::Remote<mojom::UidGenerator> uid_generator_remote_;
  mojo::Remote<mojom::NotificationGenerator> notification_generator_remote_;
  mojo::Remote<mojom::DisplayStreamHandler> display_stream_handler_remote_;
  mojo::Remote<mojom::StreamOrientationObserver>
      stream_orientation_observer_remote_;
  mojo::Remote<mojom::ConnectionStatusObserver>
      connection_status_observer_remote_;
  mojo::Remote<mojom::KeyboardLayoutHandler> keyboard_layout_handler_remote_;
};

TEST_F(EcheAppManagerTest, BindCheck) {
  EXPECT_FALSE(signaling_message_exchanger_remote());
  EXPECT_FALSE(system_info_provider_remote());
  EXPECT_FALSE(uid_generator_remote());
  EXPECT_FALSE(notification_generator_remote());
  EXPECT_FALSE(display_stream_handler_remote());
  EXPECT_FALSE(stream_orientation_observer_remote());
  EXPECT_FALSE(connection_status_observer_remote());
  EXPECT_FALSE(keyboard_layout_handler_remote());

  Bind();

  EXPECT_TRUE(signaling_message_exchanger_remote());
  EXPECT_TRUE(system_info_provider_remote());
  EXPECT_TRUE(uid_generator_remote());
  EXPECT_TRUE(notification_generator_remote());
  EXPECT_TRUE(display_stream_handler_remote());
  EXPECT_TRUE(stream_orientation_observer_remote());
  EXPECT_TRUE(connection_status_observer_remote());
  EXPECT_TRUE(keyboard_layout_handler_remote());
}

}  // namespace ash::eche_app