1 // Copyright 2014 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.
10 #include "base/callback.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
19 #include "chrome/browser/supervised_user/supervised_user_site_list.h"
20 #include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "sync/api/sync_change.h"
26 #include "sync/api/sync_error_factory.h"
27 #include "sync/protocol/sync.pb.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 #if !defined(OS_ANDROID)
31 #include "components/safe_json/testing_json_parser.h"
36 const char kClientId
[] = "client-id";
38 class MockSupervisedUserWhitelistInstaller
39 : public component_updater::SupervisedUserWhitelistInstaller
{
41 MockSupervisedUserWhitelistInstaller() {}
42 ~MockSupervisedUserWhitelistInstaller() override
{}
44 const std::set
<std::string
>& registered_whitelists() {
45 return registered_whitelists_
;
48 void NotifyWhitelistReady(const std::string
& crx_id
,
49 const base::FilePath
& path
) {
50 for (const auto& callback
: ready_callbacks_
)
51 callback
.Run(crx_id
, path
);
54 // SupervisedUserWhitelistInstaller implementation:
55 void RegisterComponents() override
{}
57 void Subscribe(const WhitelistReadyCallback
& callback
) override
{
58 ready_callbacks_
.push_back(callback
);
61 void RegisterWhitelist(const std::string
& client_id
,
62 const std::string
& crx_id
,
63 const std::string
& name
) override
{
64 EXPECT_EQ(kClientId
, client_id
);
65 EXPECT_FALSE(WhitelistIsRegistered(crx_id
)) << crx_id
;
66 registered_whitelists_
.insert(crx_id
);
69 void UnregisterWhitelist(const std::string
& client_id
,
70 const std::string
& crx_id
) override
{
71 EXPECT_EQ(kClientId
, client_id
);
72 EXPECT_TRUE(WhitelistIsRegistered(crx_id
)) << crx_id
;
73 registered_whitelists_
.erase(crx_id
);
77 bool WhitelistIsRegistered(const std::string
& crx_id
) {
78 return registered_whitelists_
.count(crx_id
) > 0;
81 std::set
<std::string
> registered_whitelists_
;
82 std::vector
<WhitelistReadyCallback
> ready_callbacks_
;
87 class SupervisedUserWhitelistServiceTest
: public testing::Test
{
89 SupervisedUserWhitelistServiceTest()
90 : installer_(new MockSupervisedUserWhitelistInstaller
),
91 service_(new SupervisedUserWhitelistService(profile_
.GetPrefs(),
94 service_
->AddSiteListsChangedCallback(
95 base::Bind(&SupervisedUserWhitelistServiceTest::OnSiteListsChanged
,
96 base::Unretained(this)));
100 void PrepareInitialStateAndPreferences() {
101 // Create two whitelists.
102 DictionaryPrefUpdate
update(profile_
.GetPrefs(),
103 prefs::kSupervisedUserWhitelists
);
104 base::DictionaryValue
* dict
= update
.Get();
106 scoped_ptr
<base::DictionaryValue
> whitelist_dict(new base::DictionaryValue
);
107 whitelist_dict
->SetString("name", "Whitelist A");
108 dict
->Set("aaaa", whitelist_dict
.release());
110 whitelist_dict
.reset(new base::DictionaryValue
);
111 whitelist_dict
->SetString("name", "Whitelist B");
112 dict
->Set("bbbb", whitelist_dict
.release());
114 installer_
->RegisterWhitelist(kClientId
, "aaaa", "Whitelist A");
115 installer_
->RegisterWhitelist(kClientId
, "bbbb", "Whitelist B");
118 void CheckFinalStateAndPreferences() {
119 EXPECT_EQ(2u, installer_
->registered_whitelists().size());
120 EXPECT_EQ(1u, installer_
->registered_whitelists().count("bbbb"));
121 EXPECT_EQ(1u, installer_
->registered_whitelists().count("cccc"));
123 const base::DictionaryValue
* dict
=
124 profile_
.GetPrefs()->GetDictionary(prefs::kSupervisedUserWhitelists
);
125 EXPECT_EQ(2u, dict
->size());
126 const base::DictionaryValue
* whitelist_dict
= nullptr;
127 ASSERT_TRUE(dict
->GetDictionary("bbbb", &whitelist_dict
));
129 ASSERT_TRUE(whitelist_dict
->GetString("name", &name
));
130 EXPECT_EQ("Whitelist B New", name
);
131 ASSERT_TRUE(dict
->GetDictionary("cccc", &whitelist_dict
));
132 ASSERT_TRUE(whitelist_dict
->GetString("name", &name
));
133 EXPECT_EQ("Whitelist C", name
);
136 const sync_pb::ManagedUserWhitelistSpecifics
* FindWhitelist(
137 const syncer::SyncDataList
& data_list
,
138 const std::string
& id
) {
139 for (const syncer::SyncData
& data
: data_list
) {
140 const sync_pb::ManagedUserWhitelistSpecifics
& whitelist
=
141 data
.GetSpecifics().managed_user_whitelist();
142 if (whitelist
.id() == id
)
148 void OnSiteListsChanged(
149 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists
) {
150 site_lists_
= site_lists
;
151 if (!site_lists_changed_callback_
.is_null())
152 site_lists_changed_callback_
.Run();
155 content::TestBrowserThreadBundle thread_bundle_
;
156 TestingProfile profile_
;
158 #if !defined(OS_ANDROID)
159 safe_json::TestingJsonParser::ScopedFactoryOverride factory_override_
;
162 scoped_ptr
<MockSupervisedUserWhitelistInstaller
> installer_
;
163 scoped_ptr
<SupervisedUserWhitelistService
> service_
;
165 std::vector
<scoped_refptr
<SupervisedUserSiteList
>> site_lists_
;
166 base::Closure site_lists_changed_callback_
;
169 TEST_F(SupervisedUserWhitelistServiceTest
, MergeEmpty
) {
172 syncer::SyncMergeResult result
= service_
->MergeDataAndStartSyncing(
173 syncer::SUPERVISED_USER_WHITELISTS
, syncer::SyncDataList(),
174 scoped_ptr
<syncer::SyncChangeProcessor
>(),
175 scoped_ptr
<syncer::SyncErrorFactory
>());
176 EXPECT_FALSE(result
.error().IsSet());
177 EXPECT_EQ(0, result
.num_items_added());
178 EXPECT_EQ(0, result
.num_items_modified());
179 EXPECT_EQ(0, result
.num_items_deleted());
180 EXPECT_EQ(0, result
.num_items_before_association());
181 EXPECT_EQ(0, result
.num_items_after_association());
183 EXPECT_EQ(0u, installer_
->registered_whitelists().size());
186 TEST_F(SupervisedUserWhitelistServiceTest
, MergeExisting
) {
187 PrepareInitialStateAndPreferences();
189 // Initialize the service. The whitelists should not be ready yet.
191 EXPECT_EQ(0u, site_lists_
.size());
193 // Notify that whitelist A is ready.
194 base::RunLoop run_loop
;
195 site_lists_changed_callback_
= run_loop
.QuitClosure();
196 base::FilePath test_data_dir
;
197 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
198 base::FilePath whitelist_path
=
199 test_data_dir
.AppendASCII("whitelists/content_pack/site_list.json");
200 installer_
->NotifyWhitelistReady("aaaa", whitelist_path
);
203 ASSERT_EQ(1u, site_lists_
.size());
204 const std::vector
<SupervisedUserSiteList::Site
>& sites
=
205 site_lists_
[0]->sites();
206 EXPECT_EQ(3u, sites
.size());
207 EXPECT_EQ("YouTube", base::UTF16ToUTF8(sites
[0].name
));
209 // Do the initial merge. One item should be added (whitelist C), one should be
210 // modified (whitelist B), and one item should be removed (whitelist A).
211 syncer::SyncDataList initial_data
;
212 initial_data
.push_back(
213 SupervisedUserWhitelistService::CreateWhitelistSyncData(
214 "bbbb", "Whitelist B New"));
215 initial_data
.push_back(
216 SupervisedUserWhitelistService::CreateWhitelistSyncData(
217 "cccc", "Whitelist C"));
218 syncer::SyncMergeResult result
= service_
->MergeDataAndStartSyncing(
219 syncer::SUPERVISED_USER_WHITELISTS
, initial_data
,
220 scoped_ptr
<syncer::SyncChangeProcessor
>(),
221 scoped_ptr
<syncer::SyncErrorFactory
>());
222 EXPECT_FALSE(result
.error().IsSet());
223 EXPECT_EQ(1, result
.num_items_added());
224 EXPECT_EQ(1, result
.num_items_modified());
225 EXPECT_EQ(1, result
.num_items_deleted());
226 EXPECT_EQ(2, result
.num_items_before_association());
227 EXPECT_EQ(2, result
.num_items_after_association());
229 // Whitelist A (which was previously ready) should be removed now, and
230 // whitelist B was never ready.
231 EXPECT_EQ(0u, site_lists_
.size());
233 CheckFinalStateAndPreferences();
236 TEST_F(SupervisedUserWhitelistServiceTest
, ApplyChanges
) {
237 PrepareInitialStateAndPreferences();
241 // Process some changes.
242 syncer::SyncChangeList changes
;
243 changes
.push_back(syncer::SyncChange(
244 FROM_HERE
, syncer::SyncChange::ACTION_ADD
,
245 SupervisedUserWhitelistService::CreateWhitelistSyncData(
246 "cccc", "Whitelist C")));
247 changes
.push_back(syncer::SyncChange(
248 FROM_HERE
, syncer::SyncChange::ACTION_UPDATE
,
249 SupervisedUserWhitelistService::CreateWhitelistSyncData(
250 "bbbb", "Whitelist B New")));
251 changes
.push_back(syncer::SyncChange(
252 FROM_HERE
, syncer::SyncChange::ACTION_DELETE
,
253 SupervisedUserWhitelistService::CreateWhitelistSyncData(
254 "aaaa", "Ignored")));
255 syncer::SyncError error
= service_
->ProcessSyncChanges(FROM_HERE
, changes
);
256 EXPECT_FALSE(error
.IsSet());
258 EXPECT_EQ(0u, site_lists_
.size());
260 // If whitelist A now becomes ready, it should be ignored.
261 installer_
->NotifyWhitelistReady(
262 "aaaa", base::FilePath(FILE_PATH_LITERAL("/path/to/aaaa")));
263 EXPECT_EQ(0u, site_lists_
.size());
265 CheckFinalStateAndPreferences();
268 TEST_F(SupervisedUserWhitelistServiceTest
, GetAllSyncData
) {
269 PrepareInitialStateAndPreferences();
271 syncer::SyncDataList sync_data
=
272 service_
->GetAllSyncData(syncer::SUPERVISED_USER_WHITELISTS
);
273 ASSERT_EQ(2u, sync_data
.size());
274 const sync_pb::ManagedUserWhitelistSpecifics
* whitelist
=
275 FindWhitelist(sync_data
, "aaaa");
276 ASSERT_TRUE(whitelist
);
277 EXPECT_EQ("Whitelist A", whitelist
->name());
278 whitelist
= FindWhitelist(sync_data
, "bbbb");
279 ASSERT_TRUE(whitelist
);
280 EXPECT_EQ("Whitelist B", whitelist
->name());