chromium/chromeos/lacros/native_theme_cache.cc

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

#include "chromeos/lacros/native_theme_cache.h"

#include <optional>

#include "base/time/time.h"
#include "chromeos/crosapi/mojom/native_theme.mojom-forward.h"
#include "chromeos/lacros/lacros_service.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_provider_key.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_aura.h"

namespace chromeos {
namespace {

ui::ColorProviderKey::SchemeVariant ConvertSchemeVariant(
    color::mojom::SchemeVariant scheme) {
  switch (scheme) {
    case color::mojom::SchemeVariant::kTonalSpot:
      return ui::ColorProviderKey::SchemeVariant::kTonalSpot;
    case color::mojom::SchemeVariant::kNeutral:
      return ui::ColorProviderKey::SchemeVariant::kNeutral;
    case color::mojom::SchemeVariant::kVibrant:
      return ui::ColorProviderKey::SchemeVariant::kVibrant;
    case color::mojom::SchemeVariant::kExpressive:
      return ui::ColorProviderKey::SchemeVariant::kExpressive;
  }
  // not reached
}

void SetSeedOnTheme(ui::NativeTheme* theme,
                    const crosapi::mojom::NativeThemeInfoPtr& info) {
  if (!info->seed_color.has_value()) {
    return;
  }

  theme->set_user_color(*info->seed_color);
}

void SetVariantOnTheme(ui::NativeTheme* theme,
                       const crosapi::mojom::NativeThemeInfoPtr& info) {
  if (!info->scheme_variant.has_value()) {
    return;
  }

  // TODO(b/286891722): Convert to an EnumTrait after circular dependency is
  // resolved.
  theme->set_scheme_variant(ConvertSchemeVariant(*info->scheme_variant));
}

void SetCaretBlinkIntervalOnTheme(
    ui::NativeTheme* theme,
    const crosapi::mojom::NativeThemeInfoPtr& info) {
  if (!info->caret_blink_interval.has_value()) {
    // A missing value indicates we should use the existing default within
    // NativeTheme, so no further work is required.
    return;
  }
  theme->set_caret_blink_interval(info->caret_blink_interval.value());
}

}  // namespace

NativeThemeCache::NativeThemeCache(const crosapi::mojom::NativeThemeInfo& info)
    : info_(info.Clone()) {
  SetNativeThemeInfo();
}

NativeThemeCache::~NativeThemeCache() = default;

void NativeThemeCache::Start() {
  auto* lacros_service = chromeos::LacrosService::Get();
  CHECK(lacros_service->IsAvailable<crosapi::mojom::NativeThemeService>());
  lacros_service->GetRemote<crosapi::mojom::NativeThemeService>()
      ->AddNativeThemeInfoObserver(receiver_.BindNewPipeAndPassRemote());
}

void NativeThemeCache::OnNativeThemeInfoChanged(
    crosapi::mojom::NativeThemeInfoPtr info) {
  info_ = std::move(info);

  SetNativeThemeInfo();
}

void NativeThemeCache::SetNativeThemeInfo() {
  bool dark_mode = info_->dark_mode || ui::NativeTheme::IsForcedDarkMode();

  auto* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
  native_theme->set_use_dark_colors(dark_mode);
  SetSeedOnTheme(native_theme, info_);
  SetVariantOnTheme(native_theme, info_);
  SetCaretBlinkIntervalOnTheme(native_theme, info_);
  native_theme->NotifyOnNativeThemeUpdated();

  auto* native_theme_web = ui::NativeTheme::GetInstanceForWeb();
  native_theme_web->set_use_dark_colors(dark_mode);
  native_theme_web->set_preferred_color_scheme(
      dark_mode ? ui::NativeTheme::PreferredColorScheme::kDark
                : ui::NativeTheme::PreferredColorScheme::kLight);
  SetSeedOnTheme(native_theme_web, info_);
  SetVariantOnTheme(native_theme_web, info_);
  SetCaretBlinkIntervalOnTheme(native_theme_web, info_);
  native_theme_web->NotifyOnNativeThemeUpdated();
}

}  // namespace chromeos