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 <string> 6 7#include "base/json/json_string_value_serializer.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/time/time.h" 10#include "base/values.h" 11#include "chrome/browser/prefs/synced_pref_change_registrar.h" 12#include "chrome/browser/ui/browser.h" 13#include "chrome/common/pref_names.h" 14#include "chrome/test/base/in_process_browser_test.h" 15#include "chrome/test/base/testing_pref_service_syncable.h" 16#include "chrome/test/base/testing_profile.h" 17#include "content/public/test/test_utils.h" 18#include "sync/api/attachments/attachment_id.h" 19#include "sync/api/fake_sync_change_processor.h" 20#include "sync/api/sync_change.h" 21#include "sync/api/sync_error_factory.h" 22#include "sync/api/sync_error_factory_mock.h" 23#include "sync/api/syncable_service.h" 24#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" 25#include "sync/protocol/sync.pb.h" 26 27#if defined(ENABLE_CONFIGURATION_POLICY) 28#include "components/policy/core/browser/browser_policy_connector.h" 29#include "components/policy/core/common/mock_configuration_policy_provider.h" 30#include "components/policy/core/common/policy_map.h" 31#include "policy/policy_constants.h" 32#endif 33 34namespace { 35 36using testing::Return; 37using testing::_; 38 39class SyncedPrefChangeRegistrarTest : public InProcessBrowserTest { 40 public: 41 SyncedPrefChangeRegistrarTest() : next_sync_data_id_(0) {} 42 virtual ~SyncedPrefChangeRegistrarTest() {} 43 44#if defined(ENABLE_CONFIGURATION_POLICY) 45 void UpdateChromePolicy(const policy::PolicyMap& policies) { 46 policy_provider_.UpdateChromePolicy(policies); 47 DCHECK(base::MessageLoop::current()); 48 base::RunLoop loop; 49 loop.RunUntilIdle(); 50 } 51#endif 52 53 void SetBooleanPrefValueFromSync(const std::string& name, bool value) { 54 std::string serialized_value; 55 JSONStringValueSerializer json(&serialized_value); 56 json.Serialize(base::FundamentalValue(value)); 57 58 sync_pb::EntitySpecifics specifics; 59 sync_pb::PreferenceSpecifics* pref_specifics = 60 specifics.mutable_preference(); 61 pref_specifics->set_name(name); 62 pref_specifics->set_value(serialized_value); 63 64 syncer::SyncData change_data = syncer::SyncData::CreateRemoteData( 65 ++next_sync_data_id_, 66 specifics, 67 base::Time(), 68 syncer::AttachmentIdList(), 69 syncer::AttachmentServiceProxyForTest::Create()); 70 syncer::SyncChange change( 71 FROM_HERE, syncer::SyncChange::ACTION_UPDATE, change_data); 72 73 syncer::SyncChangeList change_list; 74 change_list.push_back(change); 75 76 syncer_->ProcessSyncChanges(FROM_HERE, change_list); 77 } 78 79 void SetBooleanPrefValueFromLocal(const std::string& name, bool value) { 80 prefs_->SetBoolean(name.c_str(), value); 81 } 82 83 bool GetBooleanPrefValue(const std::string& name) { 84 return prefs_->GetBoolean(name.c_str()); 85 } 86 87 PrefServiceSyncable* prefs() const { 88 return prefs_; 89 } 90 91 SyncedPrefChangeRegistrar* registrar() const { 92 return registrar_.get(); 93 } 94 95 private: 96#if defined(ENABLE_CONFIGURATION_POLICY) 97 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 98 EXPECT_CALL(policy_provider_, IsInitializationComplete(_)) 99 .WillRepeatedly(Return(true)); 100 policy::BrowserPolicyConnector::SetPolicyProviderForTesting( 101 &policy_provider_); 102 } 103#endif 104 105 virtual void SetUpOnMainThread() OVERRIDE { 106 prefs_ = PrefServiceSyncable::FromProfile(browser()->profile()); 107 syncer_ = prefs_->GetSyncableService(syncer::PREFERENCES); 108 syncer_->MergeDataAndStartSyncing( 109 syncer::PREFERENCES, 110 syncer::SyncDataList(), 111 scoped_ptr<syncer::SyncChangeProcessor>( 112 new syncer::FakeSyncChangeProcessor), 113 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock)); 114 registrar_.reset(new SyncedPrefChangeRegistrar(prefs_)); 115 } 116 117 virtual void TearDownOnMainThread() OVERRIDE { 118 registrar_.reset(); 119 } 120 121 PrefServiceSyncable* prefs_; 122 syncer::SyncableService* syncer_; 123 int next_sync_data_id_; 124 125 scoped_ptr<SyncedPrefChangeRegistrar> registrar_; 126#if defined(ENABLE_CONFIGURATION_POLICY) 127 policy::MockConfigurationPolicyProvider policy_provider_; 128#endif 129}; 130 131struct TestSyncedPrefObserver { 132 bool last_seen_value; 133 bool last_update_is_from_sync; 134 bool has_been_notified; 135}; 136 137void TestPrefChangeCallback(PrefService* prefs, 138 TestSyncedPrefObserver* observer, 139 const std::string& path, 140 bool from_sync) { 141 observer->last_seen_value = prefs->GetBoolean(path.c_str()); 142 observer->last_update_is_from_sync = from_sync; 143 observer->has_been_notified = true; 144} 145 146} // namespace 147 148IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest, 149 DifferentiateRemoteAndLocalChanges) { 150 TestSyncedPrefObserver observer = {}; 151 registrar()->Add(prefs::kShowHomeButton, 152 base::Bind(&TestPrefChangeCallback, prefs(), &observer)); 153 154 EXPECT_FALSE(observer.has_been_notified); 155 156 SetBooleanPrefValueFromSync(prefs::kShowHomeButton, true); 157 EXPECT_TRUE(observer.has_been_notified); 158 EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton)); 159 EXPECT_TRUE(observer.last_update_is_from_sync); 160 EXPECT_TRUE(observer.last_seen_value); 161 162 observer.has_been_notified = false; 163 SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false); 164 EXPECT_TRUE(observer.has_been_notified); 165 EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton)); 166 EXPECT_FALSE(observer.last_update_is_from_sync); 167 EXPECT_FALSE(observer.last_seen_value); 168 169 observer.has_been_notified = false; 170 SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, true); 171 EXPECT_TRUE(observer.has_been_notified); 172 EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton)); 173 EXPECT_FALSE(observer.last_update_is_from_sync); 174 EXPECT_TRUE(observer.last_seen_value); 175 176 observer.has_been_notified = false; 177 SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false); 178 EXPECT_TRUE(observer.has_been_notified); 179 EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton)); 180 EXPECT_TRUE(observer.last_update_is_from_sync); 181 EXPECT_FALSE(observer.last_seen_value); 182} 183 184#if defined(ENABLE_CONFIGURATION_POLICY) 185IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest, 186 IgnoreLocalChangesToManagedPrefs) { 187 TestSyncedPrefObserver observer = {}; 188 registrar()->Add(prefs::kShowHomeButton, 189 base::Bind(&TestPrefChangeCallback, prefs(), &observer)); 190 191 policy::PolicyMap policies; 192 policies.Set(policy::key::kShowHomeButton, 193 policy::POLICY_LEVEL_MANDATORY, 194 policy::POLICY_SCOPE_USER, 195 new base::FundamentalValue(true), 196 NULL); 197 UpdateChromePolicy(policies); 198 199 EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton)); 200 201 SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false); 202 EXPECT_FALSE(observer.has_been_notified); 203 EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton)); 204} 205 206IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest, 207 IgnoreSyncChangesToManagedPrefs) { 208 TestSyncedPrefObserver observer = {}; 209 registrar()->Add(prefs::kShowHomeButton, 210 base::Bind(&TestPrefChangeCallback, prefs(), &observer)); 211 212 policy::PolicyMap policies; 213 policies.Set(policy::key::kShowHomeButton, 214 policy::POLICY_LEVEL_MANDATORY, 215 policy::POLICY_SCOPE_USER, 216 new base::FundamentalValue(true), 217 NULL); 218 UpdateChromePolicy(policies); 219 220 EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton)); 221 SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false); 222 EXPECT_FALSE(observer.has_been_notified); 223 EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton)); 224} 225#endif 226