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