chromium/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_keyboard_backlight_provider_impl_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 "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_keyboard_backlight_provider_impl.h"

#include <memory>
#include <optional>
#include <vector>

#include "ash/constants/ash_features.h"
#include "ash/rgb_keyboard/rgb_keyboard_manager.h"
#include "ash/shell.h"
#include "ash/system/keyboard_brightness/keyboard_backlight_color_controller.h"
#include "ash/webui/personalization_app/mojom/personalization_app.mojom.h"
#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_metrics.h"
#include "chrome/test/base/chrome_ash_test_base.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_web_ui.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"

namespace ash::personalization_app {

namespace {

constexpr char kFakeTestEmail[] = "fakeemail@personalization";
const AccountId account_id =
    AccountId::FromUserEmailGaiaId(kFakeTestEmail, kFakeTestEmail);

class TestKeyboardBacklightObserver
    : public ash::personalization_app::mojom::KeyboardBacklightObserver {
 public:
  void OnBacklightStateChanged(
      mojom::CurrentBacklightStatePtr current_backlight_state) override {
    current_backlight_state_ = std::move(current_backlight_state);
  }

  void OnWallpaperColorChanged(SkColor wallpaper_color) override {
    wallpaper_color_ = wallpaper_color;
  }

  mojo::PendingRemote<
      ash::personalization_app::mojom::KeyboardBacklightObserver>
  pending_remote() {
    if (keyboard_backlight_observer_receiver_.is_bound()) {
      keyboard_backlight_observer_receiver_.reset();
    }

    return keyboard_backlight_observer_receiver_.BindNewPipeAndPassRemote();
  }

  mojom::CurrentBacklightState* current_backlight_state() {
    keyboard_backlight_observer_receiver_.FlushForTesting();
    return current_backlight_state_.get();
  }

  std::optional<SkColor> wallpaper_color() {
    keyboard_backlight_observer_receiver_.FlushForTesting();
    return wallpaper_color_;
  }

 private:
  mojo::Receiver<ash::personalization_app::mojom::KeyboardBacklightObserver>
      keyboard_backlight_observer_receiver_{this};
  mojom::CurrentBacklightStatePtr current_backlight_state_ =
      mojom::CurrentBacklightState::NewColor(mojom::BacklightColor::kRed);
  std::optional<SkColor> wallpaper_color_;
};

}  // namespace

class PersonalizationAppKeyboardBacklightProviderImplTest
    : public ChromeAshTestBase {
 public:
  PersonalizationAppKeyboardBacklightProviderImplTest()
      : scoped_user_manager_(std::make_unique<ash::FakeChromeUserManager>()),
        profile_manager_(TestingBrowserProcess::GetGlobal()) {
    scoped_feature_list_.InitWithFeatures(
        {ash::features::kMultiZoneRgbKeyboard}, {});
  }
  PersonalizationAppKeyboardBacklightProviderImplTest(
      const PersonalizationAppKeyboardBacklightProviderImplTest&) = delete;
  PersonalizationAppKeyboardBacklightProviderImplTest& operator=(
      const PersonalizationAppKeyboardBacklightProviderImplTest&) = delete;
  ~PersonalizationAppKeyboardBacklightProviderImplTest() override = default;

 protected:
  // testing::Test:
  void SetUp() override {
    ChromeAshTestBase::SetUp();

    ASSERT_TRUE(profile_manager_.SetUp());
    profile_ = profile_manager_.CreateTestingProfile(kFakeTestEmail);

    ash::FakeChromeUserManager* user_manager =
        static_cast<ash::FakeChromeUserManager*>(
            user_manager::UserManager::Get());
    user_manager->AddUser(account_id);

    web_contents_ = content::WebContents::Create(
        content::WebContents::CreateParams(profile_));
    web_ui_.set_web_contents(web_contents_.get());

    keyboard_backlight_provider_ =
        std::make_unique<PersonalizationAppKeyboardBacklightProviderImpl>(
            &web_ui_);
    keyboard_backlight_color_controller_ =
        std::make_unique<KeyboardBacklightColorController>(local_state());
    keyboard_backlight_color_controller_->OnRgbKeyboardSupportedChanged(true);
    keyboard_backlight_provider_->SetKeyboardBacklightColorControllerForTesting(
        keyboard_backlight_color_controller_.get());
    keyboard_backlight_provider_->BindInterface(
        keyboard_backlight_provider_remote_.BindNewPipeAndPassReceiver());
  }

  void TearDown() override {
    keyboard_backlight_color_controller_.reset();
    keyboard_backlight_provider_.reset();
    ChromeAshTestBase::TearDown();
  }

  const base::HistogramTester& histogram_tester() const {
    return histogram_tester_;
  }

  TestingProfile* profile() { return profile_; }

  mojo::Remote<ash::personalization_app::mojom::KeyboardBacklightProvider>*
  keyboard_backlight_provider_remote() {
    return &keyboard_backlight_provider_remote_;
  }

  PersonalizationAppKeyboardBacklightProviderImpl*
  keyboard_backlight_provider() {
    return keyboard_backlight_provider_.get();
  }

  void SetKeyboardBacklightObserver() {
    keyboard_backlight_provider_remote_->SetKeyboardBacklightObserver(
        test_keyboard_backlight_observer_.pending_remote());
  }

  mojom::CurrentBacklightState* ObservedBacklightColor() {
    keyboard_backlight_provider_remote_.FlushForTesting();
    return test_keyboard_backlight_observer_.current_backlight_state();
  }

  std::optional<SkColor> ObservedWallpaperColor() {
    keyboard_backlight_provider_remote_.FlushForTesting();
    return test_keyboard_backlight_observer_.wallpaper_color();
  }

  void set_rgb_capability(rgbkbd::RgbKeyboardCapabilities capability) {
    RgbKeyboardManager* rgb_keyboard_manager =
        Shell::Get()->rgb_keyboard_manager();
    rgb_keyboard_manager->OnCapabilityUpdatedForTesting(capability);
  }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  user_manager::ScopedUserManager scoped_user_manager_;
  TestingProfileManager profile_manager_;
  content::TestWebUI web_ui_;
  std::unique_ptr<content::WebContents> web_contents_;
  raw_ptr<TestingProfile> profile_;
  std::unique_ptr<KeyboardBacklightColorController>
      keyboard_backlight_color_controller_;
  mojo::Remote<ash::personalization_app::mojom::KeyboardBacklightProvider>
      keyboard_backlight_provider_remote_;
  std::unique_ptr<PersonalizationAppKeyboardBacklightProviderImpl>
      keyboard_backlight_provider_;
  TestKeyboardBacklightObserver test_keyboard_backlight_observer_;
  base::HistogramTester histogram_tester_;
};

TEST_F(PersonalizationAppKeyboardBacklightProviderImplTest, SetBacklightColor) {
  SimulateUserLogin(account_id);
  SetKeyboardBacklightObserver();
  keyboard_backlight_provider_remote()->FlushForTesting();
  keyboard_backlight_provider()->SetBacklightColor(
      mojom::BacklightColor::kBlue);

  // Verify JS side is notified.
  EXPECT_TRUE(ObservedBacklightColor()->is_color());
  EXPECT_EQ(mojom::BacklightColor::kBlue,
            ObservedBacklightColor()->get_color());
  histogram_tester().ExpectBucketCount(
      kPersonalizationKeyboardBacklightColorHistogramName,
      mojom::BacklightColor::kBlue, 1);
}

TEST_F(PersonalizationAppKeyboardBacklightProviderImplTest,
       SetBacklightZoneColor) {
  SimulateUserLogin(account_id);
  SetKeyboardBacklightObserver();
  set_rgb_capability(rgbkbd::RgbKeyboardCapabilities::kFourZoneFortyLed);
  keyboard_backlight_provider_remote()->FlushForTesting();

  keyboard_backlight_provider()->SetBacklightColor(
      mojom::BacklightColor::kBlue);
  EXPECT_TRUE(ObservedBacklightColor()->is_color());

  keyboard_backlight_provider()->SetBacklightZoneColor(
      1, mojom::BacklightColor::kRed);
  // Verify JS side is notified.
  EXPECT_TRUE(ObservedBacklightColor()->is_zone_colors());
  const auto zone_colors = ObservedBacklightColor()->get_zone_colors();
  for (size_t i = 0; i < zone_colors.size(); i++) {
    EXPECT_EQ(zone_colors[i], i == 1 ? mojom::BacklightColor::kRed
                                     : mojom::BacklightColor::kBlue);
  }
}

TEST_F(PersonalizationAppKeyboardBacklightProviderImplTest,
       ObserveWallpaperColor) {
  SimulateUserLogin(account_id);
  SetKeyboardBacklightObserver();
  keyboard_backlight_provider_remote()->FlushForTesting();
  keyboard_backlight_provider()->OnWallpaperColorsChanged();

  // Verify JS side is notified.
  EXPECT_TRUE(ObservedWallpaperColor().has_value());
}

}  // namespace ash::personalization_app