Home | History | Annotate | Download | only in common
      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 
    124 PolicyTestBase::PolicyTestBase() {}
    125 
    126 PolicyTestBase::~PolicyTestBase() {}
    127 
    128 void PolicyTestBase::SetUp() {
    129   const PolicyNamespace ns(POLICY_DOMAIN_CHROME, "");
    130   ASSERT_TRUE(RegisterSchema(ns, kTestChromeSchema));
    131 }
    132 
    133 void PolicyTestBase::TearDown() {
    134   loop_.RunUntilIdle();
    135 }
    136 
    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 
    149 PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level,
    150                                                      PolicyScope scope)
    151     : level_(level), scope_(scope) {}
    152 
    153 PolicyProviderTestHarness::~PolicyProviderTestHarness() {}
    154 
    155 PolicyLevel PolicyProviderTestHarness::policy_level() const {
    156   return level_;
    157 }
    158 
    159 PolicyScope PolicyProviderTestHarness::policy_scope() const {
    160   return scope_;
    161 }
    162 
    163 void PolicyProviderTestHarness::Install3rdPartyPolicy(
    164     const base::DictionaryValue* policies) {
    165   FAIL();
    166 }
    167 
    168 ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
    169 
    170 ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
    171 
    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 
    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 
    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 
    235 TEST_P(ConfigurationPolicyProviderTest, Empty) {
    236   provider_->RefreshPolicies();
    237   loop_.RunUntilIdle();
    238   const PolicyBundle kEmptyBundle;
    239   EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
    240 }
    241 
    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 
    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 
    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 
    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 
    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 
    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::
    351     Configuration3rdPartyPolicyProviderTest() {}
    352 
    353 Configuration3rdPartyPolicyProviderTest::
    354     ~Configuration3rdPartyPolicyProviderTest() {}
    355 
    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