123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "fuchsia_web/webengine/browser/theme_manager.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/check.h"
- #include "base/fuchsia/fuchsia_logging.h"
- #include "third_party/blink/public/common/web_preferences/web_preferences.h"
- #include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom.h"
- #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
- namespace {
- using blink::mojom::PreferredColorScheme;
- using fuchsia::settings::ThemeType;
- constexpr PreferredColorScheme kFallbackColorScheme =
- PreferredColorScheme::kLight;
- PreferredColorScheme ThemeTypeToBlinkScheme(ThemeType type) {
- switch (type) {
- case ThemeType::LIGHT:
- return PreferredColorScheme::kLight;
- case ThemeType::DARK:
- return PreferredColorScheme::kDark;
- default:
- NOTREACHED();
- return kFallbackColorScheme;
- }
- }
- } // namespace
- ThemeManager::ThemeManager(content::WebContents* web_contents,
- base::OnceClosure on_display_error)
- : web_contents_(web_contents),
- on_display_error_(std::move(on_display_error)) {
- DCHECK(web_contents_);
- // Per the FIDL API, the default theme is LIGHT.
- SetTheme(ThemeType::LIGHT);
- }
- ThemeManager::~ThemeManager() = default;
- void ThemeManager::SetTheme(ThemeType theme) {
- requested_theme_ = theme;
- if (theme == ThemeType::DEFAULT) {
- if (!EnsureDisplayService()) {
- OnDisplayServiceMissing();
- return;
- }
- }
- }
- bool ThemeManager::EnsureDisplayService() {
- if (observed_display_service_error_)
- return false;
- if (display_service_)
- return true;
- display_service_ = base::ComponentContextForProcess()
- ->svc()
- ->Connect<fuchsia::settings::Display>();
- display_service_.set_error_handler([this](zx_status_t status) {
- ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
- << "fuchsia.settings.Display disconnected.";
- observed_display_service_error_ = true;
- // If the channel to the Display service was dropped before we received a
- // response from WatchForDisplayChanges, then it's likely that the service
- // isn't available in the namespace at all, which should be reported as
- // an error on the Frame.
- // Otherwise, if a failure was detected for a Display that was previously
- // functioning, it should be treated as a transient issue and the last known
- // system theme should be used.
- if (requested_theme_ && (*requested_theme_ == ThemeType::DEFAULT) &&
- !did_receive_first_watch_result_) {
- OnDisplayServiceMissing();
- }
- });
- WatchForDisplayChanges();
- return true;
- }
- void ThemeManager::OnDisplayServiceMissing() {
- LOG(ERROR) << "DEFAULT theme requires access to the "
- "`fuchsia.settings.Display` service to work.";
- if (on_display_error_)
- std::move(on_display_error_).Run();
- }
- void ThemeManager::ApplyThemeToWebPreferences(
- blink::web_pref::WebPreferences* web_prefs) {
- DCHECK(requested_theme_);
- if (requested_theme_ == ThemeType::DEFAULT) {
- if (!system_theme_) {
- // Defer theme application until we receive a system theme.
- return;
- }
- web_prefs->preferred_color_scheme = ThemeTypeToBlinkScheme(*system_theme_);
- } else {
- DCHECK(requested_theme_ == ThemeType::LIGHT ||
- requested_theme_ == ThemeType::DARK);
- web_prefs->preferred_color_scheme =
- ThemeTypeToBlinkScheme(*requested_theme_);
- }
- }
- void ThemeManager::WatchForDisplayChanges() {
- DCHECK(display_service_);
- // Will reply immediately for the first call of Watch(). Subsequent calls to
- // Watch() will be replied to as changes occur.
- display_service_->Watch(
- fit::bind_member(this, &ThemeManager::OnWatchResultReceived));
- }
- void ThemeManager::OnWatchResultReceived(
- fuchsia::settings::DisplaySettings settings) {
- did_receive_first_watch_result_ = true;
- if (settings.has_theme() && settings.theme().has_theme_type() &&
- (settings.theme().theme_type() == ThemeType::DARK ||
- settings.theme().theme_type() == ThemeType::LIGHT)) {
- system_theme_ = settings.theme().theme_type();
- } else {
- system_theme_ = absl::nullopt;
- }
- web_contents_->OnWebPreferencesChanged();
- WatchForDisplayChanges();
- }
|