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.
5 #include "base/memory/scoped_ptr.h"
6 #include "base/path_service.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/prefs/scoped_user_pref_update.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
14 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
15 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service.h"
18 #include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service_factory.h"
19 #include "chrome/browser/supervised_user/permission_request_creator.h"
20 #include "chrome/browser/supervised_user/supervised_user_service.h"
21 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
22 #include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
23 #include "chrome/browser/ui/browser_list.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "components/signin/core/browser/signin_manager.h"
28 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "content/public/test/test_utils.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 #if defined(ENABLE_EXTENSIONS)
33 #include "chrome/browser/extensions/extension_service.h"
34 #include "chrome/browser/extensions/extension_service_test_base.h"
35 #include "chrome/browser/extensions/unpacked_installer.h"
36 #include "chrome/common/extensions/features/feature_channel.h"
37 #include "extensions/common/extension.h"
38 #include "extensions/common/extension_builder.h"
39 #include "extensions/common/manifest_constants.h"
42 using content::MessageLoopRunner
;
46 void OnProfileDownloadedFail(const base::string16
& full_name
) {
47 ASSERT_TRUE(false) << "Profile download should not have succeeded.";
50 // Base class for helper objects that wait for certain events to happen.
51 // This class will ensure that calls to QuitRunLoop() (triggered by a subclass)
52 // are balanced with Wait() calls.
53 class AsyncTestHelper
{
62 // |quit_called_| will be initialized in Reset().
67 EXPECT_FALSE(quit_called_
);
71 // QuitRunLoop() can not be called more than once between calls to Wait().
72 ASSERT_FALSE(quit_called_
);
80 run_loop_
.reset(new base::RunLoop
);
83 scoped_ptr
<base::RunLoop
> run_loop_
;
86 DISALLOW_COPY_AND_ASSIGN(AsyncTestHelper
);
89 class SupervisedUserURLFilterObserver
90 : public AsyncTestHelper
,
91 public SupervisedUserURLFilter::Observer
{
93 SupervisedUserURLFilterObserver() : scoped_observer_(this) {}
94 ~SupervisedUserURLFilterObserver() {}
96 void Init(SupervisedUserURLFilter
* url_filter
) {
97 scoped_observer_
.Add(url_filter
);
100 // SupervisedUserURLFilter::Observer
101 void OnSiteListUpdated() override
{
106 ScopedObserver
<SupervisedUserURLFilter
, SupervisedUserURLFilter::Observer
>
109 DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilterObserver
);
112 class SiteListObserver
: public AsyncTestHelper
{
114 SiteListObserver() {}
115 ~SiteListObserver() {}
117 void Init(SupervisedUserWhitelistService
* service
) {
118 service
->AddSiteListsChangedCallback(base::Bind(
119 &SiteListObserver::OnSiteListsChanged
, base::Unretained(this)));
121 // The initial call to AddSiteListsChangedCallback will call
122 // OnSiteListsChanged(), so we balance it out by calling Wait().
126 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists() {
130 const std::vector
<SupervisedUserSiteList::Site
>& sites() {
135 void OnSiteListsChanged(
136 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists
) {
137 site_lists_
= site_lists
;
139 for (const scoped_refptr
<SupervisedUserSiteList
>& site_list
: site_lists
) {
140 const std::vector
<SupervisedUserSiteList::Site
>& sites
=
142 sites_
.insert(sites_
.end(), sites
.begin(), sites
.end());
148 std::vector
<scoped_refptr
<SupervisedUserSiteList
>> site_lists_
;
149 std::vector
<SupervisedUserSiteList::Site
> sites_
;
151 DISALLOW_COPY_AND_ASSIGN(SiteListObserver
);
154 class AsyncResultHolder
{
156 AsyncResultHolder() : result_(false) {}
157 ~AsyncResultHolder() {}
159 void SetResult(bool result
) {
170 base::RunLoop run_loop_
;
173 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder
);
176 class SupervisedUserServiceTest
: public ::testing::Test
{
178 SupervisedUserServiceTest() {}
180 void SetUp() override
{
181 TestingProfile::Builder builder
;
182 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
183 BuildFakeProfileOAuth2TokenService
);
184 profile_
= builder
.Build();
185 supervised_user_service_
=
186 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
189 void TearDown() override
{ profile_
.reset(); }
191 ~SupervisedUserServiceTest() override
{}
194 void AddURLAccessRequest(const GURL
& url
, AsyncResultHolder
* result_holder
) {
195 supervised_user_service_
->AddURLAccessRequest(
196 url
, base::Bind(&AsyncResultHolder::SetResult
,
197 base::Unretained(result_holder
)));
200 content::TestBrowserThreadBundle thread_bundle_
;
201 scoped_ptr
<TestingProfile
> profile_
;
202 SupervisedUserService
* supervised_user_service_
;
207 TEST_F(SupervisedUserServiceTest
, ChangesIncludedSessionOnChangedSettings
) {
208 supervised_user_service_
->Init();
209 EXPECT_TRUE(supervised_user_service_
->IncludesSyncSessionsType());
210 profile_
->GetPrefs()->SetBoolean(prefs::kRecordHistory
, false);
211 EXPECT_FALSE(supervised_user_service_
->IncludesSyncSessionsType());
214 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
215 // DCHECK is hit when the service is destroyed, this test passed.
216 TEST_F(SupervisedUserServiceTest
, ShutDownCustodianProfileDownloader
) {
217 CustodianProfileDownloaderService
* downloader_service
=
218 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_
.get());
220 // Emulate being logged in, then start to download a profile so a
221 // ProfileDownloader gets created.
222 SigninManagerFactory::GetForProfile(profile_
.get())->
223 SetAuthenticatedAccountInfo("12345", "Logged In");
224 downloader_service
->DownloadProfile(base::Bind(&OnProfileDownloadedFail
));
229 class MockPermissionRequestCreator
: public PermissionRequestCreator
{
231 MockPermissionRequestCreator() : enabled_(false) {}
232 ~MockPermissionRequestCreator() override
{}
234 void set_enabled(bool enabled
) {
238 const std::vector
<GURL
>& requested_urls() const {
239 return requested_urls_
;
242 void AnswerRequest(size_t index
, bool result
) {
243 ASSERT_LT(index
, requested_urls_
.size());
244 callbacks_
[index
].Run(result
);
245 callbacks_
.erase(callbacks_
.begin() + index
);
246 requested_urls_
.erase(requested_urls_
.begin() + index
);
250 // PermissionRequestCreator:
251 bool IsEnabled() const override
{ return enabled_
; }
253 void CreateURLAccessRequest(const GURL
& url_requested
,
254 const SuccessCallback
& callback
) override
{
255 ASSERT_TRUE(enabled_
);
256 requested_urls_
.push_back(url_requested
);
257 callbacks_
.push_back(callback
);
260 void CreateExtensionUpdateRequest(const std::string
& id
,
261 const SuccessCallback
& callback
) override
{
266 std::vector
<GURL
> requested_urls_
;
267 std::vector
<SuccessCallback
> callbacks_
;
269 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator
);
274 TEST_F(SupervisedUserServiceTest
, CreatePermissionRequest
) {
275 GURL
url("http://www.example.com");
277 // Without any permission request creators, it should be disabled, and any
278 // AddURLAccessRequest() calls should fail.
279 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
281 AsyncResultHolder result_holder
;
282 AddURLAccessRequest(url
, &result_holder
);
283 EXPECT_FALSE(result_holder
.GetResult());
286 // Add a disabled permission request creator. This should not change anything.
287 MockPermissionRequestCreator
* creator
= new MockPermissionRequestCreator
;
288 supervised_user_service_
->AddPermissionRequestCreator(
289 make_scoped_ptr(creator
));
291 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
293 AsyncResultHolder result_holder
;
294 AddURLAccessRequest(url
, &result_holder
);
295 EXPECT_FALSE(result_holder
.GetResult());
298 // Enable the permission request creator. This should enable permission
299 // requests and queue them up.
300 creator
->set_enabled(true);
301 EXPECT_TRUE(supervised_user_service_
->AccessRequestsEnabled());
303 AsyncResultHolder result_holder
;
304 AddURLAccessRequest(url
, &result_holder
);
305 ASSERT_EQ(1u, creator
->requested_urls().size());
306 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
308 creator
->AnswerRequest(0, true);
309 EXPECT_TRUE(result_holder
.GetResult());
313 AsyncResultHolder result_holder
;
314 AddURLAccessRequest(url
, &result_holder
);
315 ASSERT_EQ(1u, creator
->requested_urls().size());
316 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
318 creator
->AnswerRequest(0, false);
319 EXPECT_FALSE(result_holder
.GetResult());
322 // Add a second permission request creator.
323 MockPermissionRequestCreator
* creator_2
= new MockPermissionRequestCreator
;
324 creator_2
->set_enabled(true);
325 supervised_user_service_
->AddPermissionRequestCreator(
326 make_scoped_ptr(creator_2
));
329 AsyncResultHolder result_holder
;
330 AddURLAccessRequest(url
, &result_holder
);
331 ASSERT_EQ(1u, creator
->requested_urls().size());
332 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
334 // Make the first creator succeed. This should make the whole thing succeed.
335 creator
->AnswerRequest(0, true);
336 EXPECT_TRUE(result_holder
.GetResult());
340 AsyncResultHolder result_holder
;
341 AddURLAccessRequest(url
, &result_holder
);
342 ASSERT_EQ(1u, creator
->requested_urls().size());
343 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
345 // Make the first creator fail. This should fall back to the second one.
346 creator
->AnswerRequest(0, false);
347 ASSERT_EQ(1u, creator_2
->requested_urls().size());
348 EXPECT_EQ(url
.spec(), creator_2
->requested_urls()[0].spec());
350 // Make the second creator succeed, which will make the whole thing succeed.
351 creator_2
->AnswerRequest(0, true);
352 EXPECT_TRUE(result_holder
.GetResult());
356 #if defined(ENABLE_EXTENSIONS)
357 class SupervisedUserServiceExtensionTestBase
358 : public extensions::ExtensionServiceTestBase
{
360 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised
)
361 : is_supervised_(is_supervised
),
362 channel_(chrome::VersionInfo::CHANNEL_DEV
) {}
363 ~SupervisedUserServiceExtensionTestBase() override
{}
365 void SetUp() override
{
366 ExtensionServiceTestBase::SetUp();
367 ExtensionServiceTestBase::ExtensionServiceInitParams params
=
368 CreateDefaultInitParams();
369 params
.profile_is_supervised
= is_supervised_
;
370 InitializeExtensionService(params
);
371 SupervisedUserService
* service
=
372 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
374 site_list_observer_
.Init(service
->GetWhitelistService());
376 SupervisedUserURLFilter
* url_filter
= service
->GetURLFilterForUIThread();
377 url_filter
->SetBlockingTaskRunnerForTesting(
378 base::ThreadTaskRunnerHandle::Get());
379 url_filter_observer_
.Init(url_filter
);
381 // Wait for the initial update to finish.
382 url_filter_observer_
.Wait();
385 void TearDown() override
{
386 // Flush the message loop, to ensure all posted tasks run.
387 base::RunLoop().RunUntilIdle();
391 scoped_refptr
<extensions::Extension
> MakeThemeExtension() {
392 scoped_ptr
<base::DictionaryValue
> source(new base::DictionaryValue());
393 source
->SetString(extensions::manifest_keys::kName
, "Theme");
394 source
->Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
395 source
->SetString(extensions::manifest_keys::kVersion
, "1.0");
396 extensions::ExtensionBuilder builder
;
397 scoped_refptr
<extensions::Extension
> extension
=
398 builder
.SetManifest(source
.Pass()).Build();
402 scoped_refptr
<extensions::Extension
> MakeExtension(bool by_custodian
) {
403 scoped_ptr
<base::DictionaryValue
> manifest
= extensions::DictionaryBuilder()
404 .Set(extensions::manifest_keys::kName
, "Extension")
405 .Set(extensions::manifest_keys::kVersion
, "1.0")
407 int creation_flags
= extensions::Extension::NO_FLAGS
;
409 creation_flags
|= extensions::Extension::WAS_INSTALLED_BY_CUSTODIAN
;
410 extensions::ExtensionBuilder builder
;
411 scoped_refptr
<extensions::Extension
> extension
=
412 builder
.SetManifest(manifest
.Pass()).AddFlags(creation_flags
).Build();
417 extensions::ScopedCurrentChannel channel_
;
418 SiteListObserver site_list_observer_
;
419 SupervisedUserURLFilterObserver url_filter_observer_
;
422 class SupervisedUserServiceExtensionTestUnsupervised
423 : public SupervisedUserServiceExtensionTestBase
{
425 SupervisedUserServiceExtensionTestUnsupervised()
426 : SupervisedUserServiceExtensionTestBase(false) {}
429 class SupervisedUserServiceExtensionTest
430 : public SupervisedUserServiceExtensionTestBase
{
432 SupervisedUserServiceExtensionTest()
433 : SupervisedUserServiceExtensionTestBase(true) {}
436 TEST_F(SupervisedUserServiceExtensionTest
, ExtensionManagementPolicyProvider
) {
437 SupervisedUserService
* supervised_user_service
=
438 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
439 ASSERT_TRUE(profile_
->IsSupervised());
441 // Check that a supervised user can install and uninstall a theme.
443 scoped_refptr
<extensions::Extension
> theme
= MakeThemeExtension();
445 base::string16 error_1
;
446 EXPECT_TRUE(supervised_user_service
->UserMayLoad(theme
.get(), &error_1
));
447 EXPECT_TRUE(error_1
.empty());
449 base::string16 error_2
;
451 supervised_user_service
->MustRemainInstalled(theme
.get(), &error_2
));
452 EXPECT_TRUE(error_2
.empty());
455 // Now check a different kind of extension; the supervised user should not be
458 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
460 base::string16 error
;
461 EXPECT_FALSE(supervised_user_service
->UserMayLoad(extension
.get(), &error
));
462 EXPECT_FALSE(error
.empty());
466 // Check that a custodian-installed extension may be loaded, but not
468 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(true);
470 base::string16 error_1
;
472 supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
473 EXPECT_TRUE(error_1
.empty());
475 base::string16 error_2
;
477 supervised_user_service
->MustRemainInstalled(extension
.get(),
479 EXPECT_FALSE(error_2
.empty());
483 EXPECT_FALSE(supervised_user_service
->GetDebugPolicyProviderName().empty());
487 TEST_F(SupervisedUserServiceExtensionTest
, NoContentPacks
) {
488 SupervisedUserService
* supervised_user_service
=
489 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
490 SupervisedUserURLFilter
* url_filter
=
491 supervised_user_service
->GetURLFilterForUIThread();
493 // ASSERT_EQ instead of ASSERT_TRUE([...].empty()) so that the error
494 // message contains the size in case of failure.
495 ASSERT_EQ(0u, site_list_observer_
.site_lists().size());
497 GURL
url("http://youtube.com");
498 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
499 url_filter
->GetFilteringBehaviorForURL(url
));
502 TEST_F(SupervisedUserServiceExtensionTest
, InstallContentPacks
) {
503 SupervisedUserService
* supervised_user_service
=
504 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
505 SupervisedUserURLFilter
* url_filter
=
506 supervised_user_service
->GetURLFilterForUIThread();
508 GURL
example_url("http://example.com");
509 GURL
moose_url("http://moose.org");
510 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
511 url_filter
->GetFilteringBehaviorForURL(example_url
));
513 profile_
->GetPrefs()->SetInteger(
514 prefs::kDefaultSupervisedUserFilteringBehavior
,
515 SupervisedUserURLFilter::BLOCK
);
516 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
517 url_filter
->GetFilteringBehaviorForURL(example_url
));
519 profile_
->GetPrefs()->SetInteger(
520 prefs::kDefaultSupervisedUserFilteringBehavior
,
521 SupervisedUserURLFilter::WARN
);
522 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
523 url_filter
->GetFilteringBehaviorForURL(example_url
));
526 base::FilePath test_data_dir
;
527 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
528 SupervisedUserWhitelistService
* whitelist_service
=
529 supervised_user_service
->GetWhitelistService();
530 base::FilePath whitelist_path
=
531 test_data_dir
.AppendASCII("whitelists/content_pack/site_list.json");
532 whitelist_service
->LoadWhitelistForTesting("aaaa", whitelist_path
);
533 site_list_observer_
.Wait();
535 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
536 ASSERT_EQ(3u, site_list_observer_
.sites().size());
537 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), site_list_observer_
.sites()[0].name
);
538 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"),
539 site_list_observer_
.sites()[1].name
);
540 EXPECT_EQ(base::string16(), site_list_observer_
.sites()[2].name
);
542 url_filter_observer_
.Wait();
543 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
544 url_filter
->GetFilteringBehaviorForURL(example_url
));
545 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
546 url_filter
->GetFilteringBehaviorForURL(moose_url
));
548 // Load a second whitelist.
550 test_data_dir
.AppendASCII("whitelists/content_pack_2/site_list.json");
551 whitelist_service
->LoadWhitelistForTesting("bbbb", whitelist_path
);
552 site_list_observer_
.Wait();
554 ASSERT_EQ(2u, site_list_observer_
.site_lists().size());
555 ASSERT_EQ(4u, site_list_observer_
.sites().size());
557 // The site lists might be returned in any order, so we put them into a set.
558 std::set
<std::string
> site_names
;
559 for (const SupervisedUserSiteList::Site
& site
: site_list_observer_
.sites())
560 site_names
.insert(base::UTF16ToUTF8(site
.name
));
561 EXPECT_EQ(1u, site_names
.count("YouTube"));
562 EXPECT_EQ(1u, site_names
.count("Homestar Runner"));
563 EXPECT_EQ(1u, site_names
.count(std::string()));
564 EXPECT_EQ(1u, site_names
.count("Moose"));
566 url_filter_observer_
.Wait();
567 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
568 url_filter
->GetFilteringBehaviorForURL(example_url
));
569 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
570 url_filter
->GetFilteringBehaviorForURL(moose_url
));
572 // Unload the first whitelist.
573 whitelist_service
->UnloadWhitelist("aaaa");
574 site_list_observer_
.Wait();
576 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
577 ASSERT_EQ(1u, site_list_observer_
.sites().size());
578 EXPECT_EQ(base::ASCIIToUTF16("Moose"), site_list_observer_
.sites()[0].name
);
580 url_filter_observer_
.Wait();
581 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
582 url_filter
->GetFilteringBehaviorForURL(example_url
));
583 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
584 url_filter
->GetFilteringBehaviorForURL(moose_url
));
586 #endif // defined(ENABLE_EXTENSIONS)