chromium/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_keyboard_backlight_provider_impl.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 "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/rgb_keyboard/rgb_keyboard_manager.h"
#include "ash/rgb_keyboard/rgb_keyboard_util.h"
#include "ash/shell.h"
#include "ash/system/keyboard_brightness/keyboard_backlight_color_controller.h"
#include "ash/system/keyboard_brightness/keyboard_backlight_color_nudge_controller.h"
#include "ash/wallpaper/wallpaper_controller_impl.h"
#include "ash/webui/personalization_app/mojom/personalization_app.mojom-shared.h"
#include "base/check.h"
#include "base/logging.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_metrics.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "components/prefs/pref_service.h"
#include "third_party/skia/include/core/SkColor.h"

namespace ash::personalization_app {

using DisplayType = KeyboardBacklightColorController::DisplayType;

PersonalizationAppKeyboardBacklightProviderImpl::
    PersonalizationAppKeyboardBacklightProviderImpl(content::WebUI* web_ui)
    : profile_(Profile::FromWebUI(web_ui)) {}

PersonalizationAppKeyboardBacklightProviderImpl::
    ~PersonalizationAppKeyboardBacklightProviderImpl() = default;

void PersonalizationAppKeyboardBacklightProviderImpl::BindInterface(
    mojo::PendingReceiver<mojom::KeyboardBacklightProvider> receiver) {
  keyboard_backlight_receiver_.reset();
  keyboard_backlight_receiver_.Bind(std::move(receiver));
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    SetKeyboardBacklightObserver(
        mojo::PendingRemote<mojom::KeyboardBacklightObserver> observer) {
  // May already be bound if user refreshes page.
  keyboard_backlight_observer_remote_.reset();
  keyboard_backlight_observer_remote_.Bind(std::move(observer));

  // Call it once to get the current status of backlight state (backlight color
  // is either static color or multi-zone colors).
  NotifyBacklightStateChanged();

  // Bind wallpaper observer now that rgb keyboard section is ready and visible
  // to users.
  if (!wallpaper_controller_observation_.IsObserving()) {
    wallpaper_controller_observation_.Observe(WallpaperController::Get());
  }
  // Call it once to get the wallpaper extracted color.
  OnWallpaperColorsChanged();
}

void PersonalizationAppKeyboardBacklightProviderImpl::SetBacklightColor(
    mojom::BacklightColor backlight_color) {
  DVLOG(4) << __func__ << " backlight_color=" << backlight_color;
  LogKeyboardBacklightColor(backlight_color);
  GetKeyboardBacklightColorController()->SetBacklightColor(
      backlight_color, GetAccountId(profile_));
  GetKeyboardBacklightColorController()
      ->keyboard_backlight_color_nudge_controller()
      ->SetUserPerformedAction();

  // Get the current status of backlight state as backlight color has changed.
  // Notifies backlight changed to a static color or rainbow color to highlight
  // the selected state of color icon button.
  NotifyBacklightStateChanged();
}

void PersonalizationAppKeyboardBacklightProviderImpl::SetBacklightZoneColor(
    int zone,
    mojom::BacklightColor backlight_color) {
  if (!ash::features::IsMultiZoneRgbKeyboardEnabled()) {
    keyboard_backlight_receiver_.ReportBadMessage(
        "Cannot call `SetBacklightZoneColor()` without multi-zone rgb keyboard "
        "enabled");
    return;
  }

  DVLOG(4) << __func__ << " zone=" << zone
           << " backlight_color=" << backlight_color;
  // TODO(b/266588717): Log zone customization metric.
  GetKeyboardBacklightColorController()->SetBacklightZoneColor(
      zone, backlight_color, GetAccountId(profile_));
  GetKeyboardBacklightColorController()
      ->keyboard_backlight_color_nudge_controller()
      ->SetUserPerformedAction();

  // Get the current status of backlight state as backlight color has changed to
  // zone colors. Notifies backlight changed to |kMultizone| to highlight the
  // selected state of customization button.
  NotifyBacklightStateChanged();
}

void PersonalizationAppKeyboardBacklightProviderImpl::ShouldShowNudge(
    ShouldShowNudgeCallback callback) {
  std::move(callback).Run(
      KeyboardBacklightColorNudgeController::ShouldShowWallpaperColorNudge());
}

void PersonalizationAppKeyboardBacklightProviderImpl::HandleNudgeShown() {
  KeyboardBacklightColorNudgeController::HandleWallpaperColorNudgeShown();
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    OnWallpaperColorsChanged() {
  DCHECK(keyboard_backlight_observer_remote_.is_bound());
  keyboard_backlight_observer_remote_->OnWallpaperColorChanged(
      ConvertBacklightColorToSkColor(
          personalization_app::mojom::BacklightColor::kWallpaper));
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    SetKeyboardBacklightColorControllerForTesting(
        KeyboardBacklightColorController* controller) {
  keyboard_backlight_color_controller_for_testing_ = controller;
}

KeyboardBacklightColorController*
PersonalizationAppKeyboardBacklightProviderImpl::
    GetKeyboardBacklightColorController() {
  if (keyboard_backlight_color_controller_for_testing_) {
    return keyboard_backlight_color_controller_for_testing_;
  }
  auto* keyboard_backlight_color_controller =
      ash::Shell::Get()->keyboard_backlight_color_controller();
  DCHECK(keyboard_backlight_color_controller);
  return keyboard_backlight_color_controller;
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    NotifyBacklightStateChanged() {
  const auto displayType =
      GetKeyboardBacklightColorController()->GetDisplayType(
          GetAccountId(profile_));
  switch (displayType) {
    case DisplayType::kStatic: {
      NotifyBacklightColorChanged();
      return;
    }
    case DisplayType::kMultiZone: {
      NotifyBacklightZoneColorsChanged();
      return;
    }
  }
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    NotifyBacklightColorChanged() {
  DCHECK(keyboard_backlight_observer_remote_.is_bound());

  keyboard_backlight_observer_remote_->OnBacklightStateChanged(
      ash::personalization_app::mojom::CurrentBacklightState::NewColor(
          GetKeyboardBacklightColorController()->GetBacklightColor(
              GetAccountId(profile_))));
}

void PersonalizationAppKeyboardBacklightProviderImpl::
    NotifyBacklightZoneColorsChanged() {
  DCHECK(keyboard_backlight_observer_remote_.is_bound());

  keyboard_backlight_observer_remote_->OnBacklightStateChanged(
      ash::personalization_app::mojom::CurrentBacklightState::NewZoneColors(
          GetKeyboardBacklightColorController()->GetBacklightZoneColors(
              GetAccountId(profile_))));
}

}  // namespace ash::personalization_app