Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2012 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 "base/callback.h"
      6 #include "base/json/json_reader.h"
      7 #include "base/prefs/testing_pref_store.h"
      8 #include "base/strings/string_util.h"
      9 #include "chrome/browser/policy/configuration_policy_provider_test.h"
     10 #include "chrome/browser/policy/external_data_fetcher.h"
     11 #include "chrome/browser/policy/managed_mode_policy_provider.h"
     12 #include "chrome/browser/policy/policy_bundle.h"
     13 #include "chrome/browser/policy/policy_map.h"
     14 #include "sync/api/sync_change.h"
     15 #include "sync/api/sync_error_factory_mock.h"
     16 #include "sync/protocol/sync.pb.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace policy {
     20 
     21 namespace {
     22 
     23 class MockChangeProcessor : public syncer::SyncChangeProcessor {
     24  public:
     25   MockChangeProcessor() {}
     26   virtual ~MockChangeProcessor() {}
     27 
     28   // SyncChangeProcessor implementation:
     29   virtual syncer::SyncError ProcessSyncChanges(
     30       const tracked_objects::Location& from_here,
     31       const syncer::SyncChangeList& change_list) OVERRIDE;
     32 
     33   const syncer::SyncChangeList& changes() const { return change_list_; }
     34 
     35  private:
     36   syncer::SyncChangeList change_list_;
     37 
     38   DISALLOW_COPY_AND_ASSIGN(MockChangeProcessor);
     39 };
     40 
     41 syncer::SyncError MockChangeProcessor::ProcessSyncChanges(
     42     const tracked_objects::Location& from_here,
     43     const syncer::SyncChangeList& change_list) {
     44   change_list_ = change_list;
     45   return syncer::SyncError();
     46 }
     47 
     48 class MockSyncErrorFactory : public syncer::SyncErrorFactory {
     49  public:
     50   explicit MockSyncErrorFactory(syncer::ModelType type);
     51   virtual ~MockSyncErrorFactory();
     52 
     53   // SyncErrorFactory implementation:
     54   virtual syncer::SyncError CreateAndUploadError(
     55       const tracked_objects::Location& location,
     56       const std::string& message) OVERRIDE;
     57 
     58  private:
     59   syncer::ModelType type_;
     60 
     61   DISALLOW_COPY_AND_ASSIGN(MockSyncErrorFactory);
     62 };
     63 
     64 MockSyncErrorFactory::MockSyncErrorFactory(syncer::ModelType type)
     65     : type_(type) {}
     66 
     67 MockSyncErrorFactory::~MockSyncErrorFactory() {}
     68 
     69 syncer::SyncError MockSyncErrorFactory::CreateAndUploadError(
     70     const tracked_objects::Location& location,
     71     const std::string& message) {
     72   return syncer::SyncError(location,
     73                            syncer::SyncError::DATATYPE_ERROR,
     74                            message,
     75                            type_);
     76 }
     77 
     78 class TestHarness : public PolicyProviderTestHarness {
     79  public:
     80   TestHarness();
     81   virtual ~TestHarness();
     82 
     83   static PolicyProviderTestHarness* Create();
     84 
     85   // PolicyProviderTestHarness implementation:
     86   virtual void SetUp() OVERRIDE;
     87 
     88   virtual ConfigurationPolicyProvider* CreateProvider(
     89       const PolicyDefinitionList* policy_definition_list) OVERRIDE;
     90 
     91   virtual void InstallEmptyPolicy() OVERRIDE;
     92   virtual void InstallStringPolicy(const std::string& policy_name,
     93                                    const std::string& policy_value) OVERRIDE;
     94   virtual void InstallIntegerPolicy(const std::string& policy_name,
     95                                     int policy_value) OVERRIDE;
     96   virtual void InstallBooleanPolicy(const std::string& policy_name,
     97                                     bool policy_value) OVERRIDE;
     98   virtual void InstallStringListPolicy(
     99       const std::string& policy_name,
    100       const base::ListValue* policy_value) OVERRIDE;
    101   virtual void InstallDictionaryPolicy(
    102       const std::string& policy_name,
    103       const base::DictionaryValue* policy_value) OVERRIDE;
    104 
    105  private:
    106   void InstallSimplePolicy(const std::string& policy_name,
    107                            scoped_ptr<base::Value> policy_value);
    108 
    109   scoped_refptr<TestingPrefStore> pref_store_;
    110 
    111   // Owned by the test fixture.
    112   ManagedModePolicyProvider* provider_;
    113 
    114   DISALLOW_COPY_AND_ASSIGN(TestHarness);
    115 };
    116 
    117 TestHarness::TestHarness()
    118     : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER),
    119       pref_store_(new TestingPrefStore) {
    120   pref_store_->SetInitializationCompleted();
    121 }
    122 
    123 TestHarness::~TestHarness() {}
    124 
    125 // static
    126 PolicyProviderTestHarness* TestHarness::Create() {
    127   return new TestHarness();
    128 }
    129 
    130 void TestHarness::SetUp() {}
    131 
    132 ConfigurationPolicyProvider* TestHarness::CreateProvider(
    133     const PolicyDefinitionList* policy_definition_list) {
    134   provider_ = new ManagedModePolicyProvider(pref_store_.get());
    135   syncer::SyncDataList initial_sync_data;
    136   scoped_ptr<syncer::SyncChangeProcessor> sync_processor(
    137       new MockChangeProcessor());
    138   scoped_ptr<syncer::SyncErrorFactory> error_handler(
    139       new MockSyncErrorFactory(syncer::MANAGED_USER_SETTINGS));
    140   syncer::SyncMergeResult result =
    141       provider_->MergeDataAndStartSyncing(syncer::MANAGED_USER_SETTINGS,
    142                                           initial_sync_data,
    143                                           sync_processor.Pass(),
    144                                           error_handler.Pass());
    145   EXPECT_FALSE(result.error().IsSet());
    146   return provider_;
    147 }
    148 
    149 void TestHarness::InstallSimplePolicy(const std::string& policy_name,
    150                                       scoped_ptr<base::Value> policy_value) {
    151   syncer::SyncData data = ManagedModePolicyProvider::CreateSyncDataForPolicy(
    152       policy_name, policy_value.get());
    153   syncer::SyncChangeList change_list;
    154   change_list.push_back(
    155       syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data));
    156   syncer::SyncError error =
    157       provider_->ProcessSyncChanges(FROM_HERE, change_list);
    158   EXPECT_FALSE(error.IsSet()) << error.ToString();
    159 }
    160 
    161 void TestHarness::InstallEmptyPolicy() {}
    162 
    163 void TestHarness::InstallStringPolicy(const std::string& policy_name,
    164                                       const std::string& policy_value) {
    165   InstallSimplePolicy(
    166       policy_name,
    167       scoped_ptr<base::Value>(base::Value::CreateStringValue(policy_value)));
    168 }
    169 
    170 void TestHarness::InstallIntegerPolicy(const std::string& policy_name,
    171                                        int policy_value) {
    172   InstallSimplePolicy(
    173       policy_name,
    174       scoped_ptr<base::Value>(new base::FundamentalValue(policy_value)));
    175 }
    176 
    177 void TestHarness::InstallBooleanPolicy(const std::string& policy_name,
    178                                        bool policy_value) {
    179   InstallSimplePolicy(
    180       policy_name,
    181       scoped_ptr<base::Value>(new base::FundamentalValue(policy_value)));
    182 }
    183 
    184 void TestHarness::InstallStringListPolicy(const std::string& policy_name,
    185                                           const base::ListValue* policy_value) {
    186   InstallSimplePolicy(policy_name,
    187                       scoped_ptr<base::Value>(policy_value->DeepCopy()));
    188 }
    189 
    190 void TestHarness::InstallDictionaryPolicy(
    191     const std::string& policy_name,
    192     const base::DictionaryValue* policy_value) {
    193   syncer::SyncChangeList change_list;
    194   for (base::DictionaryValue::Iterator it(*policy_value); !it.IsAtEnd();
    195        it.Advance()) {
    196     syncer::SyncData data = ManagedModePolicyProvider::CreateSyncDataForPolicy(
    197         ManagedModePolicyProvider::MakeSplitSettingKey(policy_name, it.key()),
    198         &it.value());
    199     change_list.push_back(
    200         syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, data));
    201   }
    202   syncer::SyncError error =
    203       provider_->ProcessSyncChanges(FROM_HERE, change_list);
    204   EXPECT_FALSE(error.IsSet()) << error.ToString();
    205 }
    206 
    207 }  // namespace
    208 
    209 // Instantiate abstract test case for basic policy reading tests.
    210 INSTANTIATE_TEST_CASE_P(
    211     ManagedModePolicyProviderTest,
    212     ConfigurationPolicyProviderTest,
    213     testing::Values(TestHarness::Create));
    214 
    215 const char kAtomicItemName[] = "X-Wombat";
    216 const char kSplitItemName[] = "X-SuperMoosePowers";
    217 
    218 class ManagedModePolicyProviderAPITest : public PolicyTestBase {
    219  protected:
    220   ManagedModePolicyProviderAPITest()
    221       : pref_store_(new TestingPrefStore), provider_(pref_store_.get()) {
    222     pref_store_->SetInitializationCompleted();
    223   }
    224   virtual ~ManagedModePolicyProviderAPITest() {}
    225 
    226   scoped_ptr<syncer::SyncChangeProcessor> CreateSyncProcessor() {
    227     sync_processor_ = new MockChangeProcessor();
    228     return scoped_ptr<syncer::SyncChangeProcessor>(sync_processor_);
    229   }
    230 
    231   void StartSyncing(const syncer::SyncDataList& initial_sync_data) {
    232     scoped_ptr<syncer::SyncErrorFactory> error_handler(
    233         new MockSyncErrorFactory(syncer::MANAGED_USER_SETTINGS));
    234     syncer::SyncMergeResult result =
    235         provider_.MergeDataAndStartSyncing(syncer::MANAGED_USER_SETTINGS,
    236                                            initial_sync_data,
    237                                            CreateSyncProcessor(),
    238                                            error_handler.Pass());
    239     EXPECT_FALSE(result.error().IsSet());
    240   }
    241 
    242   void UploadSplitItem(const std::string& key, const std::string& value) {
    243     dict_.SetStringWithoutPathExpansion(key, value);
    244     provider_.UploadItem(
    245         ManagedModePolicyProvider::MakeSplitSettingKey(kSplitItemName, key),
    246         scoped_ptr<base::Value>(base::Value::CreateStringValue(value)));
    247   }
    248 
    249   void UploadAtomicItem(const std::string& value) {
    250     atomic_setting_value_.reset(new base::StringValue(value));
    251     provider_.UploadItem(
    252         kAtomicItemName,
    253         scoped_ptr<base::Value>(base::Value::CreateStringValue(value)));
    254   }
    255 
    256   void VerifySyncDataItem(syncer::SyncData sync_data) {
    257     const sync_pb::ManagedUserSettingSpecifics& managed_user_setting =
    258         sync_data.GetSpecifics().managed_user_setting();
    259     base::Value* expected_value = NULL;
    260     if (managed_user_setting.name() == kAtomicItemName) {
    261       expected_value = atomic_setting_value_.get();
    262     } else {
    263       EXPECT_TRUE(StartsWithASCII(managed_user_setting.name(),
    264                                   std::string(kSplitItemName) + ':',
    265                                   true));
    266       std::string key =
    267           managed_user_setting.name().substr(strlen(kSplitItemName) + 1);
    268       EXPECT_TRUE(dict_.GetWithoutPathExpansion(key, &expected_value));
    269     }
    270 
    271     scoped_ptr<Value> value(
    272         base::JSONReader::Read(managed_user_setting.value()));
    273     EXPECT_TRUE(expected_value->Equals(value.get()));
    274   }
    275 
    276   // PolicyTestBase overrides:
    277   virtual void TearDown() OVERRIDE {
    278     provider_.Shutdown();
    279     PolicyTestBase::TearDown();
    280   }
    281 
    282   base::DictionaryValue dict_;
    283   scoped_ptr<base::Value> atomic_setting_value_;
    284   scoped_refptr<TestingPrefStore> pref_store_;
    285   ManagedModePolicyProvider provider_;
    286 
    287   // Owned by the ManagedModePolicyProvider.
    288   MockChangeProcessor* sync_processor_;
    289 };
    290 
    291 TEST_F(ManagedModePolicyProviderAPITest, UploadItem) {
    292   UploadSplitItem("foo", "bar");
    293   UploadSplitItem("blurp", "baz");
    294   UploadAtomicItem("hurdle");
    295 
    296   // Uploading should produce changes when we start syncing.
    297   StartSyncing(syncer::SyncDataList());
    298   const syncer::SyncChangeList& changes = sync_processor_->changes();
    299   ASSERT_EQ(3u, changes.size());
    300   for (syncer::SyncChangeList::const_iterator it = changes.begin();
    301        it != changes.end(); ++it) {
    302     ASSERT_TRUE(it->IsValid());
    303     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, it->change_type());
    304     VerifySyncDataItem(it->sync_data());
    305   }
    306 
    307   // It should also show up in local Sync data.
    308   syncer::SyncDataList sync_data =
    309       provider_.GetAllSyncData(syncer::MANAGED_USER_SETTINGS);
    310   EXPECT_EQ(3u, sync_data.size());
    311   for (syncer::SyncDataList::const_iterator it = sync_data.begin();
    312        it != sync_data.end(); ++it) {
    313     VerifySyncDataItem(*it);
    314   }
    315 
    316   // Uploading after we have started syncing should work too.
    317   UploadSplitItem("froodle", "narf");
    318   ASSERT_EQ(1u, sync_processor_->changes().size());
    319   syncer::SyncChange change = sync_processor_->changes()[0];
    320   ASSERT_TRUE(change.IsValid());
    321   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, change.change_type());
    322   VerifySyncDataItem(change.sync_data());
    323 
    324   sync_data = provider_.GetAllSyncData(syncer::MANAGED_USER_SETTINGS);
    325   EXPECT_EQ(4u, sync_data.size());
    326   for (syncer::SyncDataList::const_iterator it = sync_data.begin();
    327        it != sync_data.end(); ++it) {
    328     VerifySyncDataItem(*it);
    329   }
    330 
    331   // Uploading an item with a previously seen key should create an UPDATE
    332   // action.
    333   UploadSplitItem("blurp", "snarl");
    334   ASSERT_EQ(1u, sync_processor_->changes().size());
    335   change = sync_processor_->changes()[0];
    336   ASSERT_TRUE(change.IsValid());
    337   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
    338   VerifySyncDataItem(change.sync_data());
    339 
    340   sync_data = provider_.GetAllSyncData(syncer::MANAGED_USER_SETTINGS);
    341   EXPECT_EQ(4u, sync_data.size());
    342   for (syncer::SyncDataList::const_iterator it = sync_data.begin();
    343        it != sync_data.end(); ++it) {
    344     VerifySyncDataItem(*it);
    345   }
    346 
    347   UploadAtomicItem("fjord");
    348   ASSERT_EQ(1u, sync_processor_->changes().size());
    349   change = sync_processor_->changes()[0];
    350   ASSERT_TRUE(change.IsValid());
    351   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
    352   VerifySyncDataItem(change.sync_data());
    353 
    354   sync_data = provider_.GetAllSyncData(syncer::MANAGED_USER_SETTINGS);
    355   EXPECT_EQ(4u, sync_data.size());
    356   for (syncer::SyncDataList::const_iterator it = sync_data.begin();
    357        it != sync_data.end(); ++it) {
    358     VerifySyncDataItem(*it);
    359   }
    360 
    361   // The uploaded items should not show up as policies.
    362   PolicyBundle empty_bundle;
    363   EXPECT_TRUE(provider_.policies().Equals(empty_bundle));
    364 
    365   // Restarting sync should not create any new changes.
    366   provider_.StopSyncing(syncer::MANAGED_USER_SETTINGS);
    367   StartSyncing(sync_data);
    368   ASSERT_EQ(0u, sync_processor_->changes().size());
    369 }
    370 
    371 const char kPolicyKey[] = "TestingPolicy";
    372 
    373 TEST_F(ManagedModePolicyProviderAPITest, SetLocalPolicy) {
    374   PolicyBundle empty_bundle;
    375   EXPECT_TRUE(provider_.policies().Equals(empty_bundle));
    376 
    377   base::StringValue policy_value("PolicyValue");
    378   provider_.SetLocalPolicyForTesting(
    379       kPolicyKey, scoped_ptr<base::Value>(policy_value.DeepCopy()));
    380 
    381   PolicyBundle expected_bundle;
    382   PolicyMap* policy_map = &expected_bundle.Get(
    383       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
    384   policy_map->Set(kPolicyKey,
    385                   POLICY_LEVEL_MANDATORY,
    386                   POLICY_SCOPE_USER,
    387                   policy_value.DeepCopy(),
    388                   NULL);
    389   EXPECT_TRUE(provider_.policies().Equals(expected_bundle));
    390 }
    391 
    392 }  // namespace policy
    393