blob: 801ebf9866e5bcaeb6cdf3f3d63775d78ba20123 [file] [log] [blame]
// 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 "components/arc/enterprise/snapshot_hours_policy_service.h"
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/time/default_clock.h"
#include "base/time/tick_clock.h"
#include "base/values.h"
#include "chromeos/policy/weekly_time/time_utils.h"
#include "components/arc/arc_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
namespace arc {
namespace data_snapshotd {
SnapshotHoursPolicyService::SnapshotHoursPolicyService(PrefService* local_state)
: local_state_(local_state) {
DCHECK(local_state_);
pref_change_registrar_.Init(local_state_);
pref_change_registrar_.Add(
prefs::kArcSnapshotHours,
base::BindRepeating(&SnapshotHoursPolicyService::UpdatePolicy,
weak_ptr_factory_.GetWeakPtr()));
UpdatePolicy();
}
SnapshotHoursPolicyService::~SnapshotHoursPolicyService() = default;
void SnapshotHoursPolicyService::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void SnapshotHoursPolicyService::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void SnapshotHoursPolicyService::StartObservingPrimaryProfilePrefs(
PrefService* profile_prefs) {
if (!user_manager::UserManager::Get() ||
!user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) {
// Do not care about ArcEnabled policy for other than MGS.
return;
}
profile_prefs_ = profile_prefs;
profile_pref_change_registrar_.Init(profile_prefs_);
profile_pref_change_registrar_.Add(
prefs::kArcEnabled,
base::BindRepeating(&SnapshotHoursPolicyService::UpdatePolicy,
weak_ptr_factory_.GetWeakPtr()));
UpdatePolicy();
}
void SnapshotHoursPolicyService::StopObservingPrimaryProfilePrefs() {
if (!profile_prefs_)
return;
profile_pref_change_registrar_.RemoveAll();
profile_prefs_ = nullptr;
UpdatePolicy();
}
void SnapshotHoursPolicyService::UpdatePolicy() {
intervals_.clear();
base::ScopedClosureRunner snapshot_disabler(
base::BindOnce(&SnapshotHoursPolicyService::DisableSnapshots,
weak_ptr_factory_.GetWeakPtr()));
if (!IsArcEnabled())
return;
const auto* dict = local_state_->GetDictionary(prefs::kArcSnapshotHours);
if (!dict)
return;
const auto* timezone = dict->FindStringKey("timezone");
if (!timezone)
return;
int offset;
if (!policy::weekly_time_utils::GetOffsetFromTimezoneToGmt(
*timezone, base::DefaultClock::GetInstance(), &offset)) {
return;
}
const auto* intervals = dict->FindListKey("intervals");
if (!intervals)
return;
for (const auto& entry : intervals->GetList()) {
if (!entry.is_dict())
continue;
auto interval =
policy::WeeklyTimeInterval::ExtractFromValue(&entry, -offset);
if (interval)
intervals_.push_back(*interval);
}
intervals_ = policy::weekly_time_utils::ConvertIntervalsToGmt(intervals_);
if (intervals_.empty())
return;
ignore_result(snapshot_disabler.Release());
EnableSnapshots();
}
void SnapshotHoursPolicyService::DisableSnapshots() {
if (!is_snapshot_enabled_)
return;
is_snapshot_enabled_ = false;
StopTimer();
SetEndTime(base::Time());
NotifySnapshotsDisabled();
}
void SnapshotHoursPolicyService::EnableSnapshots() {
if (is_snapshot_enabled_)
return;
is_snapshot_enabled_ = true;
UpdateTimer();
NotifySnapshotsEnabled();
}
void SnapshotHoursPolicyService::UpdateTimer() {
namespace wtu = ::policy::weekly_time_utils;
const base::Time now = base::Time::Now();
const bool in_interval = wtu::Contains(now, intervals_);
const base::Optional<base::Time> update_time =
wtu::GetNextEventTime(now, intervals_);
SetEndTime(in_interval ? update_time.value() : base::Time{});
if (update_time)
StartTimer(update_time.value());
else
StopTimer();
}
void SnapshotHoursPolicyService::StartTimer(const base::Time& update_time) {
timer_.Start(FROM_HERE, update_time,
base::BindOnce(&SnapshotHoursPolicyService::UpdateTimer,
weak_ptr_factory_.GetWeakPtr()));
}
void SnapshotHoursPolicyService::StopTimer() {
timer_.Stop();
}
void SnapshotHoursPolicyService::SetEndTime(base::Time end_time) {
if (snapshot_update_end_time_ == end_time)
return;
snapshot_update_end_time_ = end_time;
NotifySnapshotUpdateEndTimeChanged();
}
void SnapshotHoursPolicyService::NotifySnapshotsDisabled() {
for (auto& observer : observers_)
observer.OnSnapshotsDisabled();
}
void SnapshotHoursPolicyService::NotifySnapshotsEnabled() {
for (auto& observer : observers_)
observer.OnSnapshotsEnabled();
}
void SnapshotHoursPolicyService::NotifySnapshotUpdateEndTimeChanged() {
for (auto& observer : observers_)
observer.OnSnapshotUpdateEndTimeChanged();
}
bool SnapshotHoursPolicyService::IsArcEnabled() const {
// Assume ARC is enabled if there is no profile prefs.
return !profile_prefs_ || profile_prefs_->GetBoolean(prefs::kArcEnabled);
}
} // namespace data_snapshotd
} // namespace arc