chromium/chrome/browser/ash/child_accounts/time_limit_test_utils.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/child_accounts/time_limit_test_utils.h"

#include <optional>
#include <utility>

#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"

namespace ash {
namespace time_limit_test_utils {
namespace {

// Definition of private constants.
constexpr char kTimeLimitLastUpdatedAt[] = "last_updated_millis";
constexpr char kTimeWindowLimit[] = "time_window_limit";
constexpr char kTimeUsageLimit[] = "time_usage_limit";
constexpr char kUsageLimitResetAt[] = "reset_at";
constexpr char kUsageLimitUsageQuota[] = "usage_quota_mins";
constexpr char kWindowLimitEntries[] = "entries";
constexpr char kWindowLimitEntryEffectiveDay[] = "effective_day";
constexpr char kWindowLimitEntryEndsAt[] = "ends_at";
constexpr char kWindowLimitEntryStartsAt[] = "starts_at";
constexpr char kWindowLimitEntryTimeHour[] = "hour";
constexpr char kWindowLimitEntryTimeMinute[] = "minute";

}  // namespace

// Definition of public constants.
const char kMonday[] = "MONDAY";
const char kTuesday[] = "TUESDAY";
const char kWednesday[] = "WEDNESDAY";
const char kThursday[] = "THURSDAY";
const char kFriday[] = "FRIDAY";
const char kSaturday[] = "SATURDAY";
const char kSunday[] = "SUNDAY";

base::Time TimeFromString(const char* time_string) {
  base::Time time;
  if (!base::Time::FromUTCString(time_string, &time))
    LOG(ERROR) << "Wrong time string format.";

  return time;
}

std::string CreatePolicyTimestamp(const char* time_string) {
  base::Time time = TimeFromString(time_string);
  return CreatePolicyTimestamp(time);
}

std::string CreatePolicyTimestamp(base::Time time) {
  return base::NumberToString(
      (time - base::Time::UnixEpoch()).InMilliseconds());
}

base::TimeDelta CreateTime(int hour, int minute) {
  DCHECK_LT(hour, 24);
  DCHECK_GE(hour, 0);
  DCHECK_LT(minute, 60);
  DCHECK_GE(minute, 0);
  return base::Minutes(hour * 60 + minute);
}

base::Value::Dict CreatePolicyTime(base::TimeDelta time) {
  DCHECK_EQ(time.InNanoseconds() % base::Minutes(1).InNanoseconds(), 0);
  DCHECK_LT(time, base::Hours(24));

  int hour = time.InHours();
  int minute = time.InMinutes() - time.InHours() * base::Hours(1).InMinutes();
  base::Value::Dict policyTime;
  policyTime.Set(kWindowLimitEntryTimeHour, base::Value(hour));
  policyTime.Set(kWindowLimitEntryTimeMinute, base::Value(minute));
  return policyTime;
}

base::Value::Dict CreateTimeWindow(const std::string& day,
                                   base::TimeDelta start_time,
                                   base::TimeDelta end_time,
                                   base::Time last_updated) {
  base::Value::Dict time_window;
  time_window.Set(kWindowLimitEntryEffectiveDay, base::Value(day));
  time_window.Set(kWindowLimitEntryStartsAt, CreatePolicyTime(start_time));
  time_window.Set(kWindowLimitEntryEndsAt, CreatePolicyTime(end_time));
  time_window.Set(kTimeLimitLastUpdatedAt,
                  base::Value(CreatePolicyTimestamp(last_updated)));
  return time_window;
}

base::Value::Dict CreateTimeUsage(base::TimeDelta usage_quota,
                                  base::Time last_updated) {
  base::Value::Dict time_usage;
  time_usage.Set(kUsageLimitUsageQuota, base::Value(usage_quota.InMinutes()));
  time_usage.Set(kTimeLimitLastUpdatedAt,
                 base::Value(CreatePolicyTimestamp(last_updated)));
  return time_usage;
}

base::Value::Dict CreateTimeLimitPolicy(base::TimeDelta reset_time) {
  base::Value::Dict time_usage_limit;
  time_usage_limit.Set(kUsageLimitResetAt, CreatePolicyTime(reset_time));

  base::Value::Dict time_limit;
  time_limit.Set(kTimeUsageLimit, std::move(time_usage_limit));

  return time_limit;
}

void AddTimeUsageLimit(base::Value::Dict* policy,
                       std::string day,
                       base::TimeDelta quota,
                       base::Time last_updated) {
  // Asserts that the usage limit quota in minutes corresponds to an integer
  // number.
  DCHECK_EQ(quota.InNanoseconds() % base::Minutes(1).InNanoseconds(), 0);
  DCHECK_LT(quota, base::Hours(24));

  base::ranges::transform(day, day.begin(), ::tolower);
  policy->Find(kTimeUsageLimit)
      ->GetDict()
      .Set(day, CreateTimeUsage(quota, last_updated));
}

void AddTimeWindowLimit(base::Value::Dict* policy,
                        const std::string& day,
                        base::TimeDelta start_time,
                        base::TimeDelta end_time,
                        base::Time last_updated) {
  base::Value::Dict* time_window_limit = policy->EnsureDict(kTimeWindowLimit);
  base::Value::List* window_limit_entries =
      time_window_limit->EnsureList(kWindowLimitEntries);
  window_limit_entries->Append(
      CreateTimeWindow(day, start_time, end_time, last_updated));
}

void AddOverride(base::Value::Dict* policy,
                 usage_time_limit::TimeLimitOverride::Action action,
                 base::Time created_at) {
  base::Value::List* overrides = policy->EnsureList(
      usage_time_limit::TimeLimitOverride::kOverridesDictKey);
  usage_time_limit::TimeLimitOverride new_override(action, created_at,
                                                   std::nullopt);
  overrides->Append(new_override.ToDictionary());
}

void AddOverrideWithDuration(base::Value::Dict* policy,
                             usage_time_limit::TimeLimitOverride::Action action,
                             base::Time created_at,
                             base::TimeDelta duration) {
  base::Value::List* overrides = policy->EnsureList(
      usage_time_limit::TimeLimitOverride::kOverridesDictKey);
  usage_time_limit::TimeLimitOverride new_override(action, created_at,
                                                   duration);
  overrides->Append(new_override.ToDictionary());
}

std::string PolicyToString(const base::Value::Dict& policy) {
  std::string json_string;
  base::JSONWriter::Write(policy, &json_string);
  return json_string;
}

}  // namespace time_limit_test_utils
}  // namespace ash