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

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/+/2001411Reviewed-by: default avatarYilkal Abe <yilkal@chromium.org>
Commit-Queue: Aga Wronska <agawronska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734123}
parent 32f7d24a
...@@ -819,6 +819,8 @@ source_set("chromeos") { ...@@ -819,6 +819,8 @@ source_set("chromeos") {
"child_accounts/time_limits/app_time_controller.h", "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.cc",
"child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h", "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.cc",
"child_accounts/time_limits/app_types.h", "child_accounts/time_limits/app_types.h",
"child_accounts/time_limits/web_time_limit_enforcer.cc", "child_accounts/time_limits/web_time_limit_enforcer.cc",
......
...@@ -49,6 +49,17 @@ enterprise_management::AppActivity::AppState AppStateForReporting( ...@@ -49,6 +49,17 @@ enterprise_management::AppActivity::AppState AppStateForReporting(
} // namespace } // 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() = default;
AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity) AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity)
...@@ -76,6 +87,8 @@ void AppActivityRegistry::OnAppInstalled(const AppId& app_id) { ...@@ -76,6 +87,8 @@ void AppActivityRegistry::OnAppInstalled(const AppId& app_id) {
// sessions and app service does not. Make sure not to override cached state. // sessions and app service does not. Make sure not to override cached state.
if (!base::Contains(activity_registry_, app_id)) if (!base::Contains(activity_registry_, app_id))
Add(app_id); Add(app_id);
// TODO(agawronska): Update the limit from policy when new app is installed.
} }
void AppActivityRegistry::OnAppUninstalled(const AppId& app_id) { void AppActivityRegistry::OnAppUninstalled(const AppId& app_id) {
...@@ -229,6 +242,21 @@ void AppActivityRegistry::CleanRegistry(base::Time timestamp) { ...@@ -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) { void AppActivityRegistry::Add(const AppId& app_id) {
auto result = activity_registry_.emplace( auto result = activity_registry_.emplace(
app_id, AppDetails(AppActivity(AppState::kAvailable))); app_id, AppDetails(AppActivity(AppState::kAvailable)));
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include "base/optional.h"
#include "base/time/time.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_activity_report_interface.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h"
...@@ -30,6 +31,18 @@ namespace app_time { ...@@ -30,6 +31,18 @@ namespace app_time {
// 30 days if upload did not happen. // 30 days if upload did not happen.
class AppActivityRegistry : public AppServiceWrapper::EventListener { class AppActivityRegistry : public AppServiceWrapper::EventListener {
public: 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); explicit AppActivityRegistry(AppServiceWrapper* app_service_wrapper);
AppActivityRegistry(const AppActivityRegistry&) = delete; AppActivityRegistry(const AppActivityRegistry&) = delete;
AppActivityRegistry& operator=(const AppActivityRegistry&) = delete; AppActivityRegistry& operator=(const AppActivityRegistry&) = delete;
...@@ -67,6 +80,9 @@ class AppActivityRegistry : public AppServiceWrapper::EventListener { ...@@ -67,6 +80,9 @@ class AppActivityRegistry : public AppServiceWrapper::EventListener {
// data left. // data left.
void CleanRegistry(base::Time timestamp); void CleanRegistry(base::Time timestamp);
// Updates time limits for the installed apps.
void UpdateAppLimits(const std::map<AppId, AppLimit>& app_limits);
private: private:
// Bundles detailed data stored for a specific app. // Bundles detailed data stored for a specific app.
struct AppDetails { struct AppDetails {
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/optional.h"
#include "base/values.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_activity_registry.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.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_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/chromeos/child_accounts/time_limits/web_time_limit_enforcer.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
...@@ -22,6 +24,15 @@ ...@@ -22,6 +24,15 @@
namespace chromeos { namespace chromeos {
namespace app_time { 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 // static
bool AppTimeController::ArePerAppTimeLimitsEnabled() { bool AppTimeController::ArePerAppTimeLimitsEnabled() {
return base::FeatureList::IsEnabled(features::kPerAppTimeLimits); return base::FeatureList::IsEnabled(features::kPerAppTimeLimits);
...@@ -77,7 +88,21 @@ void AppTimeController::RegisterProfilePrefObservers( ...@@ -77,7 +88,21 @@ void AppTimeController::RegisterProfilePrefObservers(
} }
void AppTimeController::TimeLimitsPolicyUpdated(const std::string& pref_name) { 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( void AppTimeController::TimeLimitsWhitelistPolicyUpdated(
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <memory> #include <memory>
#include "base/time/time.h"
class Profile; class Profile;
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefChangeRegistrar; class PrefChangeRegistrar;
...@@ -23,6 +25,18 @@ class WebTimeLimitEnforcer; ...@@ -23,6 +25,18 @@ class WebTimeLimitEnforcer;
// Coordinates per-app time limit for child user. // Coordinates per-app time limit for child user.
class AppTimeController { class AppTimeController {
public: 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 ArePerAppTimeLimitsEnabled();
static bool IsAppActivityReportingEnabled(); static bool IsAppActivityReportingEnabled();
...@@ -53,6 +67,10 @@ class AppTimeController { ...@@ -53,6 +67,10 @@ class AppTimeController {
void TimeLimitsPolicyUpdated(const std::string& pref_name); void TimeLimitsPolicyUpdated(const std::string& pref_name);
void TimeLimitsWhitelistPolicyUpdated(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<AppServiceWrapper> app_service_wrapper_;
std::unique_ptr<AppActivityRegistry> app_registry_; std::unique_ptr<AppActivityRegistry> app_registry_;
std::unique_ptr<WebTimeLimitEnforcer> web_time_enforcer_; 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 @@ ...@@ -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_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_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 chromeos {
namespace app_time { namespace app_time {
...@@ -16,8 +18,8 @@ AppTimeLimitsWhitelistPolicyBuilder::~AppTimeLimitsWhitelistPolicyBuilder() = ...@@ -16,8 +18,8 @@ AppTimeLimitsWhitelistPolicyBuilder::~AppTimeLimitsWhitelistPolicyBuilder() =
void AppTimeLimitsWhitelistPolicyBuilder::SetUp() { void AppTimeLimitsWhitelistPolicyBuilder::SetUp() {
value_ = base::Value(base::Value::Type::DICTIONARY); value_ = base::Value(base::Value::Type::DICTIONARY);
value_.SetKey(kUrlList, base::Value(base::Value::Type::LIST)); value_.SetKey(policy::kUrlList, base::Value(base::Value::Type::LIST));
value_.SetKey(kAppList, base::Value(base::Value::Type::LIST)); value_.SetKey(policy::kAppList, base::Value(base::Value::Type::LIST));
} }
void AppTimeLimitsWhitelistPolicyBuilder::Clear() { void AppTimeLimitsWhitelistPolicyBuilder::Clear() {
...@@ -28,16 +30,17 @@ void AppTimeLimitsWhitelistPolicyBuilder::Clear() { ...@@ -28,16 +30,17 @@ void AppTimeLimitsWhitelistPolicyBuilder::Clear() {
void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistUrlList( void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistUrlList(
const std::string& scheme) { const std::string& scheme) {
AppendToList(kUrlList, base::Value(scheme)); AppendToList(policy::kUrlList, base::Value(scheme));
} }
void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistAppList( void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistAppList(
const AppId& app_id) { const AppId& app_id) {
base::Value value_to_append(base::Value::Type::DICTIONARY); base::Value value_to_append(base::Value::Type::DICTIONARY);
value_to_append.SetKey(kAppId, base::Value(app_id.app_id())); value_to_append.SetKey(policy::kAppId, base::Value(app_id.app_id()));
value_to_append.SetKey(kAppType, value_to_append.SetKey(
base::Value(AppTypeToString(app_id.app_type()))); policy::kAppType,
AppendToList(kAppList, std::move(value_to_append)); base::Value(policy::AppTypeToPolicyString(app_id.app_type())));
AppendToList(policy::kAppList, std::move(value_to_append));
} }
void AppTimeLimitsWhitelistPolicyBuilder::AppendToList(const std::string& key, void AppTimeLimitsWhitelistPolicyBuilder::AppendToList(const std::string& key,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_WHITELIST_POLICY_TEST_UTILS_H_ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_WHITELIST_POLICY_TEST_UTILS_H_
#include <string> #include <string>
#include "base/values.h" #include "base/values.h"
namespace chromeos { namespace chromeos {
......
...@@ -4,48 +4,13 @@ ...@@ -4,48 +4,13 @@
#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_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 chromeos {
namespace app_time { 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( AppTimeLimitsWhitelistPolicyWrapper::AppTimeLimitsWhitelistPolicyWrapper(
const base::Value* value) const base::Value* value)
: value_(value) {} : value_(value) {}
...@@ -55,7 +20,7 @@ AppTimeLimitsWhitelistPolicyWrapper::~AppTimeLimitsWhitelistPolicyWrapper() = ...@@ -55,7 +20,7 @@ AppTimeLimitsWhitelistPolicyWrapper::~AppTimeLimitsWhitelistPolicyWrapper() =
std::vector<std::string> std::vector<std::string>
AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const { AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const {
const base::Value* list = value_->FindListKey(kUrlList); const base::Value* list = value_->FindListKey(policy::kUrlList);
DCHECK(list); DCHECK(list);
base::Value::ConstListView list_view = list->GetList(); base::Value::ConstListView list_view = list->GetList();
...@@ -68,19 +33,15 @@ AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const { ...@@ -68,19 +33,15 @@ AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const {
std::vector<AppId> AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistAppList() std::vector<AppId> AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistAppList()
const { const {
const base::Value* app_list = value_->FindListKey(kAppList); const base::Value* app_list = value_->FindListKey(policy::kAppList);
DCHECK(app_list); DCHECK(app_list);
base::Value::ConstListView list_view = app_list->GetList(); base::Value::ConstListView list_view = app_list->GetList();
std::vector<AppId> return_value; std::vector<AppId> return_value;
for (const base::Value& value : list_view) { for (const base::Value& value : list_view) {
const std::string* app_id = value.FindStringKey(kAppId); base::Optional<AppId> app_id = policy::AppIdFromDict(value);
DCHECK(app_id); if (app_id)
return_value.push_back(*app_id);
const std::string* app_type = value.FindStringKey(kAppType);
DCHECK(app_type);
return_value.push_back(AppId(StringToAppType(*app_type), *app_id));
} }
return return_value; return return_value;
......
...@@ -7,23 +7,14 @@ ...@@ -7,23 +7,14 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/values.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" #include "base/values.h"
namespace chromeos { namespace chromeos {
namespace app_time { namespace app_time {
class AppId; 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 { class AppTimeLimitsWhitelistPolicyWrapper {
public: public:
explicit AppTimeLimitsWhitelistPolicyWrapper(const base::Value* value); 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 { ...@@ -85,6 +85,7 @@ class AppLimit {
~AppLimit(); ~AppLimit();
AppRestriction restriction() const { return restriction_; } AppRestriction restriction() const { return restriction_; }
base::Time last_updated() const { return last_updated_; }
const base::Optional<base::TimeDelta>& daily_limit() const { const base::Optional<base::TimeDelta>& daily_limit() const {
return daily_limit_; return daily_limit_;
} }
......
...@@ -2107,6 +2107,9 @@ if (!is_android) { ...@@ -2107,6 +2107,9 @@ if (!is_android) {
"../browser/chromeos/child_accounts/parent_access_code/parent_access_test_utils.h", "../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/screen_time_controller_browsertest.cc",
"../browser/chromeos/child_accounts/time_limit_test_utils.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.cc",
"../browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h", "../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", "../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