blob: 5955912acf58cdb0acbb896334df198bdc5ce67c [file] [log] [blame]
// Copyright 2019 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/child_accounts/time_limit_override.h"
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
namespace chromeos {
namespace usage_time_limit {
namespace {
constexpr char kOverrideAction[] = "action";
constexpr char kOverrideActionCreatedAt[] = "created_at_millis";
constexpr char kOverrideActionDurationMins[] = "duration_mins";
constexpr char kOverrideActionLock[] = "LOCK";
constexpr char kOverrideActionUnlock[] = "UNLOCK";
constexpr char kOverrideActionSpecificData[] = "action_specific_data";
constexpr char kOverrideActionDuration[] = "duration_mins";
// Returns string containing |timestamp| int64_t value in milliseconds. This is
// how timestamp is sent in a policy.
std::string PolicyTimestamp(base::Time timestamp) {
return std::to_string((timestamp - base::Time::UnixEpoch()).InMilliseconds());
}
} // namespace
// static
constexpr char TimeLimitOverride::kOverridesDictKey[];
// static
std::string TimeLimitOverride::ActionToString(Action action) {
switch (action) {
case Action::kLock:
return kOverrideActionLock;
case Action::kUnlock:
return kOverrideActionUnlock;
}
}
// static
base::Optional<TimeLimitOverride> TimeLimitOverride::FromDictionary(
const base::Value* dict) {
if (!dict || !dict->is_dict()) {
DLOG(ERROR) << "Override entry is not a dictionary";
return base::nullopt;
}
const std::string* action_string = dict->FindStringKey(kOverrideAction);
if (!action_string || action_string->empty()) {
DLOG(ERROR) << "Invalid override action.";
return base::nullopt;
}
const std::string* creation_time_string =
dict->FindStringKey(kOverrideActionCreatedAt);
int64_t creation_time_millis;
if (!creation_time_string || creation_time_string->empty() ||
!base::StringToInt64(*creation_time_string, &creation_time_millis)) {
DLOG(ERROR) << "Invalid override creation time.";
return base::nullopt;
}
Action action =
*action_string == kOverrideActionLock ? Action::kLock : Action::kUnlock;
base::Time creation_time =
base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(creation_time_millis);
const base::Value* duration_value = dict->FindPath(
{kOverrideActionSpecificData, kOverrideActionDurationMins});
base::Optional<base::TimeDelta> duration =
duration_value ? base::TimeDelta::FromMinutes(duration_value->GetInt())
: base::Optional<base::TimeDelta>();
return TimeLimitOverride(action, creation_time, duration);
}
// static
base::Optional<TimeLimitOverride> TimeLimitOverride::MostRecentFromList(
const base::Value* list) {
if (!list || !list->is_list()) {
DLOG(ERROR) << "Override entries should be a list.";
return base::nullopt;
}
// The most recent override created.
base::Optional<TimeLimitOverride> last_override;
for (const base::Value& override_value : list->GetList()) {
base::Optional<TimeLimitOverride> current_override =
FromDictionary(&override_value);
if (!current_override.has_value()) {
DLOG(ERROR) << "Invalid override entry";
continue;
}
if (!last_override.has_value() ||
(current_override->created_at() > last_override->created_at())) {
last_override = std::move(current_override);
}
}
return last_override;
}
TimeLimitOverride::TimeLimitOverride(Action action,
base::Time created_at,
base::Optional<base::TimeDelta> duration)
: action_(action), created_at_(created_at), duration_(duration) {}
TimeLimitOverride::~TimeLimitOverride() = default;
TimeLimitOverride::TimeLimitOverride(TimeLimitOverride&&) = default;
TimeLimitOverride& TimeLimitOverride::operator=(TimeLimitOverride&&) = default;
bool TimeLimitOverride::IsLock() const {
return action_ == Action::kLock;
}
base::Value TimeLimitOverride::ToDictionary() const {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey(kOverrideAction, base::Value(ActionToString(action_)));
dict.SetKey(kOverrideActionCreatedAt,
base::Value(PolicyTimestamp(created_at_)));
if (duration_.has_value()) {
base::Value duration_dict(base::Value::Type::DICTIONARY);
duration_dict.SetKey(kOverrideActionDuration,
base::Value(duration_->InMinutes()));
dict.SetKey(kOverrideActionSpecificData, std::move(duration_dict));
}
return dict;
}
} // namespace usage_time_limit
} // namespace chromeos