blob: 8e8a9e58103ac623682ad0ac3d302312b5c8367a [file] [log] [blame]
// 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 <memory>
#include "base/bind.h"
#include "base/logging.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/common/pref_names.h"
#include "chromeos/login/login_state/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();
if (!user)
return; // May occur if not running on a device.
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() {
device_settings_observer_ = CrosSettings::Get()->AddSettingsObserver(
kSystemUse24HourClock, base::Bind(&SystemClock::OnSystemPrefChanged,
weak_ptr_factory_.GetWeakPtr()));
if (LoginState::IsInitialized())
LoginState::Get()->AddObserver(this);
user_manager::UserManager::Get()->AddSessionStateObserver(this);
}
SystemClock::~SystemClock() {
if (LoginState::IsInitialized())
LoginState::Get()->RemoveObserver(this);
if (user_manager::UserManager::IsInitialized())
user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
}
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());
}
void SystemClock::OnProfileWillBeDestroyed(Profile* profile) {
DCHECK_EQ(profile, user_profile_);
profile_observer_.Remove(profile);
user_pref_registrar_.reset();
user_profile_ = nullptr;
}
void SystemClock::ActiveUserChanged(user_manager::User* active_user) {
if (!active_user)
return;
active_user->AddProfileCreatedObserver(
base::BindOnce(&SystemClock::SetProfileByUser,
weak_ptr_factory_.GetWeakPtr(), active_user));
}
void SystemClock::AddObserver(SystemClockObserver* observer) {
observer_list_.AddObserver(observer);
}
void SystemClock::RemoveObserver(SystemClockObserver* observer) {
observer_list_.RemoveObserver(observer);
}
void SystemClock::SetProfileByUser(const user_manager::User* user) {
SetProfile(ProfileHelper::Get()->GetProfileByUser(user));
}
void SystemClock::SetProfile(Profile* profile) {
user_profile_ = profile;
profile_observer_.RemoveAll();
profile_observer_.Add(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)));
UpdateClockType();
}
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 {
// default is used for kUse24HourClock preference on login screen and whenever
// set so in user's 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);
const bool default_value =
system_value_found ? system_use_24_hour_clock
: (base::GetHourClockType() == base::k24HourClock);
if ((status == LoginState::LOGGED_IN_USER_NONE) || !user_pref_registrar_)
return default_value;
const PrefService::Preference* user_pref =
user_pref_registrar_->prefs()->FindPreference(prefs::kUse24HourClock);
if (status == LoginState::LOGGED_IN_USER_GUEST && user_pref->IsDefaultValue())
return default_value;
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);
}
}
if (status != LoginState::LOGGED_IN_USER_REGULAR &&
user_pref->IsDefaultValue()) {
return default_value;
}
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 (auto& observer : observer_list_)
observer.OnSystemClockChanged(this);
}
} // namespace system
} // namespace chromeos