OLD | NEW |
| (Empty) |
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 "chrome/browser/policy/schema_map.h" | |
6 | |
7 #include "base/memory/weak_ptr.h" | |
8 #include "base/values.h" | |
9 #include "components/policy/core/common/external_data_fetcher.h" | |
10 #include "components/policy/core/common/external_data_manager.h" | |
11 #include "components/policy/core/common/policy_bundle.h" | |
12 #include "components/policy/core/common/policy_map.h" | |
13 #include "components/policy/core/common/schema.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace policy { | |
17 | |
18 namespace { | |
19 | |
20 const char kTestSchema[] = | |
21 "{" | |
22 " \"type\": \"object\"," | |
23 " \"properties\": {" | |
24 " \"string\": { \"type\": \"string\" }," | |
25 " \"integer\": { \"type\": \"integer\" }," | |
26 " \"boolean\": { \"type\": \"boolean\" }," | |
27 " \"null\": { \"type\": \"null\" }," | |
28 " \"double\": { \"type\": \"number\" }," | |
29 " \"list\": {" | |
30 " \"type\": \"array\"," | |
31 " \"items\": { \"type\": \"string\" }" | |
32 " }," | |
33 " \"object\": {" | |
34 " \"type\": \"object\"," | |
35 " \"properties\": {" | |
36 " \"a\": { \"type\": \"string\" }," | |
37 " \"b\": { \"type\": \"integer\" }" | |
38 " }" | |
39 " }" | |
40 " }" | |
41 "}"; | |
42 | |
43 } // namespace | |
44 | |
45 class SchemaMapTest : public testing::Test { | |
46 protected: | |
47 Schema CreateTestSchema() { | |
48 std::string error; | |
49 Schema schema = Schema::Parse(kTestSchema, &error); | |
50 if (!schema.valid()) | |
51 ADD_FAILURE() << error; | |
52 return schema; | |
53 } | |
54 | |
55 scoped_refptr<SchemaMap> CreateTestMap() { | |
56 Schema schema = CreateTestSchema(); | |
57 ComponentMap component_map; | |
58 component_map["extension-1"] = schema; | |
59 component_map["extension-2"] = schema; | |
60 component_map["legacy-extension"] = Schema(); | |
61 | |
62 DomainMap domain_map; | |
63 domain_map[POLICY_DOMAIN_EXTENSIONS] = component_map; | |
64 | |
65 return new SchemaMap(domain_map); | |
66 } | |
67 }; | |
68 | |
69 TEST_F(SchemaMapTest, Empty) { | |
70 scoped_refptr<SchemaMap> map = new SchemaMap(); | |
71 EXPECT_TRUE(map->GetDomains().empty()); | |
72 EXPECT_FALSE(map->GetComponents(POLICY_DOMAIN_CHROME)); | |
73 EXPECT_FALSE(map->GetComponents(POLICY_DOMAIN_EXTENSIONS)); | |
74 EXPECT_FALSE(map->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, ""))); | |
75 EXPECT_FALSE(map->HasComponents()); | |
76 } | |
77 | |
78 TEST_F(SchemaMapTest, HasComponents) { | |
79 scoped_refptr<SchemaMap> map = new SchemaMap(); | |
80 EXPECT_FALSE(map->HasComponents()); | |
81 | |
82 // The Chrome schema does not count as a component. | |
83 Schema schema = CreateTestSchema(); | |
84 ComponentMap component_map; | |
85 component_map[""] = schema; | |
86 DomainMap domain_map; | |
87 domain_map[POLICY_DOMAIN_CHROME] = component_map; | |
88 map = new SchemaMap(domain_map); | |
89 EXPECT_FALSE(map->HasComponents()); | |
90 | |
91 // An extension schema does. | |
92 domain_map[POLICY_DOMAIN_EXTENSIONS] = component_map; | |
93 map = new SchemaMap(domain_map); | |
94 EXPECT_TRUE(map->HasComponents()); | |
95 } | |
96 | |
97 TEST_F(SchemaMapTest, Lookups) { | |
98 scoped_refptr<SchemaMap> map = CreateTestMap(); | |
99 ASSERT_TRUE(map); | |
100 EXPECT_TRUE(map->HasComponents()); | |
101 | |
102 EXPECT_FALSE(map->GetSchema( | |
103 PolicyNamespace(POLICY_DOMAIN_CHROME, ""))); | |
104 EXPECT_FALSE(map->GetSchema( | |
105 PolicyNamespace(POLICY_DOMAIN_CHROME, "extension-1"))); | |
106 EXPECT_FALSE(map->GetSchema( | |
107 PolicyNamespace(POLICY_DOMAIN_CHROME, "legacy-extension"))); | |
108 EXPECT_FALSE(map->GetSchema( | |
109 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, ""))); | |
110 EXPECT_FALSE(map->GetSchema( | |
111 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "extension-3"))); | |
112 | |
113 const Schema* schema = | |
114 map->GetSchema(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "extension-1")); | |
115 ASSERT_TRUE(schema); | |
116 EXPECT_TRUE(schema->valid()); | |
117 | |
118 schema = map->GetSchema( | |
119 PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "legacy-extension")); | |
120 ASSERT_TRUE(schema); | |
121 EXPECT_FALSE(schema->valid()); | |
122 } | |
123 | |
124 TEST_F(SchemaMapTest, FilterBundle) { | |
125 std::string error; | |
126 Schema schema = Schema::Parse(kTestSchema, &error); | |
127 ASSERT_TRUE(schema.valid()) << error; | |
128 | |
129 DomainMap domain_map; | |
130 domain_map[POLICY_DOMAIN_EXTENSIONS]["abc"] = schema; | |
131 scoped_refptr<SchemaMap> schema_map = new SchemaMap(domain_map); | |
132 | |
133 PolicyBundle bundle; | |
134 schema_map->FilterBundle(&bundle); | |
135 const PolicyBundle empty_bundle; | |
136 EXPECT_TRUE(bundle.Equals(empty_bundle)); | |
137 | |
138 // The Chrome namespace isn't filtered. | |
139 PolicyBundle expected_bundle; | |
140 PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, ""); | |
141 expected_bundle.Get(chrome_ns).Set("ChromePolicy", | |
142 POLICY_LEVEL_MANDATORY, | |
143 POLICY_SCOPE_USER, | |
144 base::Value::CreateStringValue("value"), | |
145 NULL); | |
146 bundle.CopyFrom(expected_bundle); | |
147 | |
148 // Unknown components are filtered out. | |
149 PolicyNamespace another_extension_ns(POLICY_DOMAIN_EXTENSIONS, "xyz"); | |
150 bundle.Get(another_extension_ns).Set( | |
151 "AnotherExtensionPolicy", | |
152 POLICY_LEVEL_MANDATORY, | |
153 POLICY_SCOPE_USER, | |
154 base::Value::CreateStringValue("value"), | |
155 NULL); | |
156 schema_map->FilterBundle(&bundle); | |
157 EXPECT_TRUE(bundle.Equals(expected_bundle)); | |
158 | |
159 PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "abc"); | |
160 PolicyMap& map = expected_bundle.Get(extension_ns); | |
161 base::ListValue list; | |
162 list.AppendString("a"); | |
163 list.AppendString("b"); | |
164 map.Set("list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
165 list.DeepCopy(), NULL); | |
166 map.Set("boolean", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
167 base::Value::CreateBooleanValue(true), NULL); | |
168 map.Set("integer", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
169 base::Value::CreateIntegerValue(1), NULL); | |
170 map.Set("null", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
171 base::Value::CreateNullValue(), NULL); | |
172 map.Set("double", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
173 base::Value::CreateDoubleValue(1.2), NULL); | |
174 base::DictionaryValue dict; | |
175 dict.SetString("a", "b"); | |
176 dict.SetInteger("b", 2); | |
177 map.Set("object", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
178 dict.DeepCopy(), NULL); | |
179 map.Set("string", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
180 base::Value::CreateStringValue("value"), NULL); | |
181 | |
182 bundle.MergeFrom(expected_bundle); | |
183 bundle.Get(extension_ns).Set("Unexpected", | |
184 POLICY_LEVEL_MANDATORY, | |
185 POLICY_SCOPE_USER, | |
186 base::Value::CreateStringValue("to-be-removed"), | |
187 NULL); | |
188 | |
189 schema_map->FilterBundle(&bundle); | |
190 EXPECT_TRUE(bundle.Equals(expected_bundle)); | |
191 | |
192 // Mismatched types are also removed. | |
193 bundle.Clear(); | |
194 PolicyMap& badmap = bundle.Get(extension_ns); | |
195 badmap.Set("list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
196 base::Value::CreateBooleanValue(false), NULL); | |
197 badmap.Set("boolean", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
198 base::Value::CreateIntegerValue(0), NULL); | |
199 badmap.Set("integer", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
200 base::Value::CreateBooleanValue(false), NULL); | |
201 badmap.Set("null", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
202 base::Value::CreateBooleanValue(false), NULL); | |
203 badmap.Set("double", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
204 base::Value::CreateBooleanValue(false), NULL); | |
205 badmap.Set("object", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
206 base::Value::CreateBooleanValue(false), NULL); | |
207 badmap.Set("string", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | |
208 NULL, | |
209 new ExternalDataFetcher(base::WeakPtr<ExternalDataManager>(), | |
210 std::string())); | |
211 | |
212 schema_map->FilterBundle(&bundle); | |
213 EXPECT_TRUE(bundle.Equals(empty_bundle)); | |
214 } | |
215 | |
216 TEST_F(SchemaMapTest, LegacyComponents) { | |
217 std::string error; | |
218 Schema schema = Schema::Parse( | |
219 "{" | |
220 " \"type\":\"object\"," | |
221 " \"properties\": {" | |
222 " \"String\": { \"type\": \"string\" }" | |
223 " }" | |
224 "}", &error); | |
225 ASSERT_TRUE(schema.valid()) << error; | |
226 | |
227 DomainMap domain_map; | |
228 domain_map[POLICY_DOMAIN_EXTENSIONS]["with-schema"] = schema; | |
229 domain_map[POLICY_DOMAIN_EXTENSIONS]["without-schema"] = Schema(); | |
230 scoped_refptr<SchemaMap> schema_map = new SchemaMap(domain_map); | |
231 | |
232 // |bundle| contains policies loaded by a policy provider. | |
233 PolicyBundle bundle; | |
234 | |
235 // Known components with schemas are filtered. | |
236 PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "with-schema"); | |
237 bundle.Get(extension_ns).Set("String", | |
238 POLICY_LEVEL_MANDATORY, | |
239 POLICY_SCOPE_USER, | |
240 base::Value::CreateStringValue("value 1"), | |
241 NULL); | |
242 | |
243 // Known components without a schema are not filtered. | |
244 PolicyNamespace without_schema_ns(POLICY_DOMAIN_EXTENSIONS, "without-schema"); | |
245 bundle.Get(without_schema_ns).Set("Schemaless", | |
246 POLICY_LEVEL_MANDATORY, | |
247 POLICY_SCOPE_USER, | |
248 base::Value::CreateStringValue("value 2"), | |
249 NULL); | |
250 | |
251 // The Chrome namespace isn't filtered. | |
252 PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, ""); | |
253 bundle.Get(chrome_ns).Set("ChromePolicy", | |
254 POLICY_LEVEL_MANDATORY, | |
255 POLICY_SCOPE_USER, | |
256 base::Value::CreateStringValue("value 3"), | |
257 NULL); | |
258 | |
259 PolicyBundle expected_bundle; | |
260 expected_bundle.MergeFrom(bundle); | |
261 | |
262 // Unknown policies of known components with a schema are removed. | |
263 bundle.Get(extension_ns).Set("Surprise", | |
264 POLICY_LEVEL_MANDATORY, | |
265 POLICY_SCOPE_USER, | |
266 base::Value::CreateStringValue("value 4"), | |
267 NULL); | |
268 | |
269 // Unknown components are removed. | |
270 PolicyNamespace unknown_ns(POLICY_DOMAIN_EXTENSIONS, "unknown"); | |
271 bundle.Get(unknown_ns).Set("Surprise", | |
272 POLICY_LEVEL_MANDATORY, | |
273 POLICY_SCOPE_USER, | |
274 base::Value::CreateStringValue("value 5"), | |
275 NULL); | |
276 | |
277 schema_map->FilterBundle(&bundle); | |
278 EXPECT_TRUE(bundle.Equals(expected_bundle)); | |
279 } | |
280 | |
281 TEST_F(SchemaMapTest, GetChanges) { | |
282 DomainMap map; | |
283 map[POLICY_DOMAIN_CHROME][""] = Schema(); | |
284 scoped_refptr<SchemaMap> older = new SchemaMap(map); | |
285 map[POLICY_DOMAIN_CHROME][""] = Schema(); | |
286 scoped_refptr<SchemaMap> newer = new SchemaMap(map); | |
287 | |
288 PolicyNamespaceList removed; | |
289 PolicyNamespaceList added; | |
290 newer->GetChanges(older, &removed, &added); | |
291 EXPECT_TRUE(removed.empty()); | |
292 EXPECT_TRUE(added.empty()); | |
293 | |
294 map[POLICY_DOMAIN_CHROME][""] = Schema(); | |
295 map[POLICY_DOMAIN_EXTENSIONS]["xyz"] = Schema(); | |
296 newer = new SchemaMap(map); | |
297 newer->GetChanges(older, &removed, &added); | |
298 EXPECT_TRUE(removed.empty()); | |
299 ASSERT_EQ(1u, added.size()); | |
300 EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), added[0]); | |
301 | |
302 older = newer; | |
303 map[POLICY_DOMAIN_EXTENSIONS]["abc"] = Schema(); | |
304 newer = new SchemaMap(map); | |
305 newer->GetChanges(older, &removed, &added); | |
306 ASSERT_EQ(2u, removed.size()); | |
307 EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), removed[0]); | |
308 EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), removed[1]); | |
309 ASSERT_EQ(1u, added.size()); | |
310 EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"), added[0]); | |
311 } | |
312 | |
313 } // namespace policy | |
OLD | NEW |