blob: f65320470720b37cfbb3486832a8be810aeec027 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/policy/core/common/policy_map.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/policy/core/common/external_data_manager.h"
#include "components/policy/core/common/features.h"
#include "components/policy/core/common/policy_details.h"
#include "components/policy/core/common/policy_merger.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace policy {
namespace {
// Dummy policy names.
const char kTestPolicyName1[] = "policy.test.1";
const char kTestPolicyName2[] = "policy.test.2";
const char kTestPolicyName3[] = "policy.test.3";
const char kTestPolicyName4[] = "policy.test.4";
const char kTestPolicyName5[] = "policy.test.5";
const char kTestPolicyName6[] = "policy.test.6";
const char kTestPolicyName7[] = "policy.test.7";
const char kTestPolicyName8[] = "policy.test.8";
// Dummy error message.
const char16_t kTestError[] = u"Test error message";
// Utility functions for the tests.
void SetPolicy(PolicyMap* map, const char* name, base::Value value) {
map->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
std::move(value), nullptr);
}
void SetPolicy(PolicyMap* map,
const char* name,
std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
map->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
absl::nullopt, std::move(external_data_fetcher));
}
template <class T>
base::Value::List GetList(const std::vector<T>& entry) {
base::Value::List result;
for (const auto& it : entry)
result.Append(it);
return result;
}
} // namespace
class PolicyMapTestBase {
protected:
std::unique_ptr<ExternalDataFetcher> CreateExternalDataFetcher(
const std::string& policy) const;
};
std::unique_ptr<ExternalDataFetcher>
PolicyMapTestBase::CreateExternalDataFetcher(const std::string& policy) const {
return std::make_unique<ExternalDataFetcher>(
base::WeakPtr<ExternalDataManager>(), policy);
}
class PolicyMapTest : public PolicyMapTestBase, public testing::Test {
public:
const PolicyDetails* GetPolicyDetailsExternalCallback(
const std::string& policy_name) {
return &externalDetails_;
}
const PolicyDetails* GetPolicyDetailsNonExternalCallback(
const std::string& policy_name) {
return &nonExternalDetails_;
}
PolicyDetails externalDetails_ = {false, false, false, 0, 10, {}};
PolicyDetails nonExternalDetails_ = {false, false, false, 0, 0, {}};
};
TEST_F(PolicyMapTest, SetAndGet) {
PolicyMap map;
EXPECT_FALSE(map.IsPolicySet(kTestPolicyName1));
SetPolicy(&map, kTestPolicyName1, base::Value("aaa"));
EXPECT_TRUE(map.IsPolicySet(kTestPolicyName1));
const base::Value kExpectedStringA("aaa");
EXPECT_EQ(kExpectedStringA, *map.GetValueUnsafe(kTestPolicyName1));
EXPECT_EQ(kExpectedStringA,
*map.GetValue(kTestPolicyName1, base::Value::Type::STRING));
EXPECT_EQ(nullptr,
map.GetValue(kTestPolicyName1, base::Value::Type::BOOLEAN));
SetPolicy(&map, kTestPolicyName1, base::Value("bbb"));
EXPECT_TRUE(map.IsPolicySet(kTestPolicyName1));
const base::Value kExpectedStringB("bbb");
EXPECT_EQ(kExpectedStringB, *map.GetValueUnsafe(kTestPolicyName1));
EXPECT_EQ(kExpectedStringB,
*map.GetValue(kTestPolicyName1, base::Value::Type::STRING));
EXPECT_EQ(nullptr,
map.GetValue(kTestPolicyName1, base::Value::Type::BOOLEAN));
SetPolicy(&map, kTestPolicyName1, base::Value(true));
EXPECT_TRUE(map.IsPolicySet(kTestPolicyName1));
const base::Value kExpectedBool(true);
EXPECT_EQ(kExpectedBool, *map.GetValueUnsafe(kTestPolicyName1));
EXPECT_EQ(nullptr, map.GetValue(kTestPolicyName1, base::Value::Type::STRING));
EXPECT_EQ(kExpectedBool,
*map.GetValue(kTestPolicyName1, base::Value::Type::BOOLEAN));
SetPolicy(&map, kTestPolicyName1, CreateExternalDataFetcher("dummy"));
EXPECT_FALSE(map.IsPolicySet(kTestPolicyName1));
map.AddMessage(kTestPolicyName1, PolicyMap::MessageType::kError,
IDS_POLICY_STORE_STATUS_VALIDATION_ERROR, {kTestError});
EXPECT_EQ(nullptr, map.GetValueUnsafe(kTestPolicyName1));
const PolicyMap::Entry* entry = map.Get(kTestPolicyName1);
ASSERT_NE(nullptr, entry);
EXPECT_EQ(POLICY_LEVEL_MANDATORY, entry->level);
EXPECT_EQ(POLICY_SCOPE_USER, entry->scope);
EXPECT_EQ(POLICY_SOURCE_CLOUD, entry->source);
std::u16string error_string =
base::StrCat({u"Validation error: ", kTestError});
PolicyMap::Entry::L10nLookupFunction lookup = base::BindRepeating(
static_cast<std::u16string (*)(int)>(&base::NumberToString16));
EXPECT_EQ(error_string, entry->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_TRUE(
ExternalDataFetcher::Equals(entry->external_data_fetcher.get(),
CreateExternalDataFetcher("dummy").get()));
map.Set(kTestPolicyName1, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, absl::nullopt, nullptr);
EXPECT_FALSE(map.IsPolicySet(kTestPolicyName1));
EXPECT_EQ(nullptr, map.GetValueUnsafe(kTestPolicyName1));
entry = map.Get(kTestPolicyName1);
ASSERT_NE(nullptr, entry);
EXPECT_EQ(POLICY_LEVEL_RECOMMENDED, entry->level);
EXPECT_EQ(POLICY_SCOPE_MACHINE, entry->scope);
EXPECT_EQ(POLICY_SOURCE_ENTERPRISE_DEFAULT, entry->source);
EXPECT_EQ(std::u16string(), entry->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_FALSE(entry->external_data_fetcher);
}
TEST_F(PolicyMapTest, AddMessage_Error) {
PolicyMap map;
SetPolicy(&map, kTestPolicyName1, base::Value(0));
PolicyMap::Entry* entry1 = map.GetMutable(kTestPolicyName1);
PolicyMap::Entry::L10nLookupFunction lookup = base::BindRepeating(
static_cast<std::u16string (*)(int)>(&base::NumberToString16));
EXPECT_EQ(std::u16string(), entry1->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
map.AddMessage(kTestPolicyName1, PolicyMap::MessageType::kError, 1234);
EXPECT_EQ(u"1234", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
map.AddMessage(kTestPolicyName1, PolicyMap::MessageType::kError, 5678);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
// Add second entry to make sure errors are added individually.
SetPolicy(&map, kTestPolicyName2, base::Value(0));
PolicyMap::Entry* entry2 = map.GetMutable(kTestPolicyName2);
// Test adding Error message with placeholder replacement (one arg)
map.AddMessage(kTestPolicyName2, PolicyMap::MessageType::kError,
IDS_POLICY_MIGRATED_OLD_POLICY, {u"SomeNewPolicy"});
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_EQ(
u"This policy is deprecated. You should use the "
u"SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kError, lookup));
map.AddMessage(kTestPolicyName2, PolicyMap::MessageType::kError, 1357);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kError, lookup));
// Test adding Error message with placeholder replacement (two args)
map.AddMessage(kTestPolicyName1, PolicyMap::MessageType::kError,
IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM,
{u"SomeSource", u"SomeDestination"});
EXPECT_EQ(
u"1234\n5678\nSharing from SomeSource to SomeDestination has "
u"been blocked by administrator policy",
entry1->GetLocalizedMessages(PolicyMap::MessageType::kError, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kError, lookup));
// Ensure other message types are empty
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
}
TEST_F(PolicyMapTest, AddMessage_Warning) {
PolicyMap map;
SetPolicy(&map, kTestPolicyName1, base::Value(0));
PolicyMap::Entry* entry1 = map.GetMutable(kTestPolicyName1);
PolicyMap::Entry::L10nLookupFunction lookup = base::BindRepeating(
static_cast<std::u16string (*)(int)>(&base::NumberToString16));
EXPECT_EQ(std::u16string(), entry1->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
entry1->AddMessage(PolicyMap::MessageType::kWarning, 1234);
EXPECT_EQ(u"1234", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
entry1->AddMessage(PolicyMap::MessageType::kWarning, 5678);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
// Add second entry to make sure warnings are added individually.
SetPolicy(&map, kTestPolicyName2, base::Value(0));
PolicyMap::Entry* entry2 = map.GetMutable(kTestPolicyName2);
// Test adding Warning message with placeholder replacement (one arg)
entry2->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_MIGRATED_OLD_POLICY, {u"SomeNewPolicy"});
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
EXPECT_EQ(
u"This policy is deprecated. You should use the "
u"SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kWarning, lookup));
entry2->AddMessage(PolicyMap::MessageType::kWarning, 1357);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kWarning, lookup));
// Test adding Warning message with placeholder replacement (two args)
entry1->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM,
{u"SomeSource", u"SomeDestination"});
EXPECT_EQ(
u"1234\n5678\nSharing from SomeSource to SomeDestination has "
u"been blocked by administrator policy",
entry1->GetLocalizedMessages(PolicyMap::MessageType::kWarning, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kWarning, lookup));
// Ensure other message types are empty
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
}
TEST_F(PolicyMapTest, AddMessage_Info) {
PolicyMap map;
SetPolicy(&map, kTestPolicyName1, base::Value(0));
PolicyMap::Entry* entry1 = map.GetMutable(kTestPolicyName1);
PolicyMap::Entry::L10nLookupFunction lookup = base::BindRepeating(
static_cast<std::u16string (*)(int)>(&base::NumberToString16));
EXPECT_EQ(std::u16string(), entry1->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
entry1->AddMessage(PolicyMap::MessageType::kInfo, 1234);
EXPECT_EQ(u"1234", entry1->GetLocalizedMessages(PolicyMap::MessageType::kInfo,
lookup));
entry1->AddMessage(PolicyMap::MessageType::kInfo, 5678);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
// Add second entry to make sure messages are added individually.
SetPolicy(&map, kTestPolicyName2, base::Value(0));
PolicyMap::Entry* entry2 = map.GetMutable(kTestPolicyName2);
// Test adding Info message with placeholder replacement (one arg)
entry2->AddMessage(PolicyMap::MessageType::kInfo,
IDS_POLICY_MIGRATED_OLD_POLICY, {u"SomeNewPolicy"});
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
EXPECT_EQ(
u"This policy is deprecated. You should use the "
u"SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kInfo, lookup));
entry2->AddMessage(PolicyMap::MessageType::kInfo, 1357);
EXPECT_EQ(u"1234\n5678", entry1->GetLocalizedMessages(
PolicyMap::MessageType::kInfo, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kInfo, lookup));
// Test adding Info message with placeholder replacement (two args)
entry1->AddMessage(PolicyMap::MessageType::kInfo,
IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM,
{u"SomeSource", u"SomeDestination"});
EXPECT_EQ(
u"1234\n5678\nSharing from SomeSource to SomeDestination has "
u"been blocked by administrator policy",
entry1->GetLocalizedMessages(PolicyMap::MessageType::kInfo, lookup));
EXPECT_EQ(
u"1357\nThis policy is deprecated. You should use "
u"the SomeNewPolicy policy instead.",
entry2->GetLocalizedMessages(PolicyMap::MessageType::kInfo, lookup));
// Ensure other message types are empty
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kError, lookup));
EXPECT_EQ(std::u16string(), entry2->GetLocalizedMessages(
PolicyMap::MessageType::kWarning, lookup));
}
TEST_F(PolicyMapTest, Equals) {
PolicyMap a;
SetPolicy(&a, kTestPolicyName1, base::Value("aaa"));
PolicyMap a2;
SetPolicy(&a2, kTestPolicyName1, base::Value("aaa"));
PolicyMap b;
SetPolicy(&b, kTestPolicyName1, base::Value("bbb"));
PolicyMap c;
SetPolicy(&c, kTestPolicyName1, base::Value("aaa"));
SetPolicy(&c, kTestPolicyName2, base::Value(true));
PolicyMap d;
SetPolicy(&d, kTestPolicyName1, CreateExternalDataFetcher("ddd"));
PolicyMap d2;
SetPolicy(&d2, kTestPolicyName1, CreateExternalDataFetcher("ddd"));
PolicyMap e;
SetPolicy(&e, kTestPolicyName1, CreateExternalDataFetcher("eee"));
EXPECT_FALSE(a.Equals(b));
EXPECT_FALSE(a.Equals(c));
EXPECT_FALSE(a.Equals(d));
EXPECT_FALSE(a.Equals(e));
EXPECT_FALSE(b.Equals(a));
EXPECT_FALSE(b.Equals(c));
EXPECT_FALSE(b.Equals(d));
EXPECT_FALSE(b.Equals(e));
EXPECT_FALSE(c.Equals(a));
EXPECT_FALSE(c.Equals(b));
EXPECT_FALSE(c.Equals(d));
EXPECT_FALSE(c.Equals(e));
EXPECT_FALSE(d.Equals(a));
EXPECT_FALSE(d.Equals(b));
EXPECT_FALSE(d.Equals(c));
EXPECT_FALSE(d.Equals(e));
EXPECT_FALSE(e.Equals(a));
EXPECT_FALSE(e.Equals(b));
EXPECT_FALSE(e.Equals(c));
EXPECT_FALSE(e.Equals(d));
EXPECT_TRUE(a.Equals(a2));
EXPECT_TRUE(a2.Equals(a));
EXPECT_TRUE(d.Equals(d2));
EXPECT_TRUE(d2.Equals(d));
PolicyMap empty1;
PolicyMap empty2;
EXPECT_TRUE(empty1.Equals(empty2));
EXPECT_TRUE(empty2.Equals(empty1));
EXPECT_FALSE(empty1.Equals(a));
EXPECT_FALSE(a.Equals(empty1));
}
TEST_F(PolicyMapTest, Swap) {
PolicyMap a;
SetPolicy(&a, kTestPolicyName1, base::Value("aaa"));
SetPolicy(&a, kTestPolicyName2, CreateExternalDataFetcher("dummy"));
PolicyMap b;
SetPolicy(&b, kTestPolicyName1, base::Value("bbb"));
SetPolicy(&b, kTestPolicyName3, base::Value(true));
a.Swap(&b);
const base::Value kExpectedStringB("bbb");
EXPECT_EQ(kExpectedStringB,
*a.GetValue(kTestPolicyName1, base::Value::Type::STRING));
const base::Value kExpectedBool(true);
EXPECT_EQ(kExpectedBool,
*a.GetValue(kTestPolicyName3, base::Value::Type::BOOLEAN));
EXPECT_EQ(nullptr, a.GetValueUnsafe(kTestPolicyName2));
EXPECT_EQ(nullptr, a.Get(kTestPolicyName2));
const base::Value kExpectedStringA("aaa");
EXPECT_EQ(kExpectedStringA,
*b.GetValue(kTestPolicyName1, base::Value::Type::STRING));
EXPECT_EQ(nullptr, b.GetValueUnsafe(kTestPolicyName3));
EXPECT_EQ(nullptr, a.GetValueUnsafe(kTestPolicyName2));
const PolicyMap::Entry* entry = b.Get(kTestPolicyName2);
ASSERT_TRUE(entry);
EXPECT_TRUE(
ExternalDataFetcher::Equals(CreateExternalDataFetcher("dummy").get(),
entry->external_data_fetcher.get()));
b.Clear();
a.Swap(&b);
PolicyMap empty;
EXPECT_TRUE(a.Equals(empty));
EXPECT_FALSE(b.Equals(empty));
}
#if !BUILDFLAG(IS_CHROMEOS)
// Policy precedence changes are not supported on Chrome OS.
TEST_F(PolicyMapTest, MergeFrom_CloudMetapolicies) {
// The two precedence metapolicies, CloudPolicyOverridesPlatformPolicy and
// CloudUserPolicyOverridesCloudMachinePolicy, are set as cloud policies in
// the incoming |policy_map_2|.
PolicyMap policy_map_1;
policy_map_1.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value("platform_machine"), nullptr);
policy_map_1.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("cloud_user"), nullptr);
policy_map_1.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("cloud_user"), nullptr);
policy_map_1.Set(kTestPolicyName4, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("cloud_machine"), nullptr);
PolicyMap policy_map_2;
// Set matching user and device affiliation IDs to allow cloud user policies
// to take precedence over cloud machine policies.
base::flat_set<std::string> affiliation_ids;
affiliation_ids.insert("a");
policy_map_2.SetUserAffiliationIds(affiliation_ids);
policy_map_2.SetDeviceAffiliationIds(affiliation_ids);
policy_map_2.Set(key::kCloudPolicyOverridesPlatformPolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
policy_map_2.Set(key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
policy_map_2.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("cloud_machine"), nullptr);
policy_map_2.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value("platform_user"),
nullptr);
policy_map_2.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value("platform_machine"), nullptr);
policy_map_2.Set(kTestPolicyName4, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("cloud_user"), nullptr);
auto conflicting_policy_1 = policy_map_1.Get(kTestPolicyName1)->DeepCopy();
auto conflicting_policy_2 = policy_map_2.Get(kTestPolicyName2)->DeepCopy();
auto conflicting_policy_3 = policy_map_2.Get(kTestPolicyName3)->DeepCopy();
auto conflicting_policy_4 = policy_map_1.Get(kTestPolicyName4)->DeepCopy();
policy_map_1.MergeFrom(policy_map_2, /*merge_precedence_metapolicies=*/true);
policy_map_1.MergeFrom(policy_map_2);
PolicyMap policy_map_expected;
policy_map_expected.SetUserAffiliationIds(affiliation_ids);
policy_map_expected.SetDeviceAffiliationIds(affiliation_ids);
policy_map_expected.Set(key::kCloudPolicyOverridesPlatformPolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
policy_map_expected.Set(key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
// Cloud machine overrides platform machine.
policy_map_expected.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("cloud_machine"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddConflictingPolicy(std::move(conflicting_policy_1));
// Cloud user overrides platform user.
policy_map_expected.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("cloud_user"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName2)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName2)
->AddConflictingPolicy(std::move(conflicting_policy_2));
// Cloud user overrides platform machine.
policy_map_expected.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("cloud_user"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName3)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName3)
->AddConflictingPolicy(std::move(conflicting_policy_3));
// Cloud user overrides cloud machine.
policy_map_expected.Set(kTestPolicyName4, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("cloud_user"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName4)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName4)
->AddConflictingPolicy(std::move(conflicting_policy_4));
EXPECT_TRUE(policy_map_1.Equals(policy_map_expected));
}
#endif // BUILDFLAG(IS_CHROMEOS)
TEST_F(PolicyMapTest, MergeValuesList) {
base::Value::List abcd = GetList<std::string>({"a", "b", "c", "d"});
base::Value::List abc = GetList<std::string>({"a", "b", "c"});
base::Value::List ab = GetList<std::string>({"a", "b"});
base::Value::List cd = GetList<std::string>({"c", "d"});
base::Value::List ef = GetList<std::string>({"e", "f"});
base::Value::List int12 = GetList<int>({1, 2});
base::Value::List int34 = GetList<int>({3, 4});
base::Value::List int56 = GetList<int>({5, 6});
base::Value::List int1234 = GetList<int>({1, 2, 3, 4});
base::Value::Dict dict_ab;
dict_ab.Set("a", true);
dict_ab.Set("b", false);
base::Value::Dict dict_c;
dict_c.Set("c", false);
base::Value::Dict dict_d;
dict_d.Set("d", false);
base::Value::List list_dict_abd;
list_dict_abd.Append(dict_ab.Clone());
list_dict_abd.Append(dict_d.Clone());
base::Value::List list_dict_c;
list_dict_c.Append(dict_c.Clone());
base::Value::List list_dict_abcd;
list_dict_abcd.Append(dict_ab.Clone());
list_dict_abcd.Append(dict_d.Clone());
list_dict_abcd.Append(dict_c.Clone());
// Case 1 - kTestPolicyName1
// Enterprise default policies should not be merged with other sources.
PolicyMap::Entry case1(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value(abc.Clone()),
nullptr);
case1.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_COMMAND_LINE,
base::Value(cd.Clone()), nullptr));
case1.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(ef.Clone()), nullptr));
case1.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(ef.Clone()), nullptr));
PolicyMap::Entry expected_case1(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_MERGED,
base::Value(abcd.Clone()), nullptr);
expected_case1.AddConflictingPolicy(case1.DeepCopy());
// Case 2 - kTestPolicyName2
// Policies should only be merged with other policies with the same target,
// level and scope.
PolicyMap::Entry case2(POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(int12.Clone()),
nullptr);
case2.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(int34.Clone()), nullptr));
case2.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(int56.Clone()), nullptr));
PolicyMap::Entry expected_case2(POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_MERGED,
base::Value(int1234.Clone()), nullptr);
expected_case2.AddConflictingPolicy(case2.DeepCopy());
// Case 3 - kTestPolicyName3
// Trivial case with 2 sources.
PolicyMap::Entry case3(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(ab.Clone()), nullptr);
case3.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(cd.Clone()), nullptr));
PolicyMap::Entry expected_case3(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_MERGED,
base::Value(abcd.Clone()), nullptr);
auto case3_blocked_by_group = expected_case3.DeepCopy();
case3_blocked_by_group.SetIgnoredByPolicyAtomicGroup();
expected_case3.AddConflictingPolicy(case3.DeepCopy());
// Case 4 - kTestPolicyName4
// Policies with a single source should stay the same.
PolicyMap::Entry case4(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(ef.Clone()), nullptr);
PolicyMap::Entry expected_case4 = case4.DeepCopy();
// Case 5 - kTestPolicyName5
// Policies that are not lists should not be merged.
// If such a policy is explicitly in the list of policies to merge, an error
// is added to the entry and the policy stays intact.
PolicyMap::Entry case5(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value("bad stuff"),
nullptr);
PolicyMap::Entry expected_case5 = case5.DeepCopy();
expected_case5.AddMessage(
PolicyMap::MessageType::kError,
IDS_POLICY_LIST_MERGING_WRONG_POLICY_TYPE_SPECIFIED);
// Case 6 - kTestPolicyName6
// User cloud policies should not be merged with other sources.
PolicyMap::Entry case6(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ab.Clone()),
nullptr);
case6.AddConflictingPolicy(
PolicyMap::Entry(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(cd.Clone()), nullptr));
case6.AddConflictingPolicy(
PolicyMap::Entry(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(ef.Clone()), nullptr));
PolicyMap::Entry expected_case6(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_MERGED, base::Value(ab.Clone()),
nullptr);
expected_case6.AddConflictingPolicy(case6.DeepCopy());
// Case 7 - kTestPolicyName7
// User platform policies should not be merged under any circumstances.
PolicyMap::Entry case7(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ab.Clone()),
nullptr);
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(cd.Clone()), nullptr));
case7.AddConflictingPolicy(
PolicyMap::Entry(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(cd.Clone()), nullptr));
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(ef.Clone()), nullptr));
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_COMMAND_LINE,
base::Value(ef.Clone()), nullptr));
PolicyMap::Entry expected_case7(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_MERGED, base::Value(ab.Clone()),
nullptr);
expected_case7.AddConflictingPolicy(case7.DeepCopy());
// Case 8 - kTestPolicyName8
// Lists of dictionaries should not have duplicates.
PolicyMap::Entry case8(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM,
base::Value(list_dict_abd.Clone()), nullptr);
case8.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(list_dict_abd.Clone()), nullptr));
case8.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_COMMAND_LINE,
base::Value(list_dict_c.Clone()), nullptr));
PolicyMap::Entry expected_case8(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_MERGED,
base::Value(list_dict_abcd.Clone()), nullptr);
expected_case8.AddConflictingPolicy(case8.DeepCopy());
PolicyMap policy_not_merged;
policy_not_merged.Set(kTestPolicyName1, case1.DeepCopy());
policy_not_merged.Set(kTestPolicyName2, case2.DeepCopy());
policy_not_merged.Set(kTestPolicyName3, case3.DeepCopy());
policy_not_merged.Set(kTestPolicyName4, case4.DeepCopy());
policy_not_merged.Set(kTestPolicyName5, case5.DeepCopy());
policy_not_merged.Set(kTestPolicyName6, case6.DeepCopy());
policy_not_merged.Set(kTestPolicyName7, case7.DeepCopy());
policy_not_merged.Set(kTestPolicyName8, case8.DeepCopy());
PolicyMap expected_list_merged;
expected_list_merged.Set(kTestPolicyName1, expected_case1.DeepCopy());
expected_list_merged.Set(kTestPolicyName2, expected_case2.DeepCopy());
expected_list_merged.Set(kTestPolicyName3, expected_case3.DeepCopy());
expected_list_merged.Set(kTestPolicyName4, expected_case4.DeepCopy());
expected_list_merged.Set(kTestPolicyName5, expected_case5.DeepCopy());
expected_list_merged.Set(kTestPolicyName6, expected_case6.DeepCopy());
expected_list_merged.Set(kTestPolicyName7, expected_case7.DeepCopy());
expected_list_merged.Set(kTestPolicyName8, expected_case8.DeepCopy());
PolicyMap list_merged = policy_not_merged.Clone();
PolicyMap list_merged_wildcard = policy_not_merged.Clone();
// Merging with no restrictions specified
PolicyListMerger empty_policy_list({});
list_merged.MergeValues({&empty_policy_list});
EXPECT_TRUE(list_merged.Equals(policy_not_merged));
PolicyListMerger bad_policy_list({"unknown"});
// Merging with wrong restrictions specified
list_merged.MergeValues({&bad_policy_list});
EXPECT_TRUE(list_merged.Equals(policy_not_merged));
// Merging lists restrictions specified
PolicyListMerger good_policy_list(
{kTestPolicyName1, kTestPolicyName2, kTestPolicyName3, kTestPolicyName4,
kTestPolicyName5, kTestPolicyName6, kTestPolicyName7, kTestPolicyName8});
PolicyListMerger wildcard_policy_list({"*"});
list_merged.MergeValues({&good_policy_list});
EXPECT_TRUE(list_merged.Equals(expected_list_merged));
PolicyMap expected_list_merged_wildcard = expected_list_merged.Clone();
expected_list_merged_wildcard.Set(kTestPolicyName5, case5.DeepCopy());
list_merged_wildcard.MergeValues({&wildcard_policy_list});
EXPECT_TRUE(list_merged_wildcard.Equals(expected_list_merged_wildcard));
}
TEST_F(PolicyMapTest, MergeValuesDictionary) {
base::Value::Dict dict_a;
dict_a.Set("keyA", true);
base::Value::Dict dict_b;
dict_b.Set("keyB", "ValueB2");
dict_b.Set("keyC", "ValueC2");
dict_b.Set("keyD", "ValueD2");
base::Value::Dict dict_c;
dict_c.Set("keyA", "ValueA");
dict_c.Set("keyB", "ValueB");
dict_c.Set("keyC", "ValueC");
dict_c.Set("keyD", "ValueD");
dict_c.Set("keyZ", "ValueZ");
base::Value::Dict dict_d;
dict_d.Set("keyC", "ValueC3");
base::Value::Dict dict_e;
dict_e.Set("keyD", "ValueD4");
dict_e.Set("keyE", 123);
base::Value::Dict dict_f;
dict_f.Set("keyX", "ValueX");
dict_f.Set("keyE", "ValueE5");
// Case 1: kTestPolicyName1 - Merging should only keep keys with the highest
// priority
PolicyMap::Entry case1(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value(dict_a.Clone()),
nullptr);
case1.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(dict_b.Clone()), nullptr));
case1.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_COMMAND_LINE,
base::Value(dict_c.Clone()), nullptr));
base::Value::Dict merged_dict_case1;
merged_dict_case1.Merge(dict_c.Clone());
merged_dict_case1.Merge(dict_b.Clone());
merged_dict_case1.Merge(dict_a.Clone());
PolicyMap::Entry expected_case1(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_MERGED,
base::Value(merged_dict_case1.Clone()), nullptr);
expected_case1.AddConflictingPolicy(case1.DeepCopy());
// Case 2 - kTestPolicyName2
// Policies should only be merged with other policies with the same target,
// level and scope.
PolicyMap::Entry case2(POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value(dict_e.Clone()),
nullptr);
case2.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(dict_f.Clone()), nullptr));
case2.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(dict_a.Clone()), nullptr));
base::Value::Dict merged_dict_case2;
merged_dict_case2.Merge(dict_f.Clone());
merged_dict_case2.Merge(dict_e.Clone());
PolicyMap::Entry expected_case2(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_MERGED,
base::Value(merged_dict_case2.Clone()), nullptr);
expected_case2.AddConflictingPolicy(case2.DeepCopy());
// Case 3 - kTestPolicyName3
// Enterprise default policies should not be merged with other sources.
PolicyMap::Entry case3(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value(dict_a.Clone()),
nullptr);
case3.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_COMMAND_LINE,
base::Value(dict_b.Clone()), nullptr));
case3.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(dict_e.Clone()), nullptr));
case3.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(dict_f.Clone()), nullptr));
base::Value::Dict merged_dict_case3;
merged_dict_case3.Merge(dict_b.Clone());
merged_dict_case3.Merge(dict_a.Clone());
PolicyMap::Entry expected_case3(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_MERGED,
base::Value(merged_dict_case3.Clone()), nullptr);
expected_case3.AddConflictingPolicy(case3.DeepCopy());
// Case 4 - kTestPolicyName4
// Policies with a single source should stay the same.
PolicyMap::Entry case4(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(dict_a.Clone()),
nullptr);
PolicyMap::Entry expected_case4 = case4.DeepCopy();
// Case 5 - kTestPolicyName5
// Policies that are not dictionaries should not be merged.
// If such a policy is explicitly in the list of policies to merge, an error
// is added to the entry and the policy stays intact.
PolicyMap::Entry case5(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value("bad stuff"),
nullptr);
PolicyMap::Entry expected_case5 = case5.DeepCopy();
expected_case5.AddMessage(
PolicyMap::MessageType::kError,
IDS_POLICY_DICTIONARY_MERGING_WRONG_POLICY_TYPE_SPECIFIED);
// Case 6 - kTestPolicyName6
// User cloud policies should not be merged with other sources.
PolicyMap::Entry case6(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(dict_a.Clone()),
nullptr);
case6.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value(dict_e.Clone()), nullptr));
case6.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value(dict_f.Clone()), nullptr));
PolicyMap::Entry expected_case6(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_MERGED,
base::Value(dict_a.Clone()), nullptr);
expected_case6.AddConflictingPolicy(case6.DeepCopy());
// Case 7 - kTestPolicyName7
// User platform policies should not be merged under any circumstances.
PolicyMap::Entry case7(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(dict_a.Clone()),
nullptr);
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(dict_b.Clone()), nullptr));
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value(dict_c.Clone()), nullptr));
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(dict_d.Clone()), nullptr));
case7.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_COMMAND_LINE,
base::Value(dict_e.Clone()), nullptr));
PolicyMap::Entry expected_case7(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_MERGED,
base::Value(dict_a.Clone()), nullptr);
expected_case7.AddConflictingPolicy(case7.DeepCopy());
// Case 8 - kTestPolicyName8
// If a dictionary policy is not in the list of dictionary policies allowed to
// be merged, an error is added to the entry and the policy stays intact.
PolicyMap::Entry case8(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(dict_a.Clone()),
nullptr);
PolicyMap::Entry expected_case8 = case8.DeepCopy();
expected_case8.AddMessage(PolicyMap::MessageType::kError,
IDS_POLICY_DICTIONARY_MERGING_POLICY_NOT_ALLOWED);
PolicyMap policy_not_merged;
policy_not_merged.Set(kTestPolicyName1, case1.DeepCopy());
policy_not_merged.Set(kTestPolicyName2, case2.DeepCopy());
policy_not_merged.Set(kTestPolicyName3, case3.DeepCopy());
policy_not_merged.Set(kTestPolicyName4, case4.DeepCopy());
policy_not_merged.Set(kTestPolicyName5, case5.DeepCopy());
policy_not_merged.Set(kTestPolicyName6, case6.DeepCopy());
policy_not_merged.Set(kTestPolicyName7, case7.DeepCopy());
policy_not_merged.Set(kTestPolicyName8, case8.DeepCopy());
PolicyMap expected_list_merged;
expected_list_merged.Set(kTestPolicyName1, expected_case1.DeepCopy());
expected_list_merged.Set(kTestPolicyName2, expected_case2.DeepCopy());
expected_list_merged.Set(kTestPolicyName3, expected_case3.DeepCopy());
expected_list_merged.Set(kTestPolicyName4, expected_case4.DeepCopy());
expected_list_merged.Set(kTestPolicyName5, expected_case5.DeepCopy());
expected_list_merged.Set(kTestPolicyName6, expected_case6.DeepCopy());
expected_list_merged.Set(kTestPolicyName7, expected_case7.DeepCopy());
expected_list_merged.Set(kTestPolicyName8, expected_case8.DeepCopy());
PolicyMap list_merged = policy_not_merged.Clone();
PolicyMap list_merged_wildcard = policy_not_merged.Clone();
// Merging with no restrictions specified
PolicyDictionaryMerger empty_policy_list({});
list_merged.MergeValues({&empty_policy_list});
EXPECT_TRUE(list_merged.Equals(policy_not_merged));
PolicyDictionaryMerger bad_policy_list({"unknown"});
// Merging with wrong restrictions specified
list_merged.MergeValues({&bad_policy_list});
EXPECT_TRUE(list_merged.Equals(policy_not_merged));
// Merging lists restrictions specified
PolicyDictionaryMerger good_policy_list(
{kTestPolicyName1, kTestPolicyName2, kTestPolicyName3, kTestPolicyName4,
kTestPolicyName5, kTestPolicyName6, kTestPolicyName7, kTestPolicyName8});
good_policy_list.SetAllowedPoliciesForTesting(
{kTestPolicyName1, kTestPolicyName2, kTestPolicyName3, kTestPolicyName4,
kTestPolicyName5, kTestPolicyName6, kTestPolicyName7});
PolicyDictionaryMerger wildcard_policy_list({"*"});
wildcard_policy_list.SetAllowedPoliciesForTesting(
{kTestPolicyName1, kTestPolicyName2, kTestPolicyName3, kTestPolicyName4,
kTestPolicyName5, kTestPolicyName6, kTestPolicyName7});
list_merged.MergeValues({&good_policy_list});
EXPECT_TRUE(list_merged.Equals(expected_list_merged));
PolicyMap expected_list_merged_wildcard = expected_list_merged.Clone();
expected_list_merged_wildcard.Set(kTestPolicyName5, case5.DeepCopy());
expected_list_merged_wildcard.Set(kTestPolicyName8, case8.DeepCopy());
list_merged_wildcard.MergeValues({&wildcard_policy_list});
EXPECT_TRUE(list_merged_wildcard.Equals(expected_list_merged_wildcard));
}
TEST_F(PolicyMapTest, MergeValuesGroup) {
base::Value::List abc = GetList<std::string>({"a", "b", "c"});
base::Value::List ab = GetList<std::string>({"a", "b"});
base::Value::List cd = GetList<std::string>({"c", "d"});
base::Value::List ef = GetList<std::string>({"e", "f"});
// Case 1 - kTestPolicyName1
// Should not be affected by the atomic groups
PolicyMap::Entry platform_user_mandatory(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(abc.Clone()), nullptr);
platform_user_mandatory.AddConflictingPolicy(
PolicyMap::Entry(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(cd.Clone()), nullptr));
platform_user_mandatory.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(ef.Clone()), nullptr));
platform_user_mandatory.AddConflictingPolicy(PolicyMap::Entry(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(ef.Clone()), nullptr));
// Case 2 - policy::key::kExtensionInstallBlocklist
// This policy is part of the atomic group "Extensions" and has the highest
// source in its group, its value should remain the same.
PolicyMap::Entry platform_machine_mandatory(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(ab.Clone()), nullptr);
platform_machine_mandatory.AddConflictingPolicy(
PolicyMap::Entry(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(cd.Clone()), nullptr));
// Case 3 - policy::key::kExtensionInstallAllowlist
// This policy is part of the atomic group "Extensions" and has a lower
// source than policy::key::kExtensionInstallBlocklist from the same group,
// its value should be ignored.
PolicyMap::Entry cloud_machine_mandatory(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(ef.Clone()), nullptr);
auto cloud_machine_mandatory_ignored = cloud_machine_mandatory.DeepCopy();
cloud_machine_mandatory_ignored.SetIgnoredByPolicyAtomicGroup();
// Case 4 - policy::key::kExtensionInstallBlocklist
// This policy is part of the atomic group "Extensions" and has the highest
// source in its group, its value should remain the same.
PolicyMap::Entry platform_machine_recommended(
POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(ab.Clone()), nullptr);
PolicyMap policy_not_merged;
policy_not_merged.Set(kTestPolicyName1, platform_user_mandatory.DeepCopy());
policy_not_merged.Set(policy::key::kPopupsAllowedForUrls,
platform_machine_mandatory.DeepCopy());
policy_not_merged.Set(policy::key::kPopupsBlockedForUrls,
cloud_machine_mandatory.DeepCopy());
policy_not_merged.Set(policy::key::kDefaultPopupsSetting,
platform_machine_recommended.DeepCopy());
PolicyMap group_merged = policy_not_merged.Clone();
PolicyGroupMerger group_merger;
group_merged.MergeValues({&group_merger});
PolicyMap expected_group_merged;
expected_group_merged.Set(kTestPolicyName1,
platform_user_mandatory.DeepCopy());
expected_group_merged.Set(policy::key::kPopupsAllowedForUrls,
platform_machine_mandatory.DeepCopy());
expected_group_merged.Set(policy::key::kPopupsBlockedForUrls,
cloud_machine_mandatory_ignored.DeepCopy());
expected_group_merged.Set(policy::key::kDefaultPopupsSetting,
platform_machine_recommended.DeepCopy());
EXPECT_TRUE(group_merged.Equals(expected_group_merged));
}
TEST_F(PolicyMapTest, LoadFromSetsLevelScopeAndSource) {
base::Value::Dict policies;
policies.Set("TestPolicy1", "google.com");
policies.Set("TestPolicy2", true);
policies.Set("TestPolicy3", -12321);
PolicyMap loaded;
loaded.LoadFrom(policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM);
PolicyMap expected;
expected.Set("TestPolicy1", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value("google.com"), nullptr);
expected.Set("TestPolicy2", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(true), nullptr);
expected.Set("TestPolicy3", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(-12321), nullptr);
EXPECT_TRUE(loaded.Equals(expected));
}
TEST_F(PolicyMapTest, LoadFromCheckForExternalPolicy) {
base::Value::Dict policies;
policies.Set("TestPolicy1", "google.com");
PolicyMap loaded;
loaded.set_chrome_policy_details_callback_for_test(
base::BindRepeating(&PolicyMapTest::GetPolicyDetailsExternalCallback,
base::Unretained(this)));
loaded.LoadFrom(policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM);
EXPECT_TRUE(loaded.empty());
loaded.set_chrome_policy_details_callback_for_test(
base::BindRepeating(&PolicyMapTest::GetPolicyDetailsNonExternalCallback,
base::Unretained(this)));
loaded.LoadFrom(policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM);
EXPECT_FALSE(loaded.empty());
}
bool IsMandatory(PolicyMap::const_reference entry) {
return entry.second.level == POLICY_LEVEL_MANDATORY;
}
TEST_F(PolicyMapTest, CloneIf) {
PolicyMap a;
a.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("google.com"), nullptr);
a.Set(kTestPolicyName2, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
PolicyMap clone = a.CloneIf(base::BindRepeating(&IsMandatory));
PolicyMap b;
b.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("google.com"), nullptr);
EXPECT_TRUE(clone.Equals(b));
}
TEST_F(PolicyMapTest, EntryAddConflict) {
base::Value::List ab = GetList<std::string>({"a", "b"});
base::Value::List cd = GetList<std::string>({"c", "d"});
base::Value::List ef = GetList<std::string>({"e", "f"});
base::Value::List gh = GetList<std::string>({"g", "h"});
// Case 1: Non-nested conflicts
PolicyMap::Entry case1(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ab.Clone()),
nullptr);
PolicyMap::Entry conflict11(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(cd.Clone()),
nullptr);
PolicyMap::Entry conflict12(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ef.Clone()),
nullptr);
PolicyMap::Entry conflict13(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(gh.Clone()),
nullptr);
PolicyMap::Entry conflict14(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ab.Clone()),
nullptr);
case1.AddConflictingPolicy(conflict11.DeepCopy());
case1.AddConflictingPolicy(conflict12.DeepCopy());
case1.AddConflictingPolicy(conflict13.DeepCopy());
case1.AddConflictingPolicy(conflict14.DeepCopy());
EXPECT_TRUE(case1.conflicts.size() == 4);
EXPECT_TRUE(case1.conflicts.at(0).entry().Equals(conflict11));
EXPECT_TRUE(case1.conflicts.at(1).entry().Equals(conflict12));
EXPECT_TRUE(case1.conflicts.at(2).entry().Equals(conflict13));
EXPECT_TRUE(case1.conflicts.at(3).entry().Equals(conflict14));
EXPECT_EQ(case1.conflicts.at(0).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(case1.conflicts.at(1).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(case1.conflicts.at(2).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(case1.conflicts.at(3).conflict_type(),
PolicyMap::ConflictType::Supersede);
// Case 2: Nested conflicts
PolicyMap::Entry case2(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ab.Clone()),
nullptr);
PolicyMap::Entry conflict21(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(cd.Clone()),
nullptr);
PolicyMap::Entry conflict22(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(cd.Clone()),
nullptr);
PolicyMap::Entry conflict23(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(ef.Clone()),
nullptr);
PolicyMap::Entry conflict24(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(gh.Clone()),
nullptr);
conflict21.AddConflictingPolicy(conflict22.DeepCopy());
conflict21.AddConflictingPolicy(conflict23.DeepCopy());
conflict21.AddConflictingPolicy(conflict24.DeepCopy());
case2.AddConflictingPolicy(conflict21.DeepCopy());
EXPECT_TRUE(case2.conflicts.size() == 4);
EXPECT_TRUE(case2.conflicts.at(0).entry().Equals(conflict22));
EXPECT_TRUE(case2.conflicts.at(1).entry().Equals(conflict23));
EXPECT_TRUE(case2.conflicts.at(2).entry().Equals(conflict24));
EXPECT_TRUE(conflict21.conflicts.at(0).entry().Equals(conflict22));
EXPECT_TRUE(conflict21.conflicts.at(1).entry().Equals(conflict23));
EXPECT_TRUE(conflict21.conflicts.at(2).entry().Equals(conflict24));
EXPECT_EQ(case2.conflicts.at(0).conflict_type(),
PolicyMap::ConflictType::Supersede);
EXPECT_EQ(case2.conflicts.at(1).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(case2.conflicts.at(2).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(case2.conflicts.at(3).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(conflict21.conflicts.at(0).conflict_type(),
PolicyMap::ConflictType::Supersede);
EXPECT_EQ(conflict21.conflicts.at(1).conflict_type(),
PolicyMap::ConflictType::Override);
EXPECT_EQ(conflict21.conflicts.at(2).conflict_type(),
PolicyMap::ConflictType::Override);
}
TEST_F(PolicyMapTest, BlockedEntry) {
PolicyMap::Entry entry_a(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("a"), nullptr);
PolicyMap::Entry entry_b = entry_a.DeepCopy();
entry_b.set_value(base::Value("b"));
PolicyMap::Entry entry_c_blocked = entry_a.DeepCopy();
entry_c_blocked.set_value(base::Value("c"));
entry_c_blocked.SetBlocked();
PolicyMap policies;
policies.Set("a", entry_a.DeepCopy());
policies.Set("b", entry_b.DeepCopy());
policies.Set("c", entry_c_blocked.DeepCopy());
const size_t expected_size = 3;
EXPECT_EQ(policies.size(), expected_size);
EXPECT_TRUE(policies.Get("a")->Equals(entry_a));
EXPECT_TRUE(policies.Get("b")->Equals(entry_b));
EXPECT_EQ(policies.Get("c"), nullptr);
EXPECT_TRUE(policies.GetMutable("a")->Equals(entry_a));
EXPECT_TRUE(policies.GetMutable("b")->Equals(entry_b));
EXPECT_EQ(policies.GetMutable("c"), nullptr);
EXPECT_EQ(*policies.GetValue("a", base::Value::Type::STRING),
*entry_a.value(base::Value::Type::STRING));
EXPECT_EQ(*policies.GetValue("b", base::Value::Type::STRING),
*entry_b.value(base::Value::Type::STRING));
EXPECT_EQ(policies.GetValue("c", base::Value::Type::STRING), nullptr);
EXPECT_EQ(*policies.GetValueUnsafe("a"), *entry_a.value_unsafe());
EXPECT_EQ(*policies.GetValueUnsafe("b"), *entry_b.value_unsafe());
EXPECT_EQ(policies.GetValueUnsafe("c"), nullptr);
EXPECT_EQ(*policies.GetMutableValue("a", base::Value::Type::STRING),
*entry_a.value(base::Value::Type::STRING));
EXPECT_EQ(*policies.GetMutableValue("b", base::Value::Type::STRING),
*entry_b.value(base::Value::Type::STRING));
EXPECT_EQ(policies.GetMutableValue("c", base::Value::Type::STRING), nullptr);
EXPECT_EQ(*policies.GetMutableValueUnsafe("a"), *entry_a.value_unsafe());
EXPECT_EQ(*policies.GetMutableValueUnsafe("b"), *entry_b.value_unsafe());
EXPECT_EQ(policies.GetMutableValueUnsafe("c"), nullptr);
EXPECT_TRUE(policies.GetUntrusted("a")->Equals(entry_a));
EXPECT_TRUE(policies.GetUntrusted("b")->Equals(entry_b));
EXPECT_TRUE(policies.GetUntrusted("c")->Equals(entry_c_blocked));
EXPECT_TRUE(policies.GetMutableUntrusted("a")->Equals(entry_a));
EXPECT_TRUE(policies.GetMutableUntrusted("b")->Equals(entry_b));
EXPECT_TRUE(policies.GetMutableUntrusted("c")->Equals(entry_c_blocked));
EXPECT_FALSE(policies.GetUntrusted("a")->ignored());
EXPECT_FALSE(policies.GetUntrusted("b")->ignored());
EXPECT_TRUE(policies.GetUntrusted("c")->ignored());
size_t iterated_values = 0;
for (auto it = policies.begin(); it != policies.end();
++it, ++iterated_values) {
}
EXPECT_TRUE(iterated_values == expected_size);
}
TEST_F(PolicyMapTest, InvalidEntry) {
PolicyMap::Entry entry_a(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("a"), nullptr);
PolicyMap::Entry entry_b_invalid = entry_a.DeepCopy();
entry_b_invalid.set_value(base::Value("b"));
entry_b_invalid.SetInvalid();
PolicyMap policies;
policies.Set("a", entry_a.DeepCopy());
policies.Set("b", entry_b_invalid.DeepCopy());
const size_t expected_size = 2;
EXPECT_EQ(policies.size(), expected_size);
EXPECT_TRUE(policies.Get("a")->Equals(entry_a));
EXPECT_EQ(policies.Get("b"), nullptr);
EXPECT_TRUE(policies.GetMutable("a")->Equals(entry_a));
EXPECT_EQ(policies.GetMutable("b"), nullptr);
EXPECT_EQ(*policies.GetValue("a", base::Value::Type::STRING),
*entry_a.value(base::Value::Type::STRING));
EXPECT_EQ(policies.GetValue("b", base::Value::Type::STRING), nullptr);
EXPECT_EQ(*policies.GetValueUnsafe("a"), *entry_a.value_unsafe());
EXPECT_EQ(policies.GetValueUnsafe("b"), nullptr);
EXPECT_EQ(*policies.GetMutableValue("a", base::Value::Type::STRING),
*entry_a.value(base::Value::Type::STRING));
EXPECT_EQ(policies.GetMutableValue("b", base::Value::Type::STRING), nullptr);
EXPECT_EQ(*policies.GetMutableValueUnsafe("a"), *entry_a.value_unsafe());
EXPECT_EQ(policies.GetMutableValueUnsafe("b"), nullptr);
EXPECT_TRUE(policies.GetUntrusted("a")->Equals(entry_a));
EXPECT_TRUE(policies.GetUntrusted("b")->Equals(entry_b_invalid));
EXPECT_TRUE(policies.GetMutableUntrusted("a")->Equals(entry_a));
EXPECT_TRUE(policies.GetMutableUntrusted("b")->Equals(entry_b_invalid));
EXPECT_FALSE(policies.GetUntrusted("a")->ignored());
EXPECT_TRUE(policies.GetUntrusted("b")->ignored());
size_t iterated_values = 0;
for (auto it = policies.begin(); it != policies.end();
++it, ++iterated_values) {
}
EXPECT_EQ(iterated_values, expected_size);
policies.SetAllInvalid();
EXPECT_TRUE(policies.GetUntrusted("a")->ignored());
EXPECT_TRUE(policies.GetUntrusted("b")->ignored());
}
TEST_F(PolicyMapTest, Affiliation) {
PolicyMap policies;
EXPECT_FALSE(policies.IsUserAffiliated());
base::flat_set<std::string> user_ids;
user_ids.insert("a");
base::flat_set<std::string> device_ids;
device_ids.insert("b");
policies.SetUserAffiliationIds(user_ids);
policies.SetDeviceAffiliationIds(device_ids);
// Affiliation check fails because user and device IDs don't have at least one
// ID in common.
EXPECT_FALSE(policies.IsUserAffiliated());
user_ids.insert("b");
device_ids.insert("c");
policies.SetUserAffiliationIds(user_ids);
policies.SetDeviceAffiliationIds(device_ids);
// Affiliation check succeeds now that 'a' is present in user and device IDs.
EXPECT_TRUE(policies.IsUserAffiliated());
}
#if !BUILDFLAG(IS_CHROMEOS)
class PolicyMapMergeTest
: public PolicyMapTestBase,
public testing::TestWithParam<
std::tuple</*cloud_policy_overrides_platform_policy=*/bool,
/*cloud_user_policy_overrides_cloud_machine_policy=*/bool,
/*is_user_affiliated=*/bool,
/*metapolicies_are_incoming=*/bool>> {
public:
bool CloudPolicyOverridesPlatformPolicy() const {
return std::get<0>(GetParam());
}
bool CloudUserPolicyOverridesCloudMachinePolicy() const {
return std::get<1>(GetParam());
}
bool IsUserAffiliated() const { return std::get<2>(GetParam()); }
bool MetapoliciesAreIncoming() const { return std::get<3>(GetParam()); }
void PopulateExpectedPolicyMap(PolicyMap& policy_map_expected,
const PolicyMap& policy_map_1,
const PolicyMap& policy_map_2) {
// Setting the metapolicies.
policy_map_expected.Set(
key::kCloudPolicyOverridesPlatformPolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map_expected.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
// Expected behavior independent of metapolicy values and affiliation.
// -------------------------------------------------------------------
// |policy_map_1| has precedence over |policy_map_2|.
policy_map_expected.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(true), nullptr);
policy_map_expected.GetMutable(kTestPolicyName2)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName2)
->AddConflictingPolicy(policy_map_2.Get(kTestPolicyName2)->DeepCopy());
policy_map_expected.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, absl::nullopt,
CreateExternalDataFetcher("a"));
policy_map_expected.GetMutable(kTestPolicyName3)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName3)
->AddConflictingPolicy(policy_map_2.Get(kTestPolicyName3)->DeepCopy());
// Cloud machine over platform user for recommended policies.
policy_map_expected.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(true), nullptr);
policy_map_expected.GetMutable(kTestPolicyName4)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName4)
->AddConflictingPolicy(policy_map_1.Get(kTestPolicyName4)->DeepCopy());
// Mandatory over recommended level.
policy_map_expected.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(std::string()), nullptr);
policy_map_expected.GetMutable(kTestPolicyName5)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName5)
->AddConflictingPolicy(policy_map_1.Get(kTestPolicyName5)->DeepCopy());
// Merge new policy.
policy_map_expected.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value(true), nullptr);
// Platform over default source.
policy_map_expected.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(true), nullptr);
policy_map_expected.GetMutable(kTestPolicyName7)->SetBlocked();
// Expected behavior that depends on metapolicy values and affiliation.
// --------------------------------------------------------------------
#if !BUILDFLAG(IS_CHROMEOS)
if (CloudPolicyOverridesPlatformPolicy() &&
CloudUserPolicyOverridesCloudMachinePolicy() && IsUserAffiliated()) {
// Cloud user over cloud machine source.
policy_map_expected.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("google.com"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddConflictingPolicy(
policy_map_2.Get(kTestPolicyName1)->DeepCopy());
// Cloud machine over platform machine when platform is blocked.
policy_map_expected.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("non-blocked cloud policy"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddConflictingPolicy(
policy_map_1.Get(kTestPolicyName8)->DeepCopy());
// policy_map_expected.GetMutable(kTestPolicyName8)->SetBlocked();
} else if (CloudUserPolicyOverridesCloudMachinePolicy() &&
IsUserAffiliated()) {
// Cloud user over cloud machine source.
policy_map_expected.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("google.com"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddConflictingPolicy(
policy_map_2.Get(kTestPolicyName1)->DeepCopy());
// Platform machine over cloud machine even when platform is blocked.
policy_map_expected.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value("blocked platform policy"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddConflictingPolicy(
policy_map_2.Get(kTestPolicyName8)->DeepCopy());
policy_map_expected.GetMutable(kTestPolicyName8)->SetBlocked();
} else if (CloudPolicyOverridesPlatformPolicy()) {
// Machine over user scope.
policy_map_expected.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("chromium.org"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddConflictingPolicy(
policy_map_1.Get(kTestPolicyName1)->DeepCopy());
// Cloud machine over platform machine when platform is blocked.
policy_map_expected.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("non-blocked cloud policy"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddConflictingPolicy(
policy_map_1.Get(kTestPolicyName8)->DeepCopy());
// policy_map_expected.GetMutable(kTestPolicyName8)->SetBlocked();
} else {
#endif // !BUILDFLAG(IS_CHROMEOS)
// Machine over user scope.
policy_map_expected.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("chromium.org"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName1)
->AddConflictingPolicy(
policy_map_1.Get(kTestPolicyName1)->DeepCopy());
// Platform machine over cloud machine even when platform is blocked.
policy_map_expected.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value("blocked platform policy"), nullptr);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(kTestPolicyName8)
->AddConflictingPolicy(
policy_map_2.Get(kTestPolicyName8)->DeepCopy());
policy_map_expected.GetMutable(kTestPolicyName8)->SetBlocked();
#if !BUILDFLAG(IS_CHROMEOS)
}
#endif // !BUILDFLAG(IS_CHROMEOS)
}
void PopulateExpectedMetapolicyMap(PolicyMap& policy_map_expected,
const PolicyMap& policy_map_1,
const PolicyMap& policy_map_2,
base::Value::List merge_list_1,
base::Value::List merge_list_2) {
// Platform machine overrides cloud machine because modified priorities
// don't apply to precedence metapolicies.
policy_map_expected.Set(
key::kCloudPolicyOverridesPlatformPolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map_expected.GetMutable(key::kCloudPolicyOverridesPlatformPolicy)
->AddMessage(CloudPolicyOverridesPlatformPolicy()
? PolicyMap::MessageType::kWarning
: PolicyMap::MessageType::kInfo,
CloudPolicyOverridesPlatformPolicy()
? IDS_POLICY_CONFLICT_DIFF_VALUE
: IDS_POLICY_CONFLICT_SAME_VALUE);
policy_map_expected.GetMutable(key::kCloudPolicyOverridesPlatformPolicy)
->AddConflictingPolicy(
policy_map_2.Get(key::kCloudPolicyOverridesPlatformPolicy)
->DeepCopy());
policy_map_expected.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
policy_map_expected
.GetMutable(key::kCloudUserPolicyOverridesCloudMachinePolicy)
->AddMessage(CloudUserPolicyOverridesCloudMachinePolicy()
? PolicyMap::MessageType::kWarning
: PolicyMap::MessageType::kInfo,
CloudUserPolicyOverridesCloudMachinePolicy()
? IDS_POLICY_CONFLICT_DIFF_VALUE
: IDS_POLICY_CONFLICT_SAME_VALUE);
policy_map_expected
.GetMutable(key::kCloudUserPolicyOverridesCloudMachinePolicy)
->AddConflictingPolicy(
policy_map_1.Get(key::kCloudUserPolicyOverridesCloudMachinePolicy)
->DeepCopy());
#if !BUILDFLAG(IS_CHROMEOS)
if (CloudPolicyOverridesPlatformPolicy()) {
// Cloud machine overrides platform machine because modified priorities
// apply to merging metapolicies.
policy_map_expected.Set(key::kPolicyListMultipleSourceMergeList,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD,
base::Value(std::move(merge_list_2)), nullptr);
policy_map_expected.GetMutable(key::kPolicyListMultipleSourceMergeList)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(key::kPolicyListMultipleSourceMergeList)
->AddConflictingPolicy(
policy_map_1.Get(key::kPolicyListMultipleSourceMergeList)
->DeepCopy());
} else {
#endif // !BUILDFLAG(IS_CHROMEOS)
// Platform machine overrides cloud machine with default precedence.
policy_map_expected.Set(key::kPolicyListMultipleSourceMergeList,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM,
base::Value(std::move(merge_list_1)), nullptr);
policy_map_expected.GetMutable(key::kPolicyListMultipleSourceMergeList)
->AddMessage(PolicyMap::MessageType::kWarning,
IDS_POLICY_CONFLICT_DIFF_VALUE);
policy_map_expected.GetMutable(key::kPolicyListMultipleSourceMergeList)
->AddConflictingPolicy(
policy_map_2.Get(key::kPolicyListMultipleSourceMergeList)
->DeepCopy());
#if !BUILDFLAG(IS_CHROMEOS)
}
#endif // !BUILDFLAG(IS_CHROMEOS)
}
};
TEST_P(PolicyMapMergeTest, MergeFrom) {
PolicyMap policy_map_1;
if (IsUserAffiliated()) {
base::flat_set<std::string> affiliation_ids;
affiliation_ids.insert("12345");
// Treat user as affiliated by setting identical user and device IDs.
policy_map_1.SetUserAffiliationIds(affiliation_ids);
policy_map_1.SetDeviceAffiliationIds(affiliation_ids);
}
if (!MetapoliciesAreIncoming()) {
// Metapolicies are set in the base PolicyMap.
policy_map_1.Set(
key::kCloudPolicyOverridesPlatformPolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map_1.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
}
policy_map_1.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value("google.com"), nullptr);
policy_map_1.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, base::Value(true),
nullptr);
policy_map_1.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_ENTERPRISE_DEFAULT,
absl::nullopt, CreateExternalDataFetcher("a"));
policy_map_1.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_USER, POLICY_SOURCE_PLATFORM,
base::Value(false), nullptr);
policy_map_1.Set(kTestPolicyName5, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("google.com/q={x}"), nullptr);
policy_map_1.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(false),
nullptr);
policy_map_1.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value("blocked platform policy"), nullptr);
PolicyMap policy_map_2;
if (MetapoliciesAreIncoming()) {
// Metapolicies are set in the incoming PolicyMap.
policy_map_2.Set(
key::kCloudPolicyOverridesPlatformPolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map_2.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
}
policy_map_2.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("chromium.org"), nullptr);
policy_map_2.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value(false), nullptr);
policy_map_2.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_ENTERPRISE_DEFAULT,
absl::nullopt, CreateExternalDataFetcher("b"));
policy_map_2.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, base::Value(true),
nullptr);
policy_map_2.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(std::string()), nullptr);
policy_map_2.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true),
nullptr);
policy_map_2.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(true), nullptr);
policy_map_2.Set(kTestPolicyName8, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
base::Value("non-blocked cloud policy"), nullptr);
PolicyMap policy_map_expected;
PopulateExpectedPolicyMap(policy_map_expected, policy_map_1, policy_map_2);
policy_map_1.GetMutable(kTestPolicyName7)->SetBlocked();
policy_map_2.GetMutable(kTestPolicyName7)->SetBlocked();
policy_map_1.GetMutable(kTestPolicyName8)->SetBlocked();
policy_map_1.MergeFrom(policy_map_2, /*merge_precedence_metapolicies=*/true);
policy_map_1.MergeFrom(policy_map_2);
EXPECT_TRUE(policy_map_1.Equals(policy_map_expected));
}
TEST_P(PolicyMapMergeTest, MergeFrom_Metapolicies) {
// Define the lists of policies that will be used by the merging metapolicies.
base::Value::List merge_list_1;
merge_list_1.Append(kTestPolicyName1);
base::Value::List merge_list_2;
merge_list_2.Append(kTestPolicyName2);
PolicyMap policy_map_1;
if (IsUserAffiliated()) {
base::flat_set<std::string> affiliation_ids;
affiliation_ids.insert("12345");
policy_map_1.SetUserAffiliationIds(affiliation_ids);
policy_map_1.SetDeviceAffiliationIds(affiliation_ids);
}
policy_map_1.Set(key::kCloudPolicyOverridesPlatformPolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map_1.Set(key::kCloudUserPolicyOverridesCloudMachinePolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(false), nullptr);
policy_map_1.Set(key::kPolicyListMultipleSourceMergeList,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM, base::Value(merge_list_1.Clone()),
nullptr);
PolicyMap policy_map_2;
policy_map_2.Set(key::kCloudPolicyOverridesPlatformPolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(false), nullptr);
policy_map_2.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
policy_map_2.Set(key::kPolicyListMultipleSourceMergeList,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(merge_list_2.Clone()),
nullptr);
PolicyMap policy_map_expected;
PopulateExpectedMetapolicyMap(policy_map_expected, policy_map_1, policy_map_2,
std::move(merge_list_1),
std::move(merge_list_2));
policy_map_1.MergeFrom(policy_map_2, /*merge_precedence_metapolicies=*/true);
policy_map_1.MergeFrom(policy_map_2);
EXPECT_TRUE(policy_map_1.Equals(policy_map_expected));
}
INSTANTIATE_TEST_SUITE_P(PolicyMapMergeTestInstance,
PolicyMapMergeTest,
testing::Combine(testing::Values(false, true),
testing::Values(false, true),
testing::Values(false, true),
testing::Values(false, true)));
class PolicyMapPriorityTest
: public testing::TestWithParam<
std::tuple</*cloud_policy_overrides_platform_policy=*/bool,
/*cloud_user_policy_overrides_cloud_machine_policy=*/bool,
/*is_user_affiliated=*/bool>> {
public:
bool CloudPolicyOverridesPlatformPolicy() { return std::get<0>(GetParam()); }
bool CloudUserPolicyOverridesCloudMachinePolicy() {
return std::get<1>(GetParam());
}
bool IsUserAffiliated() { return std::get<2>(GetParam()); }
void CheckPriorityConditions(PolicyMap& policy_map) {
PolicyMap::Entry platform_machine(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(), nullptr);
PolicyMap::Entry platform_user(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, base::Value(),
nullptr);
PolicyMap::Entry cloud_machine(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_CLOUD, base::Value(), nullptr);
PolicyMap::Entry cloud_user(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_CLOUD, base::Value(), nullptr);
PolicyMap::Entry command_line(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_COMMAND_LINE, base::Value(),
nullptr);
PolicyMap::Entry enterprise_default(
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_ENTERPRISE_DEFAULT, base::Value(), nullptr);
// The policy priority conditions depend on the precedence metapolicy values
// and user affiliation.
if (CloudPolicyOverridesPlatformPolicy() &&
CloudUserPolicyOverridesCloudMachinePolicy() && IsUserAffiliated()) {
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, platform_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(platform_user, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(command_line, enterprise_default));
} else if (CloudUserPolicyOverridesCloudMachinePolicy() &&
IsUserAffiliated()) {
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, platform_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(platform_user, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(command_line, enterprise_default));
} else if (CloudPolicyOverridesPlatformPolicy()) {
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, platform_user));
EXPECT_FALSE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(platform_user, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(command_line, enterprise_default));
} else {
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, platform_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_machine));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(platform_machine, cloud_user));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_machine, platform_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_machine, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(platform_user, cloud_user));
EXPECT_TRUE(policy_map.EntryHasHigherPriority(cloud_user, command_line));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(cloud_user, enterprise_default));
EXPECT_TRUE(
policy_map.EntryHasHigherPriority(command_line, enterprise_default));
}
}
};
TEST_P(PolicyMapPriorityTest, PriorityCheck) {
PolicyMap policy_map;
// Update the metapolicy values.
policy_map.Set(key::kCloudPolicyOverridesPlatformPolicy,
POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
POLICY_SOURCE_PLATFORM,
base::Value(CloudPolicyOverridesPlatformPolicy()), nullptr);
policy_map.Set(
key::kCloudUserPolicyOverridesCloudMachinePolicy, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
base::Value(CloudUserPolicyOverridesCloudMachinePolicy()), nullptr);
// Causes the stored metapolicy values to be updated.
PolicyMap policy_map_empty;
policy_map.MergeFrom(policy_map_empty,
/*merge_precedence_metapolicies=*/true);
if (IsUserAffiliated()) {
base::flat_set<std::string> affiliation_ids;
affiliation_ids.insert("a");
policy_map.SetUserAffiliationIds(affiliation_ids);
policy_map.SetDeviceAffiliationIds(affiliation_ids);
}
CheckPriorityConditions(policy_map);
}
INSTANTIATE_TEST_SUITE_P(PolicyMapPriorityTestInstance,
PolicyMapPriorityTest,
testing::Combine(testing::Values(false, true),
testing::Values(false, true),
testing::Values(false, true)));
#endif // !BUILDFLAG(IS_CHROMEOS)
} // namespace policy