// Copyright 2015 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 "chrome/browser/chromeos/system/system_clock.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/system/system_clock_observer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/pref_names.h" #include "chromeos/login/login_state.h" #include "chromeos/settings/cros_settings_names.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/notification_service.h" namespace chromeos { namespace system { namespace { void SetShouldUse24HourClock(bool use_24_hour_clock) { user_manager::User* const user = user_manager::UserManager::Get()->GetActiveUser(); CHECK(user); Profile* const profile = ProfileHelper::Get()->GetProfileByUser(user); if (!profile) return; // May occur in tests or if not running on a device. OwnerSettingsServiceChromeOS* const service = OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(profile); CHECK(service); service->SetBoolean(kSystemUse24HourClock, use_24_hour_clock); } } // anonymous namespace SystemClock::SystemClock() : user_pod_was_focused_(false), last_focused_pod_hour_clock_type_(base::k12HourClock), user_profile_(NULL), device_settings_observer_(CrosSettings::Get()->AddSettingsObserver( kSystemUse24HourClock, base::Bind(&SystemClock::OnSystemPrefChanged, base::Unretained(this)))) { if (LoginState::IsInitialized()) LoginState::Get()->AddObserver(this); // Register notifications on construction so that events such as // PROFILE_CREATED do not get missed if they happen before Initialize(). registrar_.reset(new content::NotificationRegistrar); if (!LoginState::IsInitialized() || LoginState::Get()->GetLoggedInUserType() == LoginState::LOGGED_IN_USER_NONE) { registrar_->Add(this, chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources()); } registrar_->Add(this, chrome::NOTIFICATION_PROFILE_CREATED, content::NotificationService::AllSources()); registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::NotificationService::AllSources()); registrar_->Add(this, chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, content::NotificationService::AllSources()); user_manager::UserManager::Get()->AddSessionStateObserver(this); } SystemClock::~SystemClock() { registrar_.reset(); device_settings_observer_.reset(); if (LoginState::IsInitialized()) LoginState::Get()->RemoveObserver(this); if (user_manager::UserManager::IsInitialized()) user_manager::UserManager::Get()->RemoveSessionStateObserver(this); } // LoginState::Observer overrides. void SystemClock::LoggedInStateChanged() { // It apparently sometimes takes a while after login before the current user // is recognized as the owner. Make sure that the system-wide clock setting // is updated when the recognition eventually happens (crbug.com/278601). if (user_manager::UserManager::Get()->IsCurrentUserOwner()) SetShouldUse24HourClock(ShouldUse24HourClock()); } // content::NotificationObserver implementation. void SystemClock::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED: { UpdateClockType(); break; } case chrome::NOTIFICATION_PROFILE_CREATED: { OnActiveProfileChanged(content::Source(source).ptr()); registrar_->Remove(this, chrome::NOTIFICATION_PROFILE_CREATED, content::NotificationService::AllSources()); break; } case chrome::NOTIFICATION_PROFILE_DESTROYED: { if (OnProfileDestroyed(content::Source(source).ptr())) { registrar_->Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::NotificationService::AllSources()); } break; } case chrome::NOTIFICATION_SESSION_STARTED: { OnActiveProfileChanged(ProfileManager::GetActiveUserProfile()); break; } default: NOTREACHED(); } } void SystemClock::ActiveUserChanged(const user_manager::User* /*user*/) { UpdateClockType(); } void SystemClock::AddObserver(SystemClockObserver* observer) { observer_list_.AddObserver(observer); } void SystemClock::RemoveObserver(SystemClockObserver* observer) { observer_list_.RemoveObserver(observer); } void SystemClock::OnActiveProfileChanged(Profile* profile) { user_profile_ = profile; PrefService* prefs = profile->GetPrefs(); user_pref_registrar_.reset(new PrefChangeRegistrar); user_pref_registrar_->Init(prefs); user_pref_registrar_->Add( prefs::kUse24HourClock, base::Bind(&SystemClock::UpdateClockType, base::Unretained(this))); } bool SystemClock::OnProfileDestroyed(Profile* profile) { if (profile != user_profile_) return false; user_pref_registrar_.reset(); user_profile_ = NULL; return true; } void SystemClock::SetLastFocusedPodHourClockType( base::HourClockType hour_clock_type) { user_pod_was_focused_ = true; last_focused_pod_hour_clock_type_ = hour_clock_type; UpdateClockType(); } bool SystemClock::ShouldUse24HourClock() const { // On login screen and in guest mode owner default is used for // kUse24HourClock preference. const chromeos::LoginState::LoggedInUserType status = LoginState::IsInitialized() ? LoginState::Get()->GetLoggedInUserType() : LoginState::LOGGED_IN_USER_NONE; if (status == LoginState::LOGGED_IN_USER_NONE && user_pod_was_focused_) return last_focused_pod_hour_clock_type_ == base::k24HourClock; const CrosSettings* const cros_settings = CrosSettings::Get(); bool system_use_24_hour_clock = true; const bool system_value_found = cros_settings->GetBoolean( kSystemUse24HourClock, &system_use_24_hour_clock); if ((status == LoginState::LOGGED_IN_USER_NONE) || !user_pref_registrar_) { return (system_value_found ? system_use_24_hour_clock : (base::GetHourClockType() == base::k24HourClock)); } const PrefService::Preference* user_pref = user_pref_registrar_->prefs()->FindPreference(prefs::kUse24HourClock); if (status == LoginState::LOGGED_IN_USER_GUEST && user_pref->IsDefaultValue()) { return (system_value_found ? system_use_24_hour_clock : (base::GetHourClockType() == base::k24HourClock)); } user_manager::User* active_user = user_manager::UserManager::Get()->GetActiveUser(); if (active_user) { Profile* user_profile = ProfileHelper::Get()->GetProfileByUser(active_user); if (user_profile) { user_pref = user_profile->GetPrefs()->FindPreference(prefs::kUse24HourClock); } } bool use_24_hour_clock = true; user_pref->GetValue()->GetAsBoolean(&use_24_hour_clock); return use_24_hour_clock; } void SystemClock::OnSystemPrefChanged() { UpdateClockType(); } void SystemClock::UpdateClockType() { // This also works for enterprise-managed devices because they never have // a local owner. if (user_manager::UserManager::Get()->IsCurrentUserOwner()) SetShouldUse24HourClock(ShouldUse24HourClock()); FOR_EACH_OBSERVER(SystemClockObserver, observer_list_, OnSystemClockChanged(this)); } } // namespace system } // namespace chromeos