1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/policy/core/common/policy_bundle.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/callback.h"
11 #include "base/values.h"
12 #include "components/policy/core/common/external_data_fetcher.h"
13 #include "components/policy/core/common/policy_map.h"
14 #include "components/policy/core/common/policy_types.h"
15 #include "components/strings/grit/components_strings.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace policy {
19
20 namespace {
21
22 const char kPolicyClashing0[] = "policy-clashing-0";
23 const char kPolicyClashing1[] = "policy-clashing-1";
24 const char kPolicy0[] = "policy-0";
25 const char kPolicy1[] = "policy-1";
26 const char kPolicy2[] = "policy-2";
27 const char kExtension0[] = "extension-0";
28 const char kExtension1[] = "extension-1";
29 const char kExtension2[] = "extension-2";
30 const char kExtension3[] = "extension-3";
31
32 // Adds test policies to |policy|.
AddTestPolicies(PolicyMap * policy)33 void AddTestPolicies(PolicyMap* policy) {
34 policy->Set("mandatory-user", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
35 POLICY_SOURCE_CLOUD, base::Value(123), nullptr);
36 policy->Set("mandatory-machine", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
37 POLICY_SOURCE_CLOUD, base::Value("omg"), nullptr);
38 policy->Set("recommended-user", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
39 POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
40 base::Value dict(base::Value::Type::DICTIONARY);
41 dict.SetBoolKey("false", false);
42 dict.SetIntKey("int", 456);
43 dict.SetStringKey("str", "bbq");
44 policy->Set("recommended-machine", POLICY_LEVEL_RECOMMENDED,
45 POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, std::move(dict),
46 nullptr);
47 }
48
49 // Adds test policies to |policy| based on the parameters:
50 // - kPolicyClashing0 mapped to |value|, user mandatory
51 // - kPolicyClashing1 mapped to |value|, with |level| and |scope|
52 // - |name| mapped to |value|, user mandatory
AddTestPoliciesWithParams(PolicyMap * policy,const char * name,int value,PolicyLevel level,PolicyScope scope)53 void AddTestPoliciesWithParams(PolicyMap *policy,
54 const char* name,
55 int value,
56 PolicyLevel level,
57 PolicyScope scope) {
58 policy->Set(kPolicyClashing0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
59 POLICY_SOURCE_CLOUD, base::Value(value), nullptr);
60 policy->Set(kPolicyClashing1, level, scope, POLICY_SOURCE_CLOUD,
61 base::Value(value), nullptr);
62 policy->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
63 POLICY_SOURCE_CLOUD, base::Value(value), nullptr);
64 }
65
66 // Returns true if |bundle| is empty.
IsEmpty(const PolicyBundle & bundle)67 bool IsEmpty(const PolicyBundle& bundle) {
68 return bundle.begin() == bundle.end();
69 }
70
71 } // namespace
72
TEST(PolicyBundleTest,Get)73 TEST(PolicyBundleTest, Get) {
74 PolicyBundle bundle;
75 EXPECT_TRUE(IsEmpty(bundle));
76
77 AddTestPolicies(&bundle.Get(
78 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
79 EXPECT_FALSE(IsEmpty(bundle));
80
81 PolicyMap policy;
82 AddTestPolicies(&policy);
83 EXPECT_TRUE(bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
84 std::string())).Equals(policy));
85
86 PolicyBundle::const_iterator it = bundle.begin();
87 ASSERT_TRUE(it != bundle.end());
88 EXPECT_EQ(POLICY_DOMAIN_CHROME, it->first.domain);
89 EXPECT_EQ("", it->first.component_id);
90 ASSERT_TRUE(it->second);
91 EXPECT_TRUE(it->second->Equals(policy));
92 ++it;
93 EXPECT_TRUE(it == bundle.end());
94 EXPECT_TRUE(bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
95 kExtension0)).empty());
96
97 EXPECT_FALSE(IsEmpty(bundle));
98 bundle.Clear();
99 EXPECT_TRUE(IsEmpty(bundle));
100 }
101
TEST(PolicyBundleTest,SwapAndCopy)102 TEST(PolicyBundleTest, SwapAndCopy) {
103 PolicyBundle bundle0;
104 PolicyBundle bundle1;
105
106 AddTestPolicies(&bundle0.Get(
107 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
108 AddTestPolicies(&bundle0.Get(
109 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0)));
110 EXPECT_FALSE(IsEmpty(bundle0));
111 EXPECT_TRUE(IsEmpty(bundle1));
112
113 PolicyMap policy;
114 AddTestPolicies(&policy);
115 EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
116 std::string())).Equals(policy));
117 EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
118 kExtension0)).Equals(policy));
119
120 bundle0.Swap(&bundle1);
121 EXPECT_TRUE(IsEmpty(bundle0));
122 EXPECT_FALSE(IsEmpty(bundle1));
123
124 EXPECT_TRUE(bundle1.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
125 std::string())).Equals(policy));
126 EXPECT_TRUE(bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
127 kExtension0)).Equals(policy));
128
129 bundle0.CopyFrom(bundle1);
130 EXPECT_FALSE(IsEmpty(bundle0));
131 EXPECT_FALSE(IsEmpty(bundle1));
132 EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
133 std::string())).Equals(policy));
134 EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
135 kExtension0)).Equals(policy));
136 }
137
TEST(PolicyBundleTest,MergeFrom)138 TEST(PolicyBundleTest, MergeFrom) {
139 // Each bundleN has kExtensionN. Each bundle also has policy for
140 // chrome and kExtension3.
141 // |bundle0| has the highest priority, |bundle2| the lowest.
142 PolicyBundle bundle0;
143 PolicyBundle bundle1;
144 PolicyBundle bundle2;
145
146 PolicyMap policy0;
147 AddTestPoliciesWithParams(
148 &policy0, kPolicy0, 0u, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER);
149 bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
150 .CopyFrom(policy0);
151 bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0))
152 .CopyFrom(policy0);
153 bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
154 .CopyFrom(policy0);
155
156 PolicyMap policy1;
157 AddTestPoliciesWithParams(
158 &policy1, kPolicy1, 1u, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
159 bundle1.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
160 .CopyFrom(policy1);
161 bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1))
162 .CopyFrom(policy1);
163 bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
164 .CopyFrom(policy1);
165
166 PolicyMap policy2;
167 AddTestPoliciesWithParams(
168 &policy2, kPolicy2, 2u, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
169 bundle2.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
170 .CopyFrom(policy2);
171 bundle2.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2))
172 .CopyFrom(policy2);
173 bundle2.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
174 .CopyFrom(policy2);
175
176 // Merge in order of decreasing priority.
177 PolicyBundle merged;
178 merged.MergeFrom(bundle0);
179 merged.MergeFrom(bundle1);
180 merged.MergeFrom(bundle2);
181 PolicyBundle empty_bundle;
182 merged.MergeFrom(empty_bundle);
183
184 // chrome and kExtension3 policies are merged:
185 // - kPolicyClashing0 comes from bundle0, which has the highest priority;
186 // - kPolicyClashing1 comes from bundle1, which has the highest level/scope
187 // combination;
188 // - kPolicyN are merged from each bundle.
189 PolicyMap expected;
190 expected.Set(kPolicyClashing0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
191 POLICY_SOURCE_CLOUD, base::Value(0), nullptr);
192 expected.GetMutable(kPolicyClashing0)
193 ->AddConflictingPolicy(policy1.Get(kPolicyClashing0)->DeepCopy());
194 expected.GetMutable(kPolicyClashing0)
195 ->AddConflictingPolicy(policy2.Get(kPolicyClashing0)->DeepCopy());
196 expected.GetMutable(kPolicyClashing0)
197 ->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
198 expected.GetMutable(kPolicyClashing0)
199 ->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
200 expected.Set(kPolicyClashing1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
201 POLICY_SOURCE_CLOUD, base::Value(1), nullptr);
202 expected.GetMutable(kPolicyClashing1)
203 ->AddConflictingPolicy(policy0.Get(kPolicyClashing1)->DeepCopy());
204 expected.GetMutable(kPolicyClashing1)
205 ->AddConflictingPolicy(policy2.Get(kPolicyClashing1)->DeepCopy());
206 expected.GetMutable(kPolicyClashing1)
207 ->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
208 expected.GetMutable(kPolicyClashing1)
209 ->AddWarning(IDS_POLICY_CONFLICT_DIFF_VALUE);
210 expected.Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
211 POLICY_SOURCE_CLOUD, base::Value(0), nullptr);
212 expected.Set(kPolicy1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
213 POLICY_SOURCE_CLOUD, base::Value(1), nullptr);
214 expected.Set(kPolicy2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
215 POLICY_SOURCE_CLOUD, base::Value(2), nullptr);
216 EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
217 std::string())).Equals(expected));
218 EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
219 kExtension3)).Equals(expected));
220 // extension0 comes only from bundle0.
221 EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
222 kExtension0)).Equals(policy0));
223 // extension1 comes only from bundle1.
224 EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
225 kExtension1)).Equals(policy1));
226 // extension2 comes only from bundle2.
227 EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
228 kExtension2)).Equals(policy2));
229 }
230
TEST(PolicyBundleTest,Equals)231 TEST(PolicyBundleTest, Equals) {
232 PolicyBundle bundle;
233 AddTestPolicies(&bundle.Get(
234 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
235 AddTestPolicies(&bundle.Get(
236 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0)));
237
238 PolicyBundle other;
239 EXPECT_FALSE(bundle.Equals(other));
240 other.CopyFrom(bundle);
241 EXPECT_TRUE(bundle.Equals(other));
242
243 AddTestPolicies(&bundle.Get(
244 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1)));
245 EXPECT_FALSE(bundle.Equals(other));
246 other.CopyFrom(bundle);
247 EXPECT_TRUE(bundle.Equals(other));
248 AddTestPolicies(&other.Get(
249 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2)));
250 EXPECT_FALSE(bundle.Equals(other));
251
252 other.CopyFrom(bundle);
253 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
254 .Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
255 POLICY_SOURCE_CLOUD, base::Value(123), nullptr);
256 EXPECT_FALSE(bundle.Equals(other));
257 other.CopyFrom(bundle);
258 EXPECT_TRUE(bundle.Equals(other));
259 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
260 .Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
261 POLICY_SOURCE_CLOUD, base::Value(123), nullptr);
262 EXPECT_FALSE(bundle.Equals(other));
263
264 // Test non-const Get().
265 bundle.Clear();
266 other.Clear();
267 PolicyMap& policy_map =
268 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
269 EXPECT_TRUE(bundle.Equals(other));
270 policy_map.Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
271 POLICY_SOURCE_CLOUD, base::Value(123), nullptr);
272 EXPECT_FALSE(bundle.Equals(other));
273 }
274
275 } // namespace policy
276