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_builder.h"
14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service.h"
17 #include "chrome/browser/supervised_user/legacy/custodian_profile_downloader_service_factory.h"
18 #include "chrome/browser/supervised_user/permission_request_creator.h"
19 #include "chrome/browser/supervised_user/supervised_user_service.h"
20 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
21 #include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
22 #include "chrome/browser/ui/browser_list.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "components/signin/core/browser/fake_profile_oauth2_token_service.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 #if !defined(OS_ANDROID) && !defined(OS_IOS)
47 void OnProfileDownloadedFail(const base::string16
& full_name
) {
48 ASSERT_TRUE(false) << "Profile download should not have succeeded.";
52 // Base class for helper objects that wait for certain events to happen.
53 // This class will ensure that calls to QuitRunLoop() (triggered by a subclass)
54 // are balanced with Wait() calls.
55 class AsyncTestHelper
{
64 // |quit_called_| will be initialized in Reset().
69 EXPECT_FALSE(quit_called_
);
73 // QuitRunLoop() can not be called more than once between calls to Wait().
74 ASSERT_FALSE(quit_called_
);
82 run_loop_
.reset(new base::RunLoop
);
85 scoped_ptr
<base::RunLoop
> run_loop_
;
88 DISALLOW_COPY_AND_ASSIGN(AsyncTestHelper
);
91 class SupervisedUserURLFilterObserver
92 : public AsyncTestHelper
,
93 public SupervisedUserURLFilter::Observer
{
95 SupervisedUserURLFilterObserver() : scoped_observer_(this) {}
96 ~SupervisedUserURLFilterObserver() {}
98 void Init(SupervisedUserURLFilter
* url_filter
) {
99 scoped_observer_
.Add(url_filter
);
102 // SupervisedUserURLFilter::Observer
103 void OnSiteListUpdated() override
{
108 ScopedObserver
<SupervisedUserURLFilter
, SupervisedUserURLFilter::Observer
>
111 DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilterObserver
);
114 class SiteListObserver
: public AsyncTestHelper
{
116 SiteListObserver() {}
117 ~SiteListObserver() {}
119 void Init(SupervisedUserWhitelistService
* service
) {
120 service
->AddSiteListsChangedCallback(base::Bind(
121 &SiteListObserver::OnSiteListsChanged
, base::Unretained(this)));
123 // The initial call to AddSiteListsChangedCallback will call
124 // OnSiteListsChanged(), so we balance it out by calling Wait().
128 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists() {
132 const std::vector
<SupervisedUserSiteList::Site
>& sites() {
137 void OnSiteListsChanged(
138 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists
) {
139 site_lists_
= site_lists
;
141 for (const scoped_refptr
<SupervisedUserSiteList
>& site_list
: site_lists
) {
142 const std::vector
<SupervisedUserSiteList::Site
>& sites
=
144 sites_
.insert(sites_
.end(), sites
.begin(), sites
.end());
150 std::vector
<scoped_refptr
<SupervisedUserSiteList
>> site_lists_
;
151 std::vector
<SupervisedUserSiteList::Site
> sites_
;
153 DISALLOW_COPY_AND_ASSIGN(SiteListObserver
);
156 class AsyncResultHolder
{
158 AsyncResultHolder() : result_(false) {}
159 ~AsyncResultHolder() {}
161 void SetResult(bool result
) {
172 base::RunLoop run_loop_
;
175 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder
);
178 class SupervisedUserServiceTest
: public ::testing::Test
{
180 SupervisedUserServiceTest() {}
182 void SetUp() override
{
183 TestingProfile::Builder builder
;
184 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
185 BuildFakeProfileOAuth2TokenService
);
186 profile_
= builder
.Build();
187 supervised_user_service_
=
188 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
191 void TearDown() override
{ profile_
.reset(); }
193 ~SupervisedUserServiceTest() override
{}
196 void AddURLAccessRequest(const GURL
& url
, AsyncResultHolder
* result_holder
) {
197 supervised_user_service_
->AddURLAccessRequest(
198 url
, base::Bind(&AsyncResultHolder::SetResult
,
199 base::Unretained(result_holder
)));
202 content::TestBrowserThreadBundle thread_bundle_
;
203 scoped_ptr
<TestingProfile
> profile_
;
204 SupervisedUserService
* supervised_user_service_
;
209 TEST_F(SupervisedUserServiceTest
, ChangesIncludedSessionOnChangedSettings
) {
210 supervised_user_service_
->Init();
211 EXPECT_TRUE(supervised_user_service_
->IncludesSyncSessionsType());
212 profile_
->GetPrefs()->SetBoolean(prefs::kRecordHistory
, false);
213 EXPECT_FALSE(supervised_user_service_
->IncludesSyncSessionsType());
216 #if !defined(OS_ANDROID) && !defined(OS_IOS)
217 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
218 // DCHECK is hit when the service is destroyed, this test passed.
219 TEST_F(SupervisedUserServiceTest
, ShutDownCustodianProfileDownloader
) {
220 CustodianProfileDownloaderService
* downloader_service
=
221 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_
.get());
223 // Emulate being logged in, then start to download a profile so a
224 // ProfileDownloader gets created.
225 SigninManagerFactory::GetForProfile(profile_
.get())->
226 SetAuthenticatedAccountInfo("12345", "Logged In");
227 downloader_service
->DownloadProfile(base::Bind(&OnProfileDownloadedFail
));
233 class MockPermissionRequestCreator
: public PermissionRequestCreator
{
235 MockPermissionRequestCreator() : enabled_(false) {}
236 ~MockPermissionRequestCreator() override
{}
238 void set_enabled(bool enabled
) {
242 const std::vector
<GURL
>& requested_urls() const {
243 return requested_urls_
;
246 void AnswerRequest(size_t index
, bool result
) {
247 ASSERT_LT(index
, requested_urls_
.size());
248 callbacks_
[index
].Run(result
);
249 callbacks_
.erase(callbacks_
.begin() + index
);
250 requested_urls_
.erase(requested_urls_
.begin() + index
);
254 // PermissionRequestCreator:
255 bool IsEnabled() const override
{ return enabled_
; }
257 void CreateURLAccessRequest(const GURL
& url_requested
,
258 const SuccessCallback
& callback
) override
{
259 ASSERT_TRUE(enabled_
);
260 requested_urls_
.push_back(url_requested
);
261 callbacks_
.push_back(callback
);
264 void CreateExtensionUpdateRequest(const std::string
& id
,
265 const SuccessCallback
& callback
) override
{
270 std::vector
<GURL
> requested_urls_
;
271 std::vector
<SuccessCallback
> callbacks_
;
273 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator
);
278 TEST_F(SupervisedUserServiceTest
, CreatePermissionRequest
) {
279 GURL
url("http://www.example.com");
281 // Without any permission request creators, it should be disabled, and any
282 // AddURLAccessRequest() calls should fail.
283 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
285 AsyncResultHolder result_holder
;
286 AddURLAccessRequest(url
, &result_holder
);
287 EXPECT_FALSE(result_holder
.GetResult());
290 // Add a disabled permission request creator. This should not change anything.
291 MockPermissionRequestCreator
* creator
= new MockPermissionRequestCreator
;
292 supervised_user_service_
->AddPermissionRequestCreator(
293 make_scoped_ptr(creator
));
295 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
297 AsyncResultHolder result_holder
;
298 AddURLAccessRequest(url
, &result_holder
);
299 EXPECT_FALSE(result_holder
.GetResult());
302 // Enable the permission request creator. This should enable permission
303 // requests and queue them up.
304 creator
->set_enabled(true);
305 EXPECT_TRUE(supervised_user_service_
->AccessRequestsEnabled());
307 AsyncResultHolder result_holder
;
308 AddURLAccessRequest(url
, &result_holder
);
309 ASSERT_EQ(1u, creator
->requested_urls().size());
310 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
312 creator
->AnswerRequest(0, true);
313 EXPECT_TRUE(result_holder
.GetResult());
317 AsyncResultHolder result_holder
;
318 AddURLAccessRequest(url
, &result_holder
);
319 ASSERT_EQ(1u, creator
->requested_urls().size());
320 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
322 creator
->AnswerRequest(0, false);
323 EXPECT_FALSE(result_holder
.GetResult());
326 // Add a second permission request creator.
327 MockPermissionRequestCreator
* creator_2
= new MockPermissionRequestCreator
;
328 creator_2
->set_enabled(true);
329 supervised_user_service_
->AddPermissionRequestCreator(
330 make_scoped_ptr(creator_2
));
333 AsyncResultHolder result_holder
;
334 AddURLAccessRequest(url
, &result_holder
);
335 ASSERT_EQ(1u, creator
->requested_urls().size());
336 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
338 // Make the first creator succeed. This should make the whole thing succeed.
339 creator
->AnswerRequest(0, true);
340 EXPECT_TRUE(result_holder
.GetResult());
344 AsyncResultHolder result_holder
;
345 AddURLAccessRequest(url
, &result_holder
);
346 ASSERT_EQ(1u, creator
->requested_urls().size());
347 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
349 // Make the first creator fail. This should fall back to the second one.
350 creator
->AnswerRequest(0, false);
351 ASSERT_EQ(1u, creator_2
->requested_urls().size());
352 EXPECT_EQ(url
.spec(), creator_2
->requested_urls()[0].spec());
354 // Make the second creator succeed, which will make the whole thing succeed.
355 creator_2
->AnswerRequest(0, true);
356 EXPECT_TRUE(result_holder
.GetResult());
360 #if defined(ENABLE_EXTENSIONS)
361 class SupervisedUserServiceExtensionTestBase
362 : public extensions::ExtensionServiceTestBase
{
364 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised
)
365 : is_supervised_(is_supervised
),
366 channel_(chrome::VersionInfo::CHANNEL_DEV
) {}
367 ~SupervisedUserServiceExtensionTestBase() override
{}
369 void SetUp() override
{
370 ExtensionServiceTestBase::SetUp();
371 ExtensionServiceTestBase::ExtensionServiceInitParams params
=
372 CreateDefaultInitParams();
373 params
.profile_is_supervised
= is_supervised_
;
374 InitializeExtensionService(params
);
375 SupervisedUserService
* service
=
376 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
378 site_list_observer_
.Init(service
->GetWhitelistService());
380 SupervisedUserURLFilter
* url_filter
= service
->GetURLFilterForUIThread();
381 url_filter
->SetBlockingTaskRunnerForTesting(
382 base::ThreadTaskRunnerHandle::Get());
383 url_filter_observer_
.Init(url_filter
);
385 // Wait for the initial update to finish.
386 url_filter_observer_
.Wait();
389 void TearDown() override
{
390 // Flush the message loop, to ensure all posted tasks run.
391 base::RunLoop().RunUntilIdle();
395 scoped_refptr
<extensions::Extension
> MakeThemeExtension() {
396 scoped_ptr
<base::DictionaryValue
> source(new base::DictionaryValue());
397 source
->SetString(extensions::manifest_keys::kName
, "Theme");
398 source
->Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
399 source
->SetString(extensions::manifest_keys::kVersion
, "1.0");
400 extensions::ExtensionBuilder builder
;
401 scoped_refptr
<extensions::Extension
> extension
=
402 builder
.SetManifest(source
.Pass()).Build();
406 scoped_refptr
<extensions::Extension
> MakeExtension(bool by_custodian
) {
407 scoped_ptr
<base::DictionaryValue
> manifest
= extensions::DictionaryBuilder()
408 .Set(extensions::manifest_keys::kName
, "Extension")
409 .Set(extensions::manifest_keys::kVersion
, "1.0")
411 int creation_flags
= extensions::Extension::NO_FLAGS
;
413 creation_flags
|= extensions::Extension::WAS_INSTALLED_BY_CUSTODIAN
;
414 extensions::ExtensionBuilder builder
;
415 scoped_refptr
<extensions::Extension
> extension
=
416 builder
.SetManifest(manifest
.Pass()).AddFlags(creation_flags
).Build();
421 extensions::ScopedCurrentChannel channel_
;
422 SiteListObserver site_list_observer_
;
423 SupervisedUserURLFilterObserver url_filter_observer_
;
426 class SupervisedUserServiceExtensionTestUnsupervised
427 : public SupervisedUserServiceExtensionTestBase
{
429 SupervisedUserServiceExtensionTestUnsupervised()
430 : SupervisedUserServiceExtensionTestBase(false) {}
433 class SupervisedUserServiceExtensionTest
434 : public SupervisedUserServiceExtensionTestBase
{
436 SupervisedUserServiceExtensionTest()
437 : SupervisedUserServiceExtensionTestBase(true) {}
440 TEST_F(SupervisedUserServiceExtensionTest
, ExtensionManagementPolicyProvider
) {
441 SupervisedUserService
* supervised_user_service
=
442 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
443 ASSERT_TRUE(profile_
->IsSupervised());
445 // Check that a supervised user can install and uninstall a theme.
447 scoped_refptr
<extensions::Extension
> theme
= MakeThemeExtension();
449 base::string16 error_1
;
450 EXPECT_TRUE(supervised_user_service
->UserMayLoad(theme
.get(), &error_1
));
451 EXPECT_TRUE(error_1
.empty());
453 base::string16 error_2
;
455 supervised_user_service
->MustRemainInstalled(theme
.get(), &error_2
));
456 EXPECT_TRUE(error_2
.empty());
459 // Now check a different kind of extension; the supervised user should not be
462 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
464 base::string16 error
;
465 EXPECT_FALSE(supervised_user_service
->UserMayLoad(extension
.get(), &error
));
466 EXPECT_FALSE(error
.empty());
470 // Check that a custodian-installed extension may be loaded, but not
472 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(true);
474 base::string16 error_1
;
476 supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
477 EXPECT_TRUE(error_1
.empty());
479 base::string16 error_2
;
481 supervised_user_service
->MustRemainInstalled(extension
.get(),
483 EXPECT_FALSE(error_2
.empty());
487 EXPECT_FALSE(supervised_user_service
->GetDebugPolicyProviderName().empty());
491 TEST_F(SupervisedUserServiceExtensionTest
, NoContentPacks
) {
492 SupervisedUserService
* supervised_user_service
=
493 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
494 SupervisedUserURLFilter
* url_filter
=
495 supervised_user_service
->GetURLFilterForUIThread();
497 // ASSERT_EQ instead of ASSERT_TRUE([...].empty()) so that the error
498 // message contains the size in case of failure.
499 ASSERT_EQ(0u, site_list_observer_
.site_lists().size());
501 GURL
url("http://youtube.com");
502 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
503 url_filter
->GetFilteringBehaviorForURL(url
));
506 TEST_F(SupervisedUserServiceExtensionTest
, InstallContentPacks
) {
507 SupervisedUserService
* supervised_user_service
=
508 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
509 SupervisedUserURLFilter
* url_filter
=
510 supervised_user_service
->GetURLFilterForUIThread();
512 GURL
example_url("http://example.com");
513 GURL
moose_url("http://moose.org");
514 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
515 url_filter
->GetFilteringBehaviorForURL(example_url
));
517 profile_
->GetPrefs()->SetInteger(
518 prefs::kDefaultSupervisedUserFilteringBehavior
,
519 SupervisedUserURLFilter::BLOCK
);
520 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
521 url_filter
->GetFilteringBehaviorForURL(example_url
));
523 profile_
->GetPrefs()->SetInteger(
524 prefs::kDefaultSupervisedUserFilteringBehavior
,
525 SupervisedUserURLFilter::WARN
);
526 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
527 url_filter
->GetFilteringBehaviorForURL(example_url
));
530 base::FilePath test_data_dir
;
531 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
532 SupervisedUserWhitelistService
* whitelist_service
=
533 supervised_user_service
->GetWhitelistService();
534 base::FilePath whitelist_path
=
535 test_data_dir
.AppendASCII("whitelists/content_pack/site_list.json");
536 whitelist_service
->LoadWhitelistForTesting("aaaa", whitelist_path
);
537 site_list_observer_
.Wait();
539 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
540 ASSERT_EQ(3u, site_list_observer_
.sites().size());
541 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), site_list_observer_
.sites()[0].name
);
542 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"),
543 site_list_observer_
.sites()[1].name
);
544 EXPECT_EQ(base::string16(), site_list_observer_
.sites()[2].name
);
546 url_filter_observer_
.Wait();
547 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
548 url_filter
->GetFilteringBehaviorForURL(example_url
));
549 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
550 url_filter
->GetFilteringBehaviorForURL(moose_url
));
552 // Load a second whitelist.
554 test_data_dir
.AppendASCII("whitelists/content_pack_2/site_list.json");
555 whitelist_service
->LoadWhitelistForTesting("bbbb", whitelist_path
);
556 site_list_observer_
.Wait();
558 ASSERT_EQ(2u, site_list_observer_
.site_lists().size());
559 ASSERT_EQ(4u, site_list_observer_
.sites().size());
561 // The site lists might be returned in any order, so we put them into a set.
562 std::set
<std::string
> site_names
;
563 for (const SupervisedUserSiteList::Site
& site
: site_list_observer_
.sites())
564 site_names
.insert(base::UTF16ToUTF8(site
.name
));
565 EXPECT_EQ(1u, site_names
.count("YouTube"));
566 EXPECT_EQ(1u, site_names
.count("Homestar Runner"));
567 EXPECT_EQ(1u, site_names
.count(std::string()));
568 EXPECT_EQ(1u, site_names
.count("Moose"));
570 url_filter_observer_
.Wait();
571 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
572 url_filter
->GetFilteringBehaviorForURL(example_url
));
573 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
574 url_filter
->GetFilteringBehaviorForURL(moose_url
));
576 // Unload the first whitelist.
577 whitelist_service
->UnloadWhitelist("aaaa");
578 site_list_observer_
.Wait();
580 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
581 ASSERT_EQ(1u, site_list_observer_
.sites().size());
582 EXPECT_EQ(base::ASCIIToUTF16("Moose"), site_list_observer_
.sites()[0].name
);
584 url_filter_observer_
.Wait();
585 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
586 url_filter
->GetFilteringBehaviorForURL(example_url
));
587 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
588 url_filter
->GetFilteringBehaviorForURL(moose_url
));
590 #endif // defined(ENABLE_EXTENSIONS)