chromium/chrome/browser/ash/crosapi/native_theme_service_ash.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 "chrome/browser/ash/crosapi/native_theme_service_ash.h"

#include "chromeos/constants/chromeos_features.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_provider_key.h"
#include "ui/color/scheme_variant.mojom.h"
#include "ui/native_theme/native_theme.h"

namespace crosapi {
namespace {

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

}  // namespace

/******** NativeThemeServiceAsh::Dispatcher ********/

NativeThemeServiceAsh::Dispatcher::Dispatcher() {
  ui::NativeTheme::GetInstanceForNativeUi()->AddObserver(this);
}

NativeThemeServiceAsh::Dispatcher::~Dispatcher() {
  ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
}

void NativeThemeServiceAsh::Dispatcher::OnNativeThemeUpdated(
    ui::NativeTheme* observed_theme) {
  DCHECK_EQ(ui::NativeTheme::GetInstanceForNativeUi(), observed_theme);

  mojom::NativeThemeInfoPtr info = NativeThemeServiceAsh::GetNativeThemeInfo();
  for (auto& observer : observers_) {
    mojom::NativeThemeInfoPtr info_copy = info->Clone();
    observer->OnNativeThemeInfoChanged(std::move(info_copy));
  }
}

/******** NativeThemeServiceAsh ********/

// static
mojom::NativeThemeInfoPtr NativeThemeServiceAsh::GetNativeThemeInfo() {
  auto info = mojom::NativeThemeInfo::New();
  const ui::NativeTheme* theme = ui::NativeTheme::GetInstanceForNativeUi();
  info->dark_mode = theme->ShouldUseDarkColors();
  info->caret_blink_interval = theme->GetCaretBlinkInterval();

  std::optional<ui::ColorProviderKey::SchemeVariant> scheme =
      theme->scheme_variant();
  if (scheme) {
    info->scheme_variant = VariantToScheme(*scheme);

    // Only set seed color if we also have a `scheme`. Color palette generation
    // is more predictable this way.
    std::optional<SkColor> user_color = theme->user_color();
    if (user_color.has_value()) {
      info->seed_color = *user_color;
    }
  }

  return info;
}

NativeThemeServiceAsh::NativeThemeServiceAsh() = default;

NativeThemeServiceAsh::~NativeThemeServiceAsh() = default;

void NativeThemeServiceAsh::BindReceiver(
    mojo::PendingReceiver<mojom::NativeThemeService> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void NativeThemeServiceAsh::AddNativeThemeInfoObserver(
    mojo::PendingRemote<mojom::NativeThemeInfoObserver> observer) {
  // Fire the observer with the initial value.
  mojo::Remote<mojom::NativeThemeInfoObserver> remote(std::move(observer));
  remote->OnNativeThemeInfoChanged(GetNativeThemeInfo());

  dispatcher_.observers_.Add(std::move(remote));
}

}  // namespace crosapi