• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/configuration_policy_provider_test.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/values.h"
11 #include "components/policy/core/common/configuration_policy_provider.h"
12 #include "components/policy/core/common/external_data_fetcher.h"
13 #include "components/policy/core/common/mock_configuration_policy_provider.h"
14 #include "components/policy/core/common/policy_bundle.h"
15 #include "components/policy/core/common/policy_map.h"
16 #include "components/policy/core/common/policy_namespace.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 
19 using ::testing::Mock;
20 using ::testing::_;
21 
22 namespace policy {
23 
24 const char kTestChromeSchema[] =
25     "{"
26     "  \"type\": \"object\","
27     "  \"properties\": {"
28     "    \"StringPolicy\": { \"type\": \"string\" },"
29     "    \"BooleanPolicy\": { \"type\": \"boolean\" },"
30     "    \"IntegerPolicy\": { \"type\": \"integer\" },"
31     "    \"StringListPolicy\": {"
32     "      \"type\": \"array\","
33     "      \"items\": { \"type\": \"string\" }"
34     "    },"
35     "    \"DictionaryPolicy\": {"
36     "      \"type\": \"object\","
37     "      \"properties\": {"
38     "        \"bool\": { \"type\": \"boolean\" },"
39     "        \"double\": { \"type\": \"number\" },"
40     "        \"int\": { \"type\": \"integer\" },"
41     "        \"string\": { \"type\": \"string\" },"
42     "        \"array\": {"
43     "          \"type\": \"array\","
44     "          \"items\": { \"type\": \"string\" }"
45     "        },"
46     "        \"dictionary\": {"
47     "          \"type\": \"object\","
48     "          \"properties\": {"
49     "            \"sub\": { \"type\": \"string\" },"
50     "            \"sublist\": {"
51     "              \"type\": \"array\","
52     "              \"items\": {"
53     "                \"type\": \"object\","
54     "                \"properties\": {"
55     "                  \"aaa\": { \"type\": \"integer\" },"
56     "                  \"bbb\": { \"type\": \"integer\" },"
57     "                  \"ccc\": { \"type\": \"string\" },"
58     "                  \"ddd\": { \"type\": \"string\" }"
59     "                }"
60     "              }"
61     "            }"
62     "          }"
63     "        },"
64     "        \"list\": {"
65     "          \"type\": \"array\","
66     "          \"items\": {"
67     "            \"type\": \"object\","
68     "            \"properties\": {"
69     "              \"subdictindex\": { \"type\": \"integer\" },"
70     "              \"subdict\": {"
71     "                \"type\": \"object\","
72     "                \"properties\": {"
73     "                  \"bool\": { \"type\": \"boolean\" },"
74     "                  \"double\": { \"type\": \"number\" },"
75     "                  \"int\": { \"type\": \"integer\" },"
76     "                  \"string\": { \"type\": \"string\" }"
77     "                }"
78     "              }"
79     "            }"
80     "          }"
81     "        },"
82     "        \"dict\": {"
83     "          \"type\": \"object\","
84     "          \"properties\": {"
85     "            \"bool\": { \"type\": \"boolean\" },"
86     "            \"double\": { \"type\": \"number\" },"
87     "            \"int\": { \"type\": \"integer\" },"
88     "            \"string\": { \"type\": \"string\" },"
89     "            \"list\": {"
90     "              \"type\": \"array\","
91     "              \"items\": {"
92     "                \"type\": \"object\","
93     "                \"properties\": {"
94     "                  \"subdictindex\": { \"type\": \"integer\" },"
95     "                  \"subdict\": {"
96     "                    \"type\": \"object\","
97     "                    \"properties\": {"
98     "                      \"bool\": { \"type\": \"boolean\" },"
99     "                      \"double\": { \"type\": \"number\" },"
100     "                      \"int\": { \"type\": \"integer\" },"
101     "                      \"string\": { \"type\": \"string\" }"
102     "                    }"
103     "                  }"
104     "                }"
105     "              }"
106     "            }"
107     "          }"
108     "        }"
109     "      }"
110     "    }"
111     "  }"
112     "}";
113 
114 namespace test_keys {
115 
116 const char kKeyString[] = "StringPolicy";
117 const char kKeyBoolean[] = "BooleanPolicy";
118 const char kKeyInteger[] = "IntegerPolicy";
119 const char kKeyStringList[] = "StringListPolicy";
120 const char kKeyDictionary[] = "DictionaryPolicy";
121 
122 }  // namespace test_keys
123 
PolicyTestBase()124 PolicyTestBase::PolicyTestBase() {}
125 
~PolicyTestBase()126 PolicyTestBase::~PolicyTestBase() {}
127 
SetUp()128 void PolicyTestBase::SetUp() {
129   const PolicyNamespace ns(POLICY_DOMAIN_CHROME, "");
130   ASSERT_TRUE(RegisterSchema(ns, kTestChromeSchema));
131 }
132 
TearDown()133 void PolicyTestBase::TearDown() {
134   loop_.RunUntilIdle();
135 }
136 
RegisterSchema(const PolicyNamespace & ns,const std::string & schema_string)137 bool PolicyTestBase::RegisterSchema(const PolicyNamespace& ns,
138                                     const std::string& schema_string) {
139   std::string error;
140   Schema schema = Schema::Parse(schema_string, &error);
141   if (schema.valid()) {
142     schema_registry_.RegisterComponent(ns, schema);
143     return true;
144   }
145   ADD_FAILURE() << error;
146   return false;
147 }
148 
PolicyProviderTestHarness(PolicyLevel level,PolicyScope scope)149 PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level,
150                                                      PolicyScope scope)
151     : level_(level), scope_(scope) {}
152 
~PolicyProviderTestHarness()153 PolicyProviderTestHarness::~PolicyProviderTestHarness() {}
154 
policy_level() const155 PolicyLevel PolicyProviderTestHarness::policy_level() const {
156   return level_;
157 }
158 
policy_scope() const159 PolicyScope PolicyProviderTestHarness::policy_scope() const {
160   return scope_;
161 }
162 
Install3rdPartyPolicy(const base::DictionaryValue * policies)163 void PolicyProviderTestHarness::Install3rdPartyPolicy(
164     const base::DictionaryValue* policies) {
165   FAIL();
166 }
167 
ConfigurationPolicyProviderTest()168 ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
169 
~ConfigurationPolicyProviderTest()170 ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
171 
SetUp()172 void ConfigurationPolicyProviderTest::SetUp() {
173   PolicyTestBase::SetUp();
174 
175   test_harness_.reset((*GetParam())());
176   test_harness_->SetUp();
177 
178   const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
179   Schema chrome_schema = *schema_registry_.schema_map()->GetSchema(chrome_ns);
180   Schema extension_schema =
181       chrome_schema.GetKnownProperty(test_keys::kKeyDictionary);
182   ASSERT_TRUE(extension_schema.valid());
183   schema_registry_.RegisterComponent(
184       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
185                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
186       extension_schema);
187   schema_registry_.RegisterComponent(
188       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
189                       "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
190       extension_schema);
191   schema_registry_.RegisterComponent(
192       PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
193                       "cccccccccccccccccccccccccccccccc"),
194       extension_schema);
195 
196   provider_.reset(test_harness_->CreateProvider(&schema_registry_,
197                                                 loop_.message_loop_proxy()));
198   provider_->Init(&schema_registry_);
199   // Some providers do a reload on init. Make sure any notifications generated
200   // are fired now.
201   loop_.RunUntilIdle();
202 
203   const PolicyBundle kEmptyBundle;
204   EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
205 }
206 
TearDown()207 void ConfigurationPolicyProviderTest::TearDown() {
208   // Give providers the chance to clean up after themselves on the file thread.
209   provider_->Shutdown();
210   provider_.reset();
211 
212   PolicyTestBase::TearDown();
213 }
214 
CheckValue(const char * policy_name,const base::Value & expected_value,base::Closure install_value)215 void ConfigurationPolicyProviderTest::CheckValue(
216     const char* policy_name,
217     const base::Value& expected_value,
218     base::Closure install_value) {
219   // Install the value, reload policy and check the provider for the value.
220   install_value.Run();
221   provider_->RefreshPolicies();
222   loop_.RunUntilIdle();
223   PolicyBundle expected_bundle;
224   expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
225       .Set(policy_name,
226            test_harness_->policy_level(),
227            test_harness_->policy_scope(),
228            expected_value.DeepCopy(),
229            NULL);
230   EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
231   // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too,
232   // and extend the |expected_bundle|, once all providers are ready.
233 }
234 
TEST_P(ConfigurationPolicyProviderTest,Empty)235 TEST_P(ConfigurationPolicyProviderTest, Empty) {
236   provider_->RefreshPolicies();
237   loop_.RunUntilIdle();
238   const PolicyBundle kEmptyBundle;
239   EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
240 }
241 
TEST_P(ConfigurationPolicyProviderTest,StringValue)242 TEST_P(ConfigurationPolicyProviderTest, StringValue) {
243   const char kTestString[] = "string_value";
244   base::StringValue expected_value(kTestString);
245   CheckValue(test_keys::kKeyString,
246              expected_value,
247              base::Bind(&PolicyProviderTestHarness::InstallStringPolicy,
248                         base::Unretained(test_harness_.get()),
249                         test_keys::kKeyString,
250                         kTestString));
251 }
252 
TEST_P(ConfigurationPolicyProviderTest,BooleanValue)253 TEST_P(ConfigurationPolicyProviderTest, BooleanValue) {
254   base::FundamentalValue expected_value(true);
255   CheckValue(test_keys::kKeyBoolean,
256              expected_value,
257              base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy,
258                         base::Unretained(test_harness_.get()),
259                         test_keys::kKeyBoolean,
260                         true));
261 }
262 
TEST_P(ConfigurationPolicyProviderTest,IntegerValue)263 TEST_P(ConfigurationPolicyProviderTest, IntegerValue) {
264   base::FundamentalValue expected_value(42);
265   CheckValue(test_keys::kKeyInteger,
266              expected_value,
267              base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy,
268                         base::Unretained(test_harness_.get()),
269                         test_keys::kKeyInteger,
270                         42));
271 }
272 
TEST_P(ConfigurationPolicyProviderTest,StringListValue)273 TEST_P(ConfigurationPolicyProviderTest, StringListValue) {
274   base::ListValue expected_value;
275   expected_value.Set(0U, new base::StringValue("first"));
276   expected_value.Set(1U, new base::StringValue("second"));
277   CheckValue(test_keys::kKeyStringList,
278              expected_value,
279              base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy,
280                         base::Unretained(test_harness_.get()),
281                         test_keys::kKeyStringList,
282                         &expected_value));
283 }
284 
TEST_P(ConfigurationPolicyProviderTest,DictionaryValue)285 TEST_P(ConfigurationPolicyProviderTest, DictionaryValue) {
286   base::DictionaryValue expected_value;
287   expected_value.SetBoolean("bool", true);
288   expected_value.SetDouble("double", 123.456);
289   expected_value.SetInteger("int", 123);
290   expected_value.SetString("string", "omg");
291 
292   base::ListValue* list = new base::ListValue();
293   list->Set(0U, new base::StringValue("first"));
294   list->Set(1U, new base::StringValue("second"));
295   expected_value.Set("array", list);
296 
297   base::DictionaryValue* dict = new base::DictionaryValue();
298   dict->SetString("sub", "value");
299   list = new base::ListValue();
300   base::DictionaryValue* sub = new base::DictionaryValue();
301   sub->SetInteger("aaa", 111);
302   sub->SetInteger("bbb", 222);
303   list->Append(sub);
304   sub = new base::DictionaryValue();
305   sub->SetString("ccc", "333");
306   sub->SetString("ddd", "444");
307   list->Append(sub);
308   dict->Set("sublist", list);
309   expected_value.Set("dictionary", dict);
310 
311   CheckValue(test_keys::kKeyDictionary,
312              expected_value,
313              base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy,
314                         base::Unretained(test_harness_.get()),
315                         test_keys::kKeyDictionary,
316                         &expected_value));
317 }
318 
TEST_P(ConfigurationPolicyProviderTest,RefreshPolicies)319 TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) {
320   PolicyBundle bundle;
321   EXPECT_TRUE(provider_->policies().Equals(bundle));
322 
323   // OnUpdatePolicy is called even when there are no changes.
324   MockConfigurationPolicyObserver observer;
325   provider_->AddObserver(&observer);
326   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
327   provider_->RefreshPolicies();
328   loop_.RunUntilIdle();
329   Mock::VerifyAndClearExpectations(&observer);
330 
331   EXPECT_TRUE(provider_->policies().Equals(bundle));
332 
333   // OnUpdatePolicy is called when there are changes.
334   test_harness_->InstallStringPolicy(test_keys::kKeyString, "value");
335   EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
336   provider_->RefreshPolicies();
337   loop_.RunUntilIdle();
338   Mock::VerifyAndClearExpectations(&observer);
339 
340   bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
341       .Set(test_keys::kKeyString,
342            test_harness_->policy_level(),
343            test_harness_->policy_scope(),
344            new base::StringValue("value"),
345            NULL);
346   EXPECT_TRUE(provider_->policies().Equals(bundle));
347   provider_->RemoveObserver(&observer);
348 }
349 
350 Configuration3rdPartyPolicyProviderTest::
Configuration3rdPartyPolicyProviderTest()351     Configuration3rdPartyPolicyProviderTest() {}
352 
353 Configuration3rdPartyPolicyProviderTest::
~Configuration3rdPartyPolicyProviderTest()354     ~Configuration3rdPartyPolicyProviderTest() {}
355 
TEST_P(Configuration3rdPartyPolicyProviderTest,Load3rdParty)356 TEST_P(Configuration3rdPartyPolicyProviderTest, Load3rdParty) {
357   base::DictionaryValue policy_dict;
358   policy_dict.SetBoolean("bool", true);
359   policy_dict.SetDouble("double", 123.456);
360   policy_dict.SetInteger("int", 789);
361   policy_dict.SetString("string", "string value");
362 
363   base::ListValue* list = new base::ListValue();
364   for (int i = 0; i < 2; ++i) {
365     base::DictionaryValue* dict = new base::DictionaryValue();
366     dict->SetInteger("subdictindex", i);
367     dict->Set("subdict", policy_dict.DeepCopy());
368     list->Append(dict);
369   }
370   policy_dict.Set("list", list);
371   policy_dict.Set("dict", policy_dict.DeepCopy());
372 
373   // Install these policies as a Chrome policy.
374   test_harness_->InstallDictionaryPolicy(test_keys::kKeyDictionary,
375                                          &policy_dict);
376   // Install them as 3rd party policies too.
377   base::DictionaryValue policy_3rdparty;
378   policy_3rdparty.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
379                       policy_dict.DeepCopy());
380   policy_3rdparty.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
381                       policy_dict.DeepCopy());
382   // Install invalid 3rd party policies that shouldn't be loaded. These also
383   // help detecting memory leaks in the code paths that detect invalid input.
384   policy_3rdparty.Set("invalid-domain.component", policy_dict.DeepCopy());
385   policy_3rdparty.Set("extensions.cccccccccccccccccccccccccccccccc",
386                       new base::StringValue("invalid-value"));
387   test_harness_->Install3rdPartyPolicy(&policy_3rdparty);
388 
389   provider_->RefreshPolicies();
390   loop_.RunUntilIdle();
391 
392   PolicyMap expected_policy;
393   expected_policy.Set(test_keys::kKeyDictionary,
394                       test_harness_->policy_level(),
395                       test_harness_->policy_scope(),
396                       policy_dict.DeepCopy(),
397                       NULL);
398   PolicyBundle expected_bundle;
399   expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
400       .CopyFrom(expected_policy);
401   expected_policy.Clear();
402   expected_policy.LoadFrom(&policy_dict,
403                            test_harness_->policy_level(),
404                            test_harness_->policy_scope());
405   expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
406                                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
407       .CopyFrom(expected_policy);
408   expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
409                                       "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
410       .CopyFrom(expected_policy);
411   EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
412 }
413 
414 }  // namespace policy
415