Commit fb0b134a authored by Aga Wronska's avatar Aga Wronska Committed by Commit Bot

Reland "Parse PerAppTimeLimits policy"

This is a reland of c78cd05f

Bug: 1044733

Original change's description:
> Parse PerAppTimeLimits policy
>
> Parse PerAppTimeLimits policy received from the server and store
> app limits data in AppActivityRegistry.
> This will be followed up by processing app limits.
>
> Bug: 1015654
> Test: AppTimeTest
> Change-Id: I29691e0c801762a73f01cce217826423359957eb
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2001411
> Reviewed-by: Yilkal Abe <yilkal@chromium.org>
> Commit-Queue: Aga Wronska <agawronska@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#734123}

Bug: 1015654
Change-Id: I5fde631303ca519501220f60d5bd2fdc53759e0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2017184
Commit-Queue: Aga Wronska <agawronska@chromium.org>
Reviewed-by: default avatarYilkal Abe <yilkal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734627}
parent 25e9b059
......@@ -820,6 +820,8 @@ source_set("chromeos") {
"child_accounts/time_limits/app_time_controller.h",
"child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc",
"child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h",
"child_accounts/time_limits/app_time_policy_helpers.cc",
"child_accounts/time_limits/app_time_policy_helpers.h",
"child_accounts/time_limits/app_types.cc",
"child_accounts/time_limits/app_types.h",
"child_accounts/time_limits/web_time_limit_enforcer.cc",
......
......@@ -77,9 +77,8 @@ void ChildUserService::AppActivityReportSubmitted(
}
bool ChildUserService::WebTimeLimitReached() const {
if (!app_time_controller_)
if (!app_time_controller_ || !app_time_controller_->web_time_enforcer())
return false;
DCHECK(app_time_controller_->web_time_enforcer());
return app_time_controller_->web_time_enforcer()->blocked();
}
......
......@@ -49,6 +49,17 @@ enterprise_management::AppActivity::AppState AppStateForReporting(
} // namespace
AppActivityRegistry::TestApi::TestApi(AppActivityRegistry* registry)
: registry_(registry) {}
AppActivityRegistry::TestApi::~TestApi() = default;
const base::Optional<AppLimit>& AppActivityRegistry::TestApi::GetAppLimit(
const AppId& app_id) const {
DCHECK(base::Contains(registry_->activity_registry_, app_id));
return registry_->activity_registry_.at(app_id).limit;
}
AppActivityRegistry::AppDetails::AppDetails() = default;
AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity)
......@@ -76,6 +87,8 @@ void AppActivityRegistry::OnAppInstalled(const AppId& app_id) {
// sessions and app service does not. Make sure not to override cached state.
if (!base::Contains(activity_registry_, app_id))
Add(app_id);
// TODO(agawronska): Update the limit from policy when new app is installed.
}
void AppActivityRegistry::OnAppUninstalled(const AppId& app_id) {
......@@ -229,6 +242,21 @@ void AppActivityRegistry::CleanRegistry(base::Time timestamp) {
}
}
void AppActivityRegistry::UpdateAppLimits(
const std::map<AppId, AppLimit>& app_limits) {
for (auto& entry : activity_registry_) {
const AppId& app_id = entry.first;
const base::Optional<AppLimit>& app_limit = entry.second.limit;
if (!base::Contains(app_limits, app_id)) {
if (app_limit)
entry.second.limit = base::nullopt;
} else {
entry.second.limit = app_limits.at(app_id);
}
}
// TODO(agawronska): Propagate information about the limit changes.
}
void AppActivityRegistry::Add(const AppId& app_id) {
auto result = activity_registry_.emplace(
app_id, AppDetails(AppActivity(AppState::kAvailable)));
......
......@@ -8,6 +8,7 @@
#include <map>
#include <set>
#include "base/optional.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h"
......@@ -30,6 +31,18 @@ namespace app_time {
// 30 days if upload did not happen.
class AppActivityRegistry : public AppServiceWrapper::EventListener {
public:
// Used for tests to get internal implementation details.
class TestApi {
public:
explicit TestApi(AppActivityRegistry* registry);
~TestApi();
const base::Optional<AppLimit>& GetAppLimit(const AppId& app_id) const;
private:
AppActivityRegistry* const registry_;
};
explicit AppActivityRegistry(AppServiceWrapper* app_service_wrapper);
AppActivityRegistry(const AppActivityRegistry&) = delete;
AppActivityRegistry& operator=(const AppActivityRegistry&) = delete;
......@@ -67,6 +80,9 @@ class AppActivityRegistry : public AppServiceWrapper::EventListener {
// data left.
void CleanRegistry(base::Time timestamp);
// Updates time limits for the installed apps.
void UpdateAppLimits(const std::map<AppId, AppLimit>& app_limits);
private:
// Bundles detailed data stored for a specific app.
struct AppDetails {
......
......@@ -7,10 +7,12 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/values.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
......@@ -22,6 +24,15 @@
namespace chromeos {
namespace app_time {
AppTimeController::TestApi::TestApi(AppTimeController* controller)
: controller_(controller) {}
AppTimeController::TestApi::~TestApi() = default;
AppActivityRegistry* AppTimeController::TestApi::app_registry() {
return controller_->app_registry_.get();
}
// static
bool AppTimeController::ArePerAppTimeLimitsEnabled() {
return base::FeatureList::IsEnabled(features::kPerAppTimeLimits);
......@@ -77,7 +88,21 @@ void AppTimeController::RegisterProfilePrefObservers(
}
void AppTimeController::TimeLimitsPolicyUpdated(const std::string& pref_name) {
NOTIMPLEMENTED();
const base::Value* policy =
pref_registrar_->prefs()->GetDictionary(prefs::kPerAppTimeLimitsPolicy);
if (!policy || !policy->is_dict()) {
LOG(WARNING) << "Invalid PerAppTimeLimits policy.";
return;
}
app_registry_->UpdateAppLimits(policy::AppLimitsFromDict(*policy));
base::Optional<base::TimeDelta> new_reset_time =
policy::ResetTimeFromDict(*policy);
// TODO(agawronska): Propagate the information about reset time change.
if (new_reset_time && *new_reset_time != limits_reset_time_)
limits_reset_time_ = *new_reset_time;
}
void AppTimeController::TimeLimitsWhitelistPolicyUpdated(
......
......@@ -7,6 +7,8 @@
#include <memory>
#include "base/time/time.h"
class Profile;
class PrefRegistrySimple;
class PrefChangeRegistrar;
......@@ -23,6 +25,18 @@ class WebTimeLimitEnforcer;
// Coordinates per-app time limit for child user.
class AppTimeController {
public:
// Used for tests to get internal implementation details.
class TestApi {
public:
explicit TestApi(AppTimeController* controller);
~TestApi();
AppActivityRegistry* app_registry();
private:
AppTimeController* const controller_;
};
static bool ArePerAppTimeLimitsEnabled();
static bool IsAppActivityReportingEnabled();
......@@ -53,6 +67,10 @@ class AppTimeController {
void TimeLimitsPolicyUpdated(const std::string& pref_name);
void TimeLimitsWhitelistPolicyUpdated(const std::string& pref_name);
// The time of the day when app time limits should be reset.
// Defaults to 6am.
base::TimeDelta limits_reset_time_ = base::TimeDelta::FromHours(6);
std::unique_ptr<AppServiceWrapper> app_service_wrapper_;
std::unique_ptr<AppActivityRegistry> app_registry_;
std::unique_ptr<WebTimeLimitEnforcer> web_time_enforcer_;
......
// 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 "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
namespace chromeos {
namespace app_time {
AppTimeLimitsPolicyBuilder::AppTimeLimitsPolicyBuilder() {
value_.SetKey(policy::kAppLimitsArray, base::Value(base::Value::Type::LIST));
value_.SetKey(policy::kResetAtDict,
base::Value(base::Value::Type::DICTIONARY));
}
AppTimeLimitsPolicyBuilder::~AppTimeLimitsPolicyBuilder() = default;
void AppTimeLimitsPolicyBuilder::AddAppLimit(const AppId& app_id,
const AppLimit& app_limit) {
base::Value new_entry(base::Value::Type::DICTIONARY);
new_entry.SetKey(policy::kAppInfoDict, policy::AppIdToDict(app_id));
base::Value app_limit_value = policy::AppLimitToDict(app_limit);
new_entry.MergeDictionary(&app_limit_value);
base::Value* list = value_.FindListKey(policy::kAppLimitsArray);
DCHECK(list);
list->Append(std::move(new_entry));
}
void AppTimeLimitsPolicyBuilder::SetResetTime(int hour, int minutes) {
value_.SetKey(policy::kResetAtDict, policy::ResetTimeToDict(hour, minutes));
}
} // namespace app_time
} // namespace chromeos
// 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.
#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_
#include "base/values.h"
namespace chromeos {
namespace app_time {
class AppId;
class AppLimit;
// Builds PerAppTimeLimits policy for tests.
class AppTimeLimitsPolicyBuilder {
public:
AppTimeLimitsPolicyBuilder();
AppTimeLimitsPolicyBuilder(const AppTimeLimitsPolicyBuilder&) = delete;
AppTimeLimitsPolicyBuilder& operator=(const AppTimeLimitsPolicyBuilder&) =
delete;
~AppTimeLimitsPolicyBuilder();
// Adds app limit data to the policy.
void AddAppLimit(const AppId& app_id, const AppLimit& app_limit);
// Sets reset time in the policy.
void SetResetTime(int hour, int minutes);
const base::Value& value() const { return value_; }
private:
base::Value value_{base::Value::Type::DICTIONARY};
};
} // namespace app_time
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_
......@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
namespace chromeos {
namespace app_time {
......@@ -16,8 +18,8 @@ AppTimeLimitsWhitelistPolicyBuilder::~AppTimeLimitsWhitelistPolicyBuilder() =
void AppTimeLimitsWhitelistPolicyBuilder::SetUp() {
value_ = base::Value(base::Value::Type::DICTIONARY);
value_.SetKey(kUrlList, base::Value(base::Value::Type::LIST));
value_.SetKey(kAppList, base::Value(base::Value::Type::LIST));
value_.SetKey(policy::kUrlList, base::Value(base::Value::Type::LIST));
value_.SetKey(policy::kAppList, base::Value(base::Value::Type::LIST));
}
void AppTimeLimitsWhitelistPolicyBuilder::Clear() {
......@@ -28,16 +30,17 @@ void AppTimeLimitsWhitelistPolicyBuilder::Clear() {
void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistUrlList(
const std::string& scheme) {
AppendToList(kUrlList, base::Value(scheme));
AppendToList(policy::kUrlList, base::Value(scheme));
}
void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistAppList(
const AppId& app_id) {
base::Value value_to_append(base::Value::Type::DICTIONARY);
value_to_append.SetKey(kAppId, base::Value(app_id.app_id()));
value_to_append.SetKey(kAppType,
base::Value(AppTypeToString(app_id.app_type())));
AppendToList(kAppList, std::move(value_to_append));
value_to_append.SetKey(policy::kAppId, base::Value(app_id.app_id()));
value_to_append.SetKey(
policy::kAppType,
base::Value(policy::AppTypeToPolicyString(app_id.app_type())));
AppendToList(policy::kAppList, std::move(value_to_append));
}
void AppTimeLimitsWhitelistPolicyBuilder::AppendToList(const std::string& key,
......
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_WHITELIST_POLICY_TEST_UTILS_H_
#include <string>
#include "base/values.h"
namespace chromeos {
......
......@@ -4,48 +4,13 @@
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h"
#include "base/optional.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
namespace chromeos {
namespace app_time {
const char kUrlList[] = "url_list";
const char kAppList[] = "app_list";
const char kAppId[] = "app_id";
const char kAppType[] = "app_type";
std::string AppTypeToString(apps::mojom::AppType app_type) {
switch (app_type) {
case apps::mojom::AppType::kArc:
return "ARC";
case apps::mojom::AppType::kBuiltIn:
return "BUILT-IN";
case apps::mojom::AppType::kCrostini:
return "CROSTINI";
case apps::mojom::AppType::kExtension:
return "EXTENSION";
case apps::mojom::AppType::kWeb:
return "WEB";
default:
NOTREACHED();
return "";
}
}
apps::mojom::AppType StringToAppType(const std::string& app_type) {
if (app_type == "ARC")
return apps::mojom::AppType::kArc;
if (app_type == "BUILD-IN")
return apps::mojom::AppType::kBuiltIn;
if (app_type == "CROSTINI")
return apps::mojom::AppType::kCrostini;
if (app_type == "EXTENSION")
return apps::mojom::AppType::kExtension;
if (app_type == "WEB")
return apps::mojom::AppType::kWeb;
NOTREACHED();
return apps::mojom::AppType::kUnknown;
}
AppTimeLimitsWhitelistPolicyWrapper::AppTimeLimitsWhitelistPolicyWrapper(
const base::Value* value)
: value_(value) {}
......@@ -55,7 +20,7 @@ AppTimeLimitsWhitelistPolicyWrapper::~AppTimeLimitsWhitelistPolicyWrapper() =
std::vector<std::string>
AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const {
const base::Value* list = value_->FindListKey(kUrlList);
const base::Value* list = value_->FindListKey(policy::kUrlList);
DCHECK(list);
base::Value::ConstListView list_view = list->GetList();
......@@ -68,19 +33,15 @@ AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const {
std::vector<AppId> AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistAppList()
const {
const base::Value* app_list = value_->FindListKey(kAppList);
const base::Value* app_list = value_->FindListKey(policy::kAppList);
DCHECK(app_list);
base::Value::ConstListView list_view = app_list->GetList();
std::vector<AppId> return_value;
for (const base::Value& value : list_view) {
const std::string* app_id = value.FindStringKey(kAppId);
DCHECK(app_id);
const std::string* app_type = value.FindStringKey(kAppType);
DCHECK(app_type);
return_value.push_back(AppId(StringToAppType(*app_type), *app_id));
base::Optional<AppId> app_id = policy::AppIdFromDict(value);
if (app_id)
return_value.push_back(*app_id);
}
return return_value;
......
......@@ -7,23 +7,14 @@
#include <string>
#include <vector>
#include "base/values.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
#include "base/values.h"
namespace chromeos {
namespace app_time {
class AppId;
extern const char kUrlList[];
extern const char kAppList[];
extern const char kAppId[];
extern const char kAppType[];
std::string AppTypeToString(apps::mojom::AppType app_type);
apps::mojom::AppType StringToAppType(const std::string& app_type);
class AppTimeLimitsWhitelistPolicyWrapper {
public:
explicit AppTimeLimitsWhitelistPolicyWrapper(const base::Value* value);
......
// 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_limits/app_time_policy_helpers.h"
#include <utility>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
namespace chromeos {
namespace app_time {
namespace policy {
const char kUrlList[] = "url_list";
const char kAppList[] = "app_list";
const char kAppId[] = "app_id";
const char kAppType[] = "app_type";
const char kAppLimitsArray[] = "app_limits";
const char kAppInfoDict[] = "app_info";
const char kRestrictionEnum[] = "restriction";
const char kDailyLimitInt[] = "daily_limit_mins";
const char kLastUpdatedString[] = "last_updated_millis";
const char kResetAtDict[] = "reset_at";
const char kHourInt[] = "hour";
const char kMinInt[] = "minute";
apps::mojom::AppType PolicyStringToAppType(const std::string& app_type) {
if (app_type == "ARC")
return apps::mojom::AppType::kArc;
if (app_type == "BUILD-IN")
return apps::mojom::AppType::kBuiltIn;
if (app_type == "CROSTINI")
return apps::mojom::AppType::kCrostini;
if (app_type == "EXTENSION")
return apps::mojom::AppType::kExtension;
if (app_type == "WEB")
return apps::mojom::AppType::kWeb;
NOTREACHED();
return apps::mojom::AppType::kUnknown;
}
std::string AppTypeToPolicyString(apps::mojom::AppType app_type) {
switch (app_type) {
case apps::mojom::AppType::kArc:
return "ARC";
case apps::mojom::AppType::kBuiltIn:
return "BUILT-IN";
case apps::mojom::AppType::kCrostini:
return "CROSTINI";
case apps::mojom::AppType::kExtension:
return "EXTENSION";
case apps::mojom::AppType::kWeb:
return "WEB";
default:
NOTREACHED();
return "";
}
}
AppRestriction PolicyStringToAppRestriction(const std::string& restriction) {
if (restriction == "BLOCK")
return AppRestriction::kBlocked;
if (restriction == "TIME_LIMIT")
return AppRestriction::kTimeLimit;
NOTREACHED();
return AppRestriction::kUnknown;
}
std::string AppRestrictionToPolicyString(const AppRestriction& restriction) {
switch (restriction) {
case AppRestriction::kBlocked:
return "BLOCK";
case AppRestriction::kTimeLimit:
return "TIME_LIMIT";
default:
NOTREACHED();
return "";
}
}
base::Optional<AppId> AppIdFromDict(const base::Value& dict) {
if (!dict.is_dict())
return base::nullopt;
const base::Value* app_info = dict.FindKey(kAppInfoDict);
if (!app_info || !app_info->is_dict()) {
DLOG(ERROR) << "Invalid app info dictionary.";
return base::nullopt;
}
const std::string* id = app_info->FindStringKey(kAppId);
if (!id || id->empty()) {
DLOG(ERROR) << "Invalid id.";
return base::nullopt;
}
const std::string* type_string = app_info->FindStringKey(kAppType);
if (!type_string || type_string->empty()) {
DLOG(ERROR) << "Invalid type.";
return base::nullopt;
}
return AppId(PolicyStringToAppType(*type_string), *id);
}
base::Value AppIdToDict(const AppId& app_id) {
base::Value value(base::Value::Type::DICTIONARY);
value.SetKey(kAppId, base::Value(app_id.app_id()));
value.SetKey(kAppType, base::Value(AppTypeToPolicyString(app_id.app_type())));
return value;
}
base::Optional<AppLimit> AppLimitFromDict(const base::Value& dict) {
if (!dict.is_dict())
return base::nullopt;
const std::string* restriction_string = dict.FindStringKey(kRestrictionEnum);
if (!restriction_string || restriction_string->empty()) {
DLOG(ERROR) << "Invalid restriction.";
return base::nullopt;
}
const AppRestriction restriction =
PolicyStringToAppRestriction(*restriction_string);
base::Optional<int> daily_limit_mins = dict.FindIntKey(kDailyLimitInt);
if ((restriction == AppRestriction::kTimeLimit && !daily_limit_mins) ||
(restriction == AppRestriction::kBlocked && daily_limit_mins)) {
DLOG(ERROR) << "Invalid restriction.";
return base::nullopt;
}
base::Optional<base::TimeDelta> daily_limit;
if (daily_limit_mins) {
daily_limit = base::TimeDelta::FromMinutes(*daily_limit_mins);
if (daily_limit && (*daily_limit < base::TimeDelta::FromHours(0) ||
*daily_limit > base::TimeDelta::FromHours(24))) {
DLOG(ERROR) << "Invalid daily limit.";
return base::nullopt;
}
}
const std::string* last_updated_string =
dict.FindStringKey(kLastUpdatedString);
int64_t last_updated_millis;
if (!last_updated_string || last_updated_string->empty() ||
!base::StringToInt64(*last_updated_string, &last_updated_millis)) {
DLOG(ERROR) << "Invalid last updated time.";
return base::nullopt;
}
const base::Time last_updated =
base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(last_updated_millis);
return AppLimit(restriction, daily_limit, last_updated);
}
base::Value AppLimitToDict(const AppLimit& limit) {
base::Value value(base::Value::Type::DICTIONARY);
value.SetKey(kRestrictionEnum,
base::Value(AppRestrictionToPolicyString(limit.restriction())));
if (limit.daily_limit())
value.SetKey(kDailyLimitInt, base::Value(limit.daily_limit()->InMinutes()));
const std::string last_updated_string = base::NumberToString(
(limit.last_updated() - base::Time::UnixEpoch()).InMilliseconds());
value.SetKey(kLastUpdatedString, base::Value(last_updated_string));
return value;
}
base::Optional<base::TimeDelta> ResetTimeFromDict(const base::Value& dict) {
if (!dict.is_dict())
return base::nullopt;
const base::Value* reset_dict = dict.FindKey(kResetAtDict);
if (!reset_dict || !reset_dict->is_dict()) {
DLOG(ERROR) << "Invalid reset time dictionary.";
return base::nullopt;
}
base::Optional<int> hour = reset_dict->FindIntKey(kHourInt);
if (!hour) {
DLOG(ERROR) << "Invalid reset hour.";
return base::nullopt;
}
base::Optional<int> minutes = reset_dict->FindIntKey(kMinInt);
if (!minutes) {
DLOG(ERROR) << "Invalid reset minutes.";
return base::nullopt;
}
const int hour_in_mins = base::TimeDelta::FromHours(1).InMinutes();
return base::TimeDelta::FromMinutes(hour.value() * hour_in_mins +
minutes.value());
}
base::Value ResetTimeToDict(int hour, int minutes) {
base::Value value(base::Value::Type::DICTIONARY);
value.SetKey(kHourInt, base::Value(hour));
value.SetKey(kMinInt, base::Value(minutes));
return value;
}
std::map<AppId, AppLimit> AppLimitsFromDict(const base::Value& dict) {
std::map<AppId, AppLimit> app_limits;
const base::Value* limits_array = dict.FindListKey(kAppLimitsArray);
if (!limits_array) {
DLOG(ERROR) << "Invalid app limits list.";
return app_limits;
}
base::Value::ConstListView list_view = limits_array->GetList();
for (const base::Value& dict : list_view) {
if (!dict.is_dict()) {
DLOG(ERROR) << "Invalid app limits entry. ";
continue;
}
base::Optional<AppId> app_id = AppIdFromDict(dict);
if (!app_id) {
DLOG(ERROR) << "Invalid app id.";
continue;
}
base::Optional<AppLimit> app_limit = AppLimitFromDict(dict);
if (!app_limit) {
DLOG(ERROR) << "Invalid app limit.";
continue;
}
app_limits.emplace(*app_id, *app_limit);
}
return app_limits;
}
} // namespace policy
} // namespace app_time
} // namespace chromeos
// 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.
#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_
#include <map>
#include <string>
#include "base/optional.h"
#include "chrome/services/app_service/public/mojom/types.mojom.h"
namespace base {
class TimeDelta;
class Value;
} // namespace base
namespace chromeos {
namespace app_time {
class AppId;
class AppLimit;
enum class AppRestriction;
namespace policy {
// Dictionary keys for app time limits related policies.
extern const char kUrlList[];
extern const char kAppList[];
extern const char kAppId[];
extern const char kAppType[];
extern const char kAppLimitsArray[];
extern const char kAppInfoDict[];
extern const char kRestrictionEnum[];
extern const char kDailyLimitInt[];
extern const char kLastUpdatedString[];
extern const char kResetAtDict[];
extern const char kHourInt[];
extern const char kMinInt[];
// Converts between apps::mojom::AppType and string used by app time limits
// policies.
apps::mojom::AppType PolicyStringToAppType(const std::string& app_type);
std::string AppTypeToPolicyString(apps::mojom::AppType app_type);
// Converts between AppRestriction and string used by app time limits policies.
AppRestriction PolicyStringToAppRestriction(const std::string& restriction);
std::string AppRestrictionToPolicyString(const AppRestriction& restriction);
// Deserializes AppId from |dict|.
// Returns value if |dict| contains valid app information.
base::Optional<AppId> AppIdFromDict(const base::Value& dict);
// Serializes AppId to the dictionary.
base::Value AppIdToDict(const AppId& app_id);
// Deserializes AppLimit from |dict|.
// Returns value if |dict| contains valid app limit information.
base::Optional<AppLimit> AppLimitFromDict(const base::Value& dict);
// Serializes AppLimit to the dictionary.
base::Value AppLimitToDict(const AppLimit& limit);
// Deserializes daily limits reset time from |dict|.
// Returns value if |dict| contains valid reset time information.
base::Optional<base::TimeDelta> ResetTimeFromDict(const base::Value& dict);
// Serializes daily limits reset to the dictionary.
base::Value ResetTimeToDict(int hour, int minutes);
// Deserializes app limits data from the |dict|.
// Will return empty map if |dict| is invalid.
std::map<AppId, AppLimit> AppLimitsFromDict(const base::Value& dict);
} // namespace policy
} // namespace app_time
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_
......@@ -85,6 +85,7 @@ class AppLimit {
~AppLimit();
AppRestriction restriction() const { return restriction_; }
base::Time last_updated() const { return last_updated_; }
const base::Optional<base::TimeDelta>& daily_limit() const {
return daily_limit_;
}
......
......@@ -2108,6 +2108,9 @@ if (!is_android) {
"../browser/chromeos/child_accounts/parent_access_code/parent_access_test_utils.h",
"../browser/chromeos/child_accounts/screen_time_controller_browsertest.cc",
"../browser/chromeos/child_accounts/time_limit_test_utils.cc",
"../browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc",
"../browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.cc",
"../browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h",
"../browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc",
"../browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h",
"../browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment