Commit d7a5991c authored by yilkal's avatar yilkal Committed by Commit Bot

arc: Restrict child user from switching accounts in Play Store.

This cl sets "playStoreMode" policy to restrict
child user from toggling Play Store account.

This cl updates "applications" policy's value for
playStore to also restrict the child user from
toggling Play Store account.

Both values have to be set because there is a race
condition that exists between the two policies.

The policies are updated from the client side and not
from the server side because the client has enough information
to set the values. In addition, sending the additional policy
values from the server will unnecessarily incur bandwidth costs
overtime (few bytes sent per policy update per child adds
up overtime).

Test: The CL has Unit tests to cover the changes. It has also been
manually tested on device.

Bug: 1106901
Change-Id: I56d95d955c8fe54b84ea7c94cabea302d7d8378f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2304996Reviewed-by: default avatarPolina Bondarenko <pbond@chromium.org>
Reviewed-by: default avatarAga Wronska <agawronska@chromium.org>
Commit-Queue: Yilkal Abe <yilkal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792727}
parent ded4b90b
......@@ -18,6 +18,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
......@@ -45,6 +46,7 @@ namespace {
constexpr char kArcCaCerts[] = "caCerts";
constexpr char kPolicyCompliantJson[] = "{ \"policyCompliant\": true }";
constexpr char kArcRequiredKeyPairs[] = "requiredKeyPairs";
constexpr char kPlayStorePackageName[] = "com.android.vending";
// invert_bool_value: If the Chrome policy and the ARC policy with boolean value
// have opposite semantics, set this to true so the bool is inverted before
......@@ -218,10 +220,10 @@ void AddRequiredKeyPairs(const ArcSmartCardManagerBridge* smart_card_manager,
std::string GetFilteredJSONPolicies(
const policy::PolicyMap& policy_map,
const PrefService* profile_prefs,
const std::string& guid,
bool is_affiliated,
const ArcSmartCardManagerBridge* smart_card_manager) {
const ArcSmartCardManagerBridge* smart_card_manager,
const Profile* profile) {
base::Value filtered_policies(base::Value::Type::DICTIONARY);
// Parse ArcPolicy as JSON string before adding other policies to the
// dictionary.
......@@ -247,6 +249,33 @@ std::string GetFilteredJSONPolicies(
}
}
if (profile->IsSupervised() &&
chromeos::ProfileHelper::Get()->IsPrimaryProfile(profile) &&
arc::IsSecondaryAccountForChildEnabled()) {
// Adds "playStoreMode" policy. The policy value is used to restrict the
// user from being able to toggle between different accounts in ARC++.
filtered_policies.SetStringKey("playStoreMode", "SUPERVISED");
// Updates "applications" policy value for PlayStore to include the child's
// primary email account.
base::Value* applications_value =
filtered_policies.FindListKey("applications");
if (applications_value) {
base::Value::ListView list_view = applications_value->GetList();
for (base::Value& entry : list_view) {
const std::string* packageName = entry.FindStringKey("packageName");
if (packageName && *packageName != kPlayStorePackageName)
continue;
base::Value management_entry(base::Value::Type::DICTIONARY);
management_entry.SetStringKey("allowed_accounts",
profile->GetProfileUserName());
entry.SetKey("managedConfiguration", std::move(management_entry));
}
}
}
const PrefService* profile_prefs = profile->GetPrefs();
// Keep them sorted by the ARC policy names.
MapBoolToBool("cameraDisabled", policy::key::kVideoCaptureAllowed, policy_map,
/* invert_bool_value */ true, &filtered_policies);
......@@ -550,9 +579,9 @@ std::string ArcPolicyBridge::GetCurrentJSONPolicies() const {
const ArcSmartCardManagerBridge* smart_card_manager =
ArcSmartCardManagerBridge::GetForBrowserContext(context_);
return GetFilteredJSONPolicies(policy_map, profile->GetPrefs(),
instance_guid_, user->IsAffiliated(),
smart_card_manager);
return GetFilteredJSONPolicies(policy_map, instance_guid_,
user->IsAffiliated(), smart_card_manager,
profile);
}
void ArcPolicyBridge::OnReportComplianceParse(
......
......@@ -11,14 +11,18 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.h"
#include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/supervised_user/supervised_user_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/arc/arc_features.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/test/connection_holder_util.h"
......@@ -79,6 +83,39 @@ constexpr char kPolicyCompliantResponse[] = "{ \"policyCompliant\": true }";
constexpr char kFakeCertName[] = "cert_name";
constexpr char kRequiredKeyPairFormat[] = "\"requiredKeyPairs\":[%s%s%s]";
constexpr char kSupervisedUserPlayStoreModePolicySetting[] =
"\"playStoreMode\":\"SUPERVISED\"";
constexpr char kPlayStoreManagedRestriction[] =
"\"managedConfiguration\":{"
"\"allowed_accounts\":\"%s\"},";
constexpr char kApplicationsPolicy[] =
"\"applications\":["
"{"
"\"disabled\":false,"
"\"installType\":\"OPTIONAL\","
"%s"
"\"packageName\":\"com.android.vending\""
"},"
"{"
"\"disabled\":false,"
"\"installType\":\"OPTIONAL\","
"\"packageName\":\"com.a.b\""
"}]";
constexpr char kTestUserEmail[] = "user@gmail.com";
std::string GetSupervisedUserPlayStoreApplicationPolicy(
bool include_playstore_restriction,
const std::string& user_email) {
std::string restriction_used =
include_playstore_restriction
? base::StringPrintf(kPlayStoreManagedRestriction, user_email.c_str())
: "";
return base::StringPrintf(kApplicationsPolicy, restriction_used.c_str());
}
MATCHER_P(ValueEquals, expected, "value matches") {
return *expected == *arg;
}
......@@ -165,13 +202,13 @@ class ArcPolicyBridgeTestBase {
user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
base::WrapUnique(fake_user_manager));
const AccountId account_id(
AccountId::FromUserEmailGaiaId("user@gmail.com", "1111111111"));
AccountId::FromUserEmailGaiaId(kTestUserEmail, "1111111111"));
fake_user_manager->AddUserWithAffiliation(account_id, is_affiliated);
fake_user_manager->LoginUser(account_id);
testing_profile_manager_ = std::make_unique<TestingProfileManager>(
TestingBrowserProcess::GetGlobal());
ASSERT_TRUE(testing_profile_manager_->SetUp());
profile_ = testing_profile_manager_->CreateTestingProfile("user@gmail.com");
profile_ = testing_profile_manager_->CreateTestingProfile(kTestUserEmail);
ASSERT_TRUE(profile_);
smart_card_manager_ = GetArcSmartCardManager();
......@@ -591,6 +628,46 @@ TEST_F(ArcPolicyBridgeTest, VpnConfigAllowedTest) {
"\",\"vpnConfigDisabled\":true}");
}
TEST_F(ArcPolicyBridgeTest, ManualChildUserPoliciesSet) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures(
/* enabled_features */ {{arc::kEnableSecondaryAccountsForChild}},
/* disabled_features */ {{}});
// Mark profile as supervised user.
profile()->SetSupervisedUserId(::supervised_users::kChildAccountSUID);
EXPECT_TRUE(profile()->IsChild());
policy_map().Set(policy::key::kArcPolicy, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value("{}"), /* external_data_fetcher */ nullptr);
// Applications policy is not present so only playStoreMode policy is set.
GetPoliciesAndVerifyResult(
base::StrCat({"{\"guid\":\"", instance_guid(), "\",",
kSupervisedUserPlayStoreModePolicySetting, "}"}));
// ARC policy with applications policy:
// The managedConfiguration for Play Store should be set in this case.
// PlayStoreMode policy should also be set in this case.
const std::string arc_policy =
base::StrCat({"{",
GetSupervisedUserPlayStoreApplicationPolicy(
/* include_playstore_restriction */ false, ""),
"}"});
policy_map().Set(policy::key::kArcPolicy, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(arc_policy),
/* external_data_fetcher */ nullptr);
const std::string expected_policy_result = base::StrCat(
{"{",
GetSupervisedUserPlayStoreApplicationPolicy(
/* include_playstore_restriction */ true, kTestUserEmail),
",\"guid\":\"", instance_guid(), "\",",
kSupervisedUserPlayStoreModePolicySetting, "}"});
GetPoliciesAndVerifyResult(expected_policy_result);
}
TEST_P(ArcPolicyBridgeAffiliatedTest, DISABLED_ApkCacheEnabledTest) {
const std::string apk_cache_enabled_policy(
"{\"apkCacheEnabled\":true,\"guid\":\"" + instance_guid() + "\"}");
......
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