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.
4
5 #include "chrome/browser/supervised_user/supervised_user_service.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/path_service.h"
16 #include "base/run_loop.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/test/scoped_feature_list.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/values.h"
21 #include "build/build_config.h"
22 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
25 #include "chrome/browser/supervised_user/permission_request_creator.h"
26 #include "chrome/browser/supervised_user/supervised_user_allowlist_service.h"
27 #include "chrome/browser/supervised_user/supervised_user_features.h"
28 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "components/prefs/pref_service.h"
33 #include "components/prefs/scoped_user_pref_update.h"
34 #include "components/version_info/version_info.h"
35 #include "content/public/test/browser_task_environment.h"
36 #include "content/public/test/test_utils.h"
37 #include "extensions/buildflags/buildflags.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 #if BUILDFLAG(ENABLE_EXTENSIONS)
41 #include "chrome/browser/extensions/extension_service.h"
42 #include "chrome/browser/extensions/extension_service_test_base.h"
43 #include "chrome/browser/extensions/extension_util.h"
44 #include "chrome/browser/extensions/unpacked_installer.h"
45 #include "extensions/common/extension.h"
46 #include "extensions/common/extension_builder.h"
47 #include "extensions/common/features/feature_channel.h"
48 #include "extensions/common/manifest_constants.h"
49
50 using extensions::Extension;
51 #endif
52
53 using content::MessageLoopRunner;
54
55 namespace {
56
57 // Base class for helper objects that wait for certain events to happen.
58 // This class will ensure that calls to QuitRunLoop() (triggered by a subclass)
59 // are balanced with Wait() calls.
60 class AsyncTestHelper {
61 public:
Wait()62 void Wait() {
63 run_loop_->Run();
64 Reset();
65 }
66
67 protected:
AsyncTestHelper()68 AsyncTestHelper() {
69 // |quit_called_| will be initialized in Reset().
70 Reset();
71 }
72
~AsyncTestHelper()73 ~AsyncTestHelper() {
74 EXPECT_FALSE(quit_called_);
75 }
76
QuitRunLoop()77 void QuitRunLoop() {
78 // QuitRunLoop() can not be called more than once between calls to Wait().
79 ASSERT_FALSE(quit_called_);
80 quit_called_ = true;
81 run_loop_->Quit();
82 }
83
84 private:
Reset()85 void Reset() {
86 quit_called_ = false;
87 run_loop_.reset(new base::RunLoop);
88 }
89
90 std::unique_ptr<base::RunLoop> run_loop_;
91 bool quit_called_;
92
93 DISALLOW_COPY_AND_ASSIGN(AsyncTestHelper);
94 };
95
96 class SupervisedUserURLFilterObserver
97 : public AsyncTestHelper,
98 public SupervisedUserURLFilter::Observer {
99 public:
SupervisedUserURLFilterObserver()100 SupervisedUserURLFilterObserver() : scoped_observer_(this) {}
~SupervisedUserURLFilterObserver()101 ~SupervisedUserURLFilterObserver() {}
102
Init(SupervisedUserURLFilter * url_filter)103 void Init(SupervisedUserURLFilter* url_filter) {
104 scoped_observer_.Add(url_filter);
105 }
106
107 // SupervisedUserURLFilter::Observer
OnSiteListUpdated()108 void OnSiteListUpdated() override {
109 QuitRunLoop();
110 }
111
112 private:
113 ScopedObserver<SupervisedUserURLFilter, SupervisedUserURLFilter::Observer>
114 scoped_observer_;
115
116 DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilterObserver);
117 };
118
119 class SiteListObserver : public AsyncTestHelper {
120 public:
SiteListObserver()121 SiteListObserver() {}
~SiteListObserver()122 ~SiteListObserver() {}
123
Init(SupervisedUserAllowlistService * service)124 void Init(SupervisedUserAllowlistService* service) {
125 service->AddSiteListsChangedCallback(base::Bind(
126 &SiteListObserver::OnSiteListsChanged, base::Unretained(this)));
127
128 // The initial call to AddSiteListsChangedCallback will call
129 // OnSiteListsChanged(), so we balance it out by calling Wait().
130 Wait();
131 }
132
site_lists()133 const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists() {
134 return site_lists_;
135 }
136
137 private:
OnSiteListsChanged(const std::vector<scoped_refptr<SupervisedUserSiteList>> & site_lists)138 void OnSiteListsChanged(
139 const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists) {
140 site_lists_ = site_lists;
141
142 QuitRunLoop();
143 }
144
145 std::vector<scoped_refptr<SupervisedUserSiteList>> site_lists_;
146
147 DISALLOW_COPY_AND_ASSIGN(SiteListObserver);
148 };
149
150 class AsyncResultHolder {
151 public:
AsyncResultHolder()152 AsyncResultHolder() : result_(false) {}
~AsyncResultHolder()153 ~AsyncResultHolder() {}
154
SetResult(bool result)155 void SetResult(bool result) {
156 result_ = result;
157 run_loop_.Quit();
158 }
159
GetResult()160 bool GetResult() {
161 run_loop_.Run();
162 return result_;
163 }
164
165 private:
166 base::RunLoop run_loop_;
167 bool result_;
168
169 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder);
170 };
171
172 class SupervisedUserServiceTest : public ::testing::Test {
173 public:
SupervisedUserServiceTest()174 SupervisedUserServiceTest() {}
175
SetUp()176 void SetUp() override {
177 profile_ = IdentityTestEnvironmentProfileAdaptor::
178 CreateProfileForIdentityTestEnvironment({});
179 identity_test_environment_adaptor_ =
180 std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
181 supervised_user_service_ =
182 SupervisedUserServiceFactory::GetForProfile(profile_.get());
183 }
184
TearDown()185 void TearDown() override {
186 identity_test_environment_adaptor_.reset();
187 profile_.reset();
188 }
189
~SupervisedUserServiceTest()190 ~SupervisedUserServiceTest() override {}
191
192 protected:
AddURLAccessRequest(const GURL & url,AsyncResultHolder * result_holder)193 void AddURLAccessRequest(const GURL& url, AsyncResultHolder* result_holder) {
194 supervised_user_service_->AddURLAccessRequest(
195 url, base::BindOnce(&AsyncResultHolder::SetResult,
196 base::Unretained(result_holder)));
197 }
198
199 std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
200 identity_test_environment_adaptor_;
201 content::BrowserTaskEnvironment task_environment_;
202 std::unique_ptr<TestingProfile> profile_;
203 SupervisedUserService* supervised_user_service_;
204 };
205
206 } // namespace
207
208 namespace {
209
210 class MockPermissionRequestCreator : public PermissionRequestCreator {
211 public:
MockPermissionRequestCreator()212 MockPermissionRequestCreator() : enabled_(false) {}
~MockPermissionRequestCreator()213 ~MockPermissionRequestCreator() override {}
214
set_enabled(bool enabled)215 void set_enabled(bool enabled) {
216 enabled_ = enabled;
217 }
218
requested_urls() const219 const std::vector<GURL>& requested_urls() const {
220 return requested_urls_;
221 }
222
AnswerRequest(size_t index,bool result)223 void AnswerRequest(size_t index, bool result) {
224 ASSERT_LT(index, requested_urls_.size());
225 std::move(callbacks_[index]).Run(result);
226 callbacks_.erase(callbacks_.begin() + index);
227 requested_urls_.erase(requested_urls_.begin() + index);
228 }
229
230 private:
231 // PermissionRequestCreator:
IsEnabled() const232 bool IsEnabled() const override { return enabled_; }
233
CreateURLAccessRequest(const GURL & url_requested,SuccessCallback callback)234 void CreateURLAccessRequest(const GURL& url_requested,
235 SuccessCallback callback) override {
236 ASSERT_TRUE(enabled_);
237 requested_urls_.push_back(url_requested);
238 callbacks_.push_back(std::move(callback));
239 }
240
241 bool enabled_;
242 std::vector<GURL> requested_urls_;
243 std::vector<SuccessCallback> callbacks_;
244
245 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
246 };
247
248 } // namespace
249
TEST_F(SupervisedUserServiceTest,CreatePermissionRequest)250 TEST_F(SupervisedUserServiceTest, CreatePermissionRequest) {
251 GURL url("http://www.example.com");
252
253 // Without any permission request creators, it should be disabled, and any
254 // AddURLAccessRequest() calls should fail.
255 EXPECT_FALSE(supervised_user_service_->AccessRequestsEnabled());
256 {
257 AsyncResultHolder result_holder;
258 AddURLAccessRequest(url, &result_holder);
259 EXPECT_FALSE(result_holder.GetResult());
260 }
261
262 // Add a disabled permission request creator. This should not change anything.
263 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
264 supervised_user_service_->AddPermissionRequestCreator(
265 base::WrapUnique(creator));
266
267 EXPECT_FALSE(supervised_user_service_->AccessRequestsEnabled());
268 {
269 AsyncResultHolder result_holder;
270 AddURLAccessRequest(url, &result_holder);
271 EXPECT_FALSE(result_holder.GetResult());
272 }
273
274 // Enable the permission request creator. This should enable permission
275 // requests and queue them up.
276 creator->set_enabled(true);
277 EXPECT_TRUE(supervised_user_service_->AccessRequestsEnabled());
278 {
279 AsyncResultHolder result_holder;
280 AddURLAccessRequest(url, &result_holder);
281 ASSERT_EQ(1u, creator->requested_urls().size());
282 EXPECT_EQ(url.spec(), creator->requested_urls()[0].spec());
283
284 creator->AnswerRequest(0, true);
285 EXPECT_TRUE(result_holder.GetResult());
286 }
287
288 {
289 AsyncResultHolder result_holder;
290 AddURLAccessRequest(url, &result_holder);
291 ASSERT_EQ(1u, creator->requested_urls().size());
292 EXPECT_EQ(url.spec(), creator->requested_urls()[0].spec());
293
294 creator->AnswerRequest(0, false);
295 EXPECT_FALSE(result_holder.GetResult());
296 }
297
298 // Add a second permission request creator.
299 MockPermissionRequestCreator* creator_2 = new MockPermissionRequestCreator;
300 creator_2->set_enabled(true);
301 supervised_user_service_->AddPermissionRequestCreator(
302 base::WrapUnique(creator_2));
303
304 {
305 AsyncResultHolder result_holder;
306 AddURLAccessRequest(url, &result_holder);
307 ASSERT_EQ(1u, creator->requested_urls().size());
308 EXPECT_EQ(url.spec(), creator->requested_urls()[0].spec());
309
310 // Make the first creator succeed. This should make the whole thing succeed.
311 creator->AnswerRequest(0, true);
312 EXPECT_TRUE(result_holder.GetResult());
313 }
314
315 {
316 AsyncResultHolder result_holder;
317 AddURLAccessRequest(url, &result_holder);
318 ASSERT_EQ(1u, creator->requested_urls().size());
319 EXPECT_EQ(url.spec(), creator->requested_urls()[0].spec());
320
321 // Make the first creator fail. This should fall back to the second one.
322 creator->AnswerRequest(0, false);
323 ASSERT_EQ(1u, creator_2->requested_urls().size());
324 EXPECT_EQ(url.spec(), creator_2->requested_urls()[0].spec());
325
326 // Make the second creator succeed, which will make the whole thing succeed.
327 creator_2->AnswerRequest(0, true);
328 EXPECT_TRUE(result_holder.GetResult());
329 }
330 }
331
332 #if BUILDFLAG(ENABLE_EXTENSIONS)
333 class SupervisedUserServiceExtensionTestBase
334 : public extensions::ExtensionServiceTestBase {
335 public:
SupervisedUserServiceExtensionTestBase(bool is_supervised)336 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised)
337 : is_supervised_(is_supervised),
338 channel_(version_info::Channel::DEV) {}
~SupervisedUserServiceExtensionTestBase()339 ~SupervisedUserServiceExtensionTestBase() override {}
340
SetUp()341 void SetUp() override {
342 ExtensionServiceTestBase::SetUp();
343 ExtensionServiceTestBase::ExtensionServiceInitParams params =
344 CreateDefaultInitParams();
345 params.profile_is_supervised = is_supervised_;
346 InitializeExtensionService(params);
347 // Flush the message loop, to ensure that credentials have been loaded in
348 // Identity Manager.
349 base::RunLoop().RunUntilIdle();
350
351 SupervisedUserService* service =
352 SupervisedUserServiceFactory::GetForProfile(profile_.get());
353 service->Init();
354 site_list_observer_.Init(service->GetAllowlistService());
355
356 SupervisedUserURLFilter* url_filter = service->GetURLFilter();
357 url_filter->SetBlockingTaskRunnerForTesting(
358 base::ThreadTaskRunnerHandle::Get());
359 url_filter_observer_.Init(url_filter);
360
361 // Wait for the initial update to finish.
362 url_filter_observer_.Wait();
363 }
364
TearDown()365 void TearDown() override {
366 // Flush the message loop, to ensure all posted tasks run.
367 base::RunLoop().RunUntilIdle();
368 }
369
370 protected:
MakeThemeExtension()371 scoped_refptr<const extensions::Extension> MakeThemeExtension() {
372 std::unique_ptr<base::DictionaryValue> source(new base::DictionaryValue());
373 source->SetString(extensions::manifest_keys::kName, "Theme");
374 source->Set(extensions::manifest_keys::kTheme,
375 std::make_unique<base::DictionaryValue>());
376 source->SetString(extensions::manifest_keys::kVersion, "1.0");
377 extensions::ExtensionBuilder builder;
378 scoped_refptr<const extensions::Extension> extension =
379 builder.SetManifest(std::move(source)).Build();
380 return extension;
381 }
382
MakeExtension()383 scoped_refptr<const extensions::Extension> MakeExtension() {
384 scoped_refptr<const extensions::Extension> extension =
385 extensions::ExtensionBuilder("Extension").Build();
386 return extension;
387 }
388
InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled)389 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
390 if (enabled) {
391 scoped_feature_list_.InitAndEnableFeature(
392 supervised_users::kSupervisedUserInitiatedExtensionInstall);
393 }
394 }
395
396 bool is_supervised_;
397 extensions::ScopedCurrentChannel channel_;
398 SiteListObserver site_list_observer_;
399 SupervisedUserURLFilterObserver url_filter_observer_;
400 base::test::ScopedFeatureList scoped_feature_list_;
401 };
402
403 class SupervisedUserServiceExtensionTestUnsupervised
404 : public SupervisedUserServiceExtensionTestBase {
405 public:
SupervisedUserServiceExtensionTestUnsupervised()406 SupervisedUserServiceExtensionTestUnsupervised()
407 : SupervisedUserServiceExtensionTestBase(false) {}
408 };
409
410 class SupervisedUserServiceExtensionTest
411 : public SupervisedUserServiceExtensionTestBase {
412 public:
SupervisedUserServiceExtensionTest()413 SupervisedUserServiceExtensionTest()
414 : SupervisedUserServiceExtensionTestBase(true) {}
415 };
416
TEST_F(SupervisedUserServiceExtensionTest,ExtensionManagementPolicyProviderWithoutSUInitiatedInstalls)417 TEST_F(SupervisedUserServiceExtensionTest,
418 ExtensionManagementPolicyProviderWithoutSUInitiatedInstalls) {
419 InitSupervisedUserInitiatedExtensionInstallFeature(true);
420
421 SupervisedUserService* supervised_user_service =
422 SupervisedUserServiceFactory::GetForProfile(profile_.get());
423 supervised_user_service
424 ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(false);
425 EXPECT_FALSE(supervised_user_service
426 ->GetSupervisedUserExtensionsMayRequestPermissionsPref());
427 EXPECT_TRUE(profile_->IsSupervised());
428
429 // Check that a supervised user can install and uninstall a theme even if
430 // they are not allowed to install extensions.
431 {
432 scoped_refptr<const extensions::Extension> theme = MakeThemeExtension();
433
434 base::string16 error_1;
435 EXPECT_TRUE(supervised_user_service->UserMayLoad(theme.get(), &error_1));
436 EXPECT_TRUE(error_1.empty());
437
438 base::string16 error_2;
439 EXPECT_FALSE(
440 supervised_user_service->MustRemainInstalled(theme.get(), &error_2));
441 EXPECT_TRUE(error_2.empty());
442 }
443
444 // Now check a different kind of extension; the supervised user should not be
445 // able to load it. It should also not need to remain installed.
446 {
447 scoped_refptr<const extensions::Extension> extension = MakeExtension();
448
449 base::string16 error_1;
450 EXPECT_FALSE(
451 supervised_user_service->UserMayLoad(extension.get(), &error_1));
452 EXPECT_FALSE(error_1.empty());
453
454 base::string16 error_2;
455 EXPECT_FALSE(
456 supervised_user_service->UserMayInstall(extension.get(), &error_2));
457 EXPECT_FALSE(error_2.empty());
458
459 base::string16 error_3;
460 EXPECT_FALSE(supervised_user_service->MustRemainInstalled(extension.get(),
461 &error_3));
462 EXPECT_TRUE(error_3.empty());
463 }
464
465 #if DCHECK_IS_ON()
466 EXPECT_FALSE(supervised_user_service->GetDebugPolicyProviderName().empty());
467 #endif
468 }
469
TEST_F(SupervisedUserServiceExtensionTest,ExtensionManagementPolicyProviderWithSUInitiatedInstalls)470 TEST_F(SupervisedUserServiceExtensionTest,
471 ExtensionManagementPolicyProviderWithSUInitiatedInstalls) {
472 // Enable child users to initiate extension installs by simulating the
473 // toggling of "Permissions for sites and apps" to enabled.
474 InitSupervisedUserInitiatedExtensionInstallFeature(true);
475
476 SupervisedUserService* supervised_user_service =
477 SupervisedUserServiceFactory::GetForProfile(profile_.get());
478 supervised_user_service
479 ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(true);
480 EXPECT_TRUE(supervised_user_service
481 ->GetSupervisedUserExtensionsMayRequestPermissionsPref());
482 EXPECT_TRUE(profile_->IsSupervised());
483
484 // The supervised user should be able to load and uninstall the extensions
485 // they install.
486 {
487 scoped_refptr<const extensions::Extension> extension = MakeExtension();
488
489 base::string16 error;
490 EXPECT_TRUE(supervised_user_service->UserMayLoad(extension.get(), &error));
491 EXPECT_TRUE(error.empty());
492
493 base::string16 error_2;
494 EXPECT_FALSE(supervised_user_service->MustRemainInstalled(extension.get(),
495 &error_2));
496 EXPECT_TRUE(error_2.empty());
497
498 base::string16 error_3;
499 extensions::disable_reason::DisableReason reason =
500 extensions::disable_reason::DISABLE_NONE;
501 EXPECT_TRUE(supervised_user_service->MustRemainDisabled(extension.get(),
502 &reason,
503 &error_3));
504 EXPECT_EQ(extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED,
505 reason);
506 EXPECT_FALSE(error_3.empty());
507
508 base::string16 error_4;
509 EXPECT_TRUE(supervised_user_service->UserMayModifySettings(extension.get(),
510 &error_4));
511 EXPECT_TRUE(error_4.empty());
512
513 base::string16 error_5;
514 EXPECT_TRUE(
515 supervised_user_service->UserMayInstall(extension.get(), &error_5));
516 EXPECT_TRUE(error_5.empty());
517 }
518
519 #if DCHECK_IS_ON()
520 EXPECT_FALSE(supervised_user_service->GetDebugPolicyProviderName().empty());
521 #endif
522 }
523
TEST_F(SupervisedUserServiceExtensionTest,NoContentPacks)524 TEST_F(SupervisedUserServiceExtensionTest, NoContentPacks) {
525 InitSupervisedUserInitiatedExtensionInstallFeature(true);
526
527 SupervisedUserService* supervised_user_service =
528 SupervisedUserServiceFactory::GetForProfile(profile_.get());
529 SupervisedUserURLFilter* url_filter = supervised_user_service->GetURLFilter();
530
531 // ASSERT_EQ instead of ASSERT_TRUE([...].empty()) so that the error
532 // message contains the size in case of failure.
533 ASSERT_EQ(0u, site_list_observer_.site_lists().size());
534
535 GURL url("http://youtube.com");
536 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
537 url_filter->GetFilteringBehaviorForURL(url));
538 }
539
TEST_F(SupervisedUserServiceExtensionTest,InstallContentPacks)540 TEST_F(SupervisedUserServiceExtensionTest, InstallContentPacks) {
541 InitSupervisedUserInitiatedExtensionInstallFeature(true);
542
543 SupervisedUserService* supervised_user_service =
544 SupervisedUserServiceFactory::GetForProfile(profile_.get());
545 SupervisedUserURLFilter* url_filter = supervised_user_service->GetURLFilter();
546
547 const std::string id1 = "ID 1";
548 const base::string16 title1 = base::ASCIIToUTF16("Title 1");
549 const std::string id2 = "ID 2";
550 const base::string16 title2 = base::ASCIIToUTF16("Title 2");
551
552 GURL youtube_url("http://www.youtube.com");
553 GURL moose_url("http://moose.org");
554 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
555 url_filter->GetFilteringBehaviorForURL(youtube_url));
556
557 profile_->GetPrefs()->SetInteger(
558 prefs::kDefaultSupervisedUserFilteringBehavior,
559 SupervisedUserURLFilter::BLOCK);
560 EXPECT_EQ(SupervisedUserURLFilter::BLOCK,
561 url_filter->GetFilteringBehaviorForURL(youtube_url));
562
563 profile_->GetPrefs()->SetInteger(
564 prefs::kDefaultSupervisedUserFilteringBehavior,
565 SupervisedUserURLFilter::WARN);
566 EXPECT_EQ(SupervisedUserURLFilter::WARN,
567 url_filter->GetFilteringBehaviorForURL(youtube_url));
568
569 // Load a allowlist.
570 base::FilePath test_data_dir;
571 ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
572 SupervisedUserAllowlistService* allowlist_service =
573 supervised_user_service->GetAllowlistService();
574 base::FilePath allowlist_path =
575 test_data_dir.AppendASCII("whitelists/content_pack/site_list.json");
576 allowlist_service->LoadAllowlistForTesting(id1, title1, allowlist_path);
577 site_list_observer_.Wait();
578
579 ASSERT_EQ(1u, site_list_observer_.site_lists().size());
580 EXPECT_EQ(id1, site_list_observer_.site_lists()[0]->id());
581 EXPECT_EQ(title1, site_list_observer_.site_lists()[0]->title());
582 EXPECT_EQ(youtube_url, site_list_observer_.site_lists()[0]->entry_point());
583
584 url_filter_observer_.Wait();
585 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
586 url_filter->GetFilteringBehaviorForURL(youtube_url));
587 EXPECT_EQ(SupervisedUserURLFilter::WARN,
588 url_filter->GetFilteringBehaviorForURL(moose_url));
589
590 // Load a second allowlist.
591 allowlist_path =
592 test_data_dir.AppendASCII("whitelists/content_pack_2/site_list.json");
593 allowlist_service->LoadAllowlistForTesting(id2, title2, allowlist_path);
594 site_list_observer_.Wait();
595
596 ASSERT_EQ(2u, site_list_observer_.site_lists().size());
597 EXPECT_EQ(id1, site_list_observer_.site_lists()[0]->id());
598 EXPECT_EQ(title1, site_list_observer_.site_lists()[0]->title());
599 EXPECT_EQ(youtube_url, site_list_observer_.site_lists()[0]->entry_point());
600 EXPECT_EQ(id2, site_list_observer_.site_lists()[1]->id());
601 EXPECT_EQ(title2, site_list_observer_.site_lists()[1]->title());
602 EXPECT_TRUE(site_list_observer_.site_lists()[1]->entry_point().is_empty());
603
604 url_filter_observer_.Wait();
605 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
606 url_filter->GetFilteringBehaviorForURL(youtube_url));
607 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
608 url_filter->GetFilteringBehaviorForURL(moose_url));
609
610 // Unload the first allowlist.
611 allowlist_service->UnloadAllowlist(id1);
612 site_list_observer_.Wait();
613
614 ASSERT_EQ(1u, site_list_observer_.site_lists().size());
615 EXPECT_EQ(id2, site_list_observer_.site_lists()[0]->id());
616 EXPECT_EQ(title2, site_list_observer_.site_lists()[0]->title());
617 EXPECT_TRUE(site_list_observer_.site_lists()[0]->entry_point().is_empty());
618
619 url_filter_observer_.Wait();
620 EXPECT_EQ(SupervisedUserURLFilter::WARN,
621 url_filter->GetFilteringBehaviorForURL(youtube_url));
622 EXPECT_EQ(SupervisedUserURLFilter::ALLOW,
623 url_filter->GetFilteringBehaviorForURL(moose_url));
624 }
625 #endif // BUILDFLAG(ENABLE_EXTENSIONS)
626