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 "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/signin/fake_profile_oauth2_token_service.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/signin_manager.h"
27 #include "content/public/test/test_browser_thread_bundle.h"
28 #include "content/public/test/test_utils.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 #if defined(ENABLE_EXTENSIONS)
32 #include "chrome/browser/extensions/extension_service.h"
33 #include "chrome/browser/extensions/extension_service_test_base.h"
34 #include "chrome/browser/extensions/unpacked_installer.h"
35 #include "chrome/common/extensions/features/feature_channel.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/extension_builder.h"
38 #include "extensions/common/manifest_constants.h"
41 using content::MessageLoopRunner
;
45 void OnProfileDownloadedFail(const base::string16
& full_name
) {
46 ASSERT_TRUE(false) << "Profile download should not have succeeded.";
49 // Base class for helper objects that wait for certain events to happen.
50 // This class will ensure that calls to QuitRunLoop() (triggered by a subclass)
51 // are balanced with Wait() calls.
52 class AsyncTestHelper
{
61 // |quit_called_| will be initialized in Reset().
66 EXPECT_FALSE(quit_called_
);
70 // QuitRunLoop() can not be called more than once between calls to Wait().
71 ASSERT_FALSE(quit_called_
);
79 run_loop_
.reset(new base::RunLoop
);
82 scoped_ptr
<base::RunLoop
> run_loop_
;
85 DISALLOW_COPY_AND_ASSIGN(AsyncTestHelper
);
88 class SupervisedUserURLFilterObserver
89 : public AsyncTestHelper
,
90 public SupervisedUserURLFilter::Observer
{
92 SupervisedUserURLFilterObserver() : scoped_observer_(this) {}
93 ~SupervisedUserURLFilterObserver() {}
95 void Init(SupervisedUserURLFilter
* url_filter
) {
96 scoped_observer_
.Add(url_filter
);
99 // SupervisedUserURLFilter::Observer
100 void OnSiteListUpdated() override
{
105 ScopedObserver
<SupervisedUserURLFilter
, SupervisedUserURLFilter::Observer
>
108 DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilterObserver
);
111 class SiteListObserver
: public AsyncTestHelper
{
113 SiteListObserver() {}
114 ~SiteListObserver() {}
116 void Init(SupervisedUserWhitelistService
* service
) {
117 service
->AddSiteListsChangedCallback(base::Bind(
118 &SiteListObserver::OnSiteListsChanged
, base::Unretained(this)));
120 // The initial call to AddSiteListsChangedCallback will call
121 // OnSiteListsChanged(), so we balance it out by calling Wait().
125 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists() {
129 const std::vector
<SupervisedUserSiteList::Site
>& sites() {
134 void OnSiteListsChanged(
135 const std::vector
<scoped_refptr
<SupervisedUserSiteList
>>& site_lists
) {
136 site_lists_
= site_lists
;
138 for (const scoped_refptr
<SupervisedUserSiteList
>& site_list
: site_lists
) {
139 const std::vector
<SupervisedUserSiteList::Site
>& sites
=
141 sites_
.insert(sites_
.end(), sites
.begin(), sites
.end());
147 std::vector
<scoped_refptr
<SupervisedUserSiteList
>> site_lists_
;
148 std::vector
<SupervisedUserSiteList::Site
> sites_
;
150 DISALLOW_COPY_AND_ASSIGN(SiteListObserver
);
153 class AsyncResultHolder
{
155 AsyncResultHolder() : result_(false) {}
156 ~AsyncResultHolder() {}
158 void SetResult(bool result
) {
169 base::RunLoop run_loop_
;
172 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder
);
175 class SupervisedUserServiceTest
: public ::testing::Test
{
177 SupervisedUserServiceTest() {}
179 void SetUp() override
{
180 TestingProfile::Builder builder
;
181 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
182 BuildFakeProfileOAuth2TokenService
);
183 profile_
= builder
.Build();
184 supervised_user_service_
=
185 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
188 void TearDown() override
{ profile_
.reset(); }
190 ~SupervisedUserServiceTest() override
{}
193 void AddURLAccessRequest(const GURL
& url
, AsyncResultHolder
* result_holder
) {
194 supervised_user_service_
->AddURLAccessRequest(
195 url
, base::Bind(&AsyncResultHolder::SetResult
,
196 base::Unretained(result_holder
)));
199 content::TestBrowserThreadBundle thread_bundle_
;
200 scoped_ptr
<TestingProfile
> profile_
;
201 SupervisedUserService
* supervised_user_service_
;
206 TEST_F(SupervisedUserServiceTest
, ChangesIncludedSessionOnChangedSettings
) {
207 supervised_user_service_
->Init();
208 EXPECT_TRUE(supervised_user_service_
->IncludesSyncSessionsType());
209 profile_
->GetPrefs()->SetBoolean(prefs::kRecordHistory
, false);
210 EXPECT_FALSE(supervised_user_service_
->IncludesSyncSessionsType());
213 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
214 // DCHECK is hit when the service is destroyed, this test passed.
215 TEST_F(SupervisedUserServiceTest
, ShutDownCustodianProfileDownloader
) {
216 CustodianProfileDownloaderService
* downloader_service
=
217 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_
.get());
219 // Emulate being logged in, then start to download a profile so a
220 // ProfileDownloader gets created.
221 SigninManagerFactory::GetForProfile(profile_
.get())->
222 SetAuthenticatedUsername("Logged In");
223 downloader_service
->DownloadProfile(base::Bind(&OnProfileDownloadedFail
));
228 class MockPermissionRequestCreator
: public PermissionRequestCreator
{
230 MockPermissionRequestCreator() : enabled_(false) {}
231 ~MockPermissionRequestCreator() override
{}
233 void set_enabled(bool enabled
) {
237 const std::vector
<GURL
>& requested_urls() const {
238 return requested_urls_
;
241 void AnswerRequest(size_t index
, bool result
) {
242 ASSERT_LT(index
, requested_urls_
.size());
243 callbacks_
[index
].Run(result
);
244 callbacks_
.erase(callbacks_
.begin() + index
);
245 requested_urls_
.erase(requested_urls_
.begin() + index
);
249 // PermissionRequestCreator:
250 bool IsEnabled() const override
{ return enabled_
; }
252 void CreateURLAccessRequest(const GURL
& url_requested
,
253 const SuccessCallback
& callback
) override
{
254 ASSERT_TRUE(enabled_
);
255 requested_urls_
.push_back(url_requested
);
256 callbacks_
.push_back(callback
);
259 void CreateExtensionUpdateRequest(const std::string
& id
,
260 const SuccessCallback
& callback
) override
{
265 std::vector
<GURL
> requested_urls_
;
266 std::vector
<SuccessCallback
> callbacks_
;
268 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator
);
273 TEST_F(SupervisedUserServiceTest
, CreatePermissionRequest
) {
274 GURL
url("http://www.example.com");
276 // Without any permission request creators, it should be disabled, and any
277 // AddURLAccessRequest() calls should fail.
278 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
280 AsyncResultHolder result_holder
;
281 AddURLAccessRequest(url
, &result_holder
);
282 EXPECT_FALSE(result_holder
.GetResult());
285 // Add a disabled permission request creator. This should not change anything.
286 MockPermissionRequestCreator
* creator
= new MockPermissionRequestCreator
;
287 supervised_user_service_
->AddPermissionRequestCreator(
288 make_scoped_ptr(creator
));
290 EXPECT_FALSE(supervised_user_service_
->AccessRequestsEnabled());
292 AsyncResultHolder result_holder
;
293 AddURLAccessRequest(url
, &result_holder
);
294 EXPECT_FALSE(result_holder
.GetResult());
297 // Enable the permission request creator. This should enable permission
298 // requests and queue them up.
299 creator
->set_enabled(true);
300 EXPECT_TRUE(supervised_user_service_
->AccessRequestsEnabled());
302 AsyncResultHolder result_holder
;
303 AddURLAccessRequest(url
, &result_holder
);
304 ASSERT_EQ(1u, creator
->requested_urls().size());
305 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
307 creator
->AnswerRequest(0, true);
308 EXPECT_TRUE(result_holder
.GetResult());
312 AsyncResultHolder result_holder
;
313 AddURLAccessRequest(url
, &result_holder
);
314 ASSERT_EQ(1u, creator
->requested_urls().size());
315 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
317 creator
->AnswerRequest(0, false);
318 EXPECT_FALSE(result_holder
.GetResult());
321 // Add a second permission request creator.
322 MockPermissionRequestCreator
* creator_2
= new MockPermissionRequestCreator
;
323 creator_2
->set_enabled(true);
324 supervised_user_service_
->AddPermissionRequestCreator(
325 make_scoped_ptr(creator_2
));
328 AsyncResultHolder result_holder
;
329 AddURLAccessRequest(url
, &result_holder
);
330 ASSERT_EQ(1u, creator
->requested_urls().size());
331 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
333 // Make the first creator succeed. This should make the whole thing succeed.
334 creator
->AnswerRequest(0, true);
335 EXPECT_TRUE(result_holder
.GetResult());
339 AsyncResultHolder result_holder
;
340 AddURLAccessRequest(url
, &result_holder
);
341 ASSERT_EQ(1u, creator
->requested_urls().size());
342 EXPECT_EQ(url
.spec(), creator
->requested_urls()[0].spec());
344 // Make the first creator fail. This should fall back to the second one.
345 creator
->AnswerRequest(0, false);
346 ASSERT_EQ(1u, creator_2
->requested_urls().size());
347 EXPECT_EQ(url
.spec(), creator_2
->requested_urls()[0].spec());
349 // Make the second creator succeed, which will make the whole thing succeed.
350 creator_2
->AnswerRequest(0, true);
351 EXPECT_TRUE(result_holder
.GetResult());
355 #if defined(ENABLE_EXTENSIONS)
356 class SupervisedUserServiceExtensionTestBase
357 : public extensions::ExtensionServiceTestBase
{
359 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised
)
360 : is_supervised_(is_supervised
),
361 channel_(chrome::VersionInfo::CHANNEL_DEV
) {}
362 ~SupervisedUserServiceExtensionTestBase() override
{}
364 void SetUp() override
{
365 ExtensionServiceTestBase::SetUp();
366 ExtensionServiceTestBase::ExtensionServiceInitParams params
=
367 CreateDefaultInitParams();
368 params
.profile_is_supervised
= is_supervised_
;
369 InitializeExtensionService(params
);
370 SupervisedUserService
* service
=
371 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
373 site_list_observer_
.Init(service
->GetWhitelistService());
375 SupervisedUserURLFilter
* url_filter
= service
->GetURLFilterForUIThread();
376 url_filter
->SetBlockingTaskRunnerForTesting(
377 base::MessageLoopProxy::current());
378 url_filter_observer_
.Init(url_filter
);
380 // Wait for the initial update to finish.
381 url_filter_observer_
.Wait();
384 void TearDown() override
{
385 // Flush the message loop, to ensure all posted tasks run.
386 base::RunLoop().RunUntilIdle();
390 scoped_refptr
<extensions::Extension
> MakeThemeExtension() {
391 scoped_ptr
<base::DictionaryValue
> source(new base::DictionaryValue());
392 source
->SetString(extensions::manifest_keys::kName
, "Theme");
393 source
->Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
394 source
->SetString(extensions::manifest_keys::kVersion
, "1.0");
395 extensions::ExtensionBuilder builder
;
396 scoped_refptr
<extensions::Extension
> extension
=
397 builder
.SetManifest(source
.Pass()).Build();
401 scoped_refptr
<extensions::Extension
> MakeExtension(bool by_custodian
) {
402 scoped_ptr
<base::DictionaryValue
> manifest
= extensions::DictionaryBuilder()
403 .Set(extensions::manifest_keys::kName
, "Extension")
404 .Set(extensions::manifest_keys::kVersion
, "1.0")
406 int creation_flags
= extensions::Extension::NO_FLAGS
;
408 creation_flags
|= extensions::Extension::WAS_INSTALLED_BY_CUSTODIAN
;
409 extensions::ExtensionBuilder builder
;
410 scoped_refptr
<extensions::Extension
> extension
=
411 builder
.SetManifest(manifest
.Pass()).AddFlags(creation_flags
).Build();
416 extensions::ScopedCurrentChannel channel_
;
417 SiteListObserver site_list_observer_
;
418 SupervisedUserURLFilterObserver url_filter_observer_
;
421 class SupervisedUserServiceExtensionTestUnsupervised
422 : public SupervisedUserServiceExtensionTestBase
{
424 SupervisedUserServiceExtensionTestUnsupervised()
425 : SupervisedUserServiceExtensionTestBase(false) {}
428 class SupervisedUserServiceExtensionTest
429 : public SupervisedUserServiceExtensionTestBase
{
431 SupervisedUserServiceExtensionTest()
432 : SupervisedUserServiceExtensionTestBase(true) {}
435 TEST_F(SupervisedUserServiceExtensionTest
, ExtensionManagementPolicyProvider
) {
436 SupervisedUserService
* supervised_user_service
=
437 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
438 ASSERT_TRUE(profile_
->IsSupervised());
440 // Check that a supervised user can install and uninstall a theme.
442 scoped_refptr
<extensions::Extension
> theme
= MakeThemeExtension();
444 base::string16 error_1
;
445 EXPECT_TRUE(supervised_user_service
->UserMayLoad(theme
.get(), &error_1
));
446 EXPECT_TRUE(error_1
.empty());
448 base::string16 error_2
;
450 supervised_user_service
->MustRemainInstalled(theme
.get(), &error_2
));
451 EXPECT_TRUE(error_2
.empty());
454 // Now check a different kind of extension; the supervised user should not be
457 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
459 base::string16 error
;
460 EXPECT_FALSE(supervised_user_service
->UserMayLoad(extension
.get(), &error
));
461 EXPECT_FALSE(error
.empty());
465 // Check that a custodian-installed extension may be loaded, but not
467 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(true);
469 base::string16 error_1
;
471 supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
472 EXPECT_TRUE(error_1
.empty());
474 base::string16 error_2
;
476 supervised_user_service
->MustRemainInstalled(extension
.get(),
478 EXPECT_FALSE(error_2
.empty());
482 EXPECT_FALSE(supervised_user_service
->GetDebugPolicyProviderName().empty());
486 TEST_F(SupervisedUserServiceExtensionTest
, NoContentPacks
) {
487 SupervisedUserService
* supervised_user_service
=
488 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
489 SupervisedUserURLFilter
* url_filter
=
490 supervised_user_service
->GetURLFilterForUIThread();
492 // ASSERT_EQ instead of ASSERT_TRUE([...].empty()) so that the error
493 // message contains the size in case of failure.
494 ASSERT_EQ(0u, site_list_observer_
.site_lists().size());
496 GURL
url("http://youtube.com");
497 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
498 url_filter
->GetFilteringBehaviorForURL(url
));
501 TEST_F(SupervisedUserServiceExtensionTest
, InstallContentPacks
) {
502 SupervisedUserService
* supervised_user_service
=
503 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
504 SupervisedUserURLFilter
* url_filter
=
505 supervised_user_service
->GetURLFilterForUIThread();
507 GURL
example_url("http://example.com");
508 GURL
moose_url("http://moose.org");
509 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
510 url_filter
->GetFilteringBehaviorForURL(example_url
));
512 profile_
->GetPrefs()->SetInteger(
513 prefs::kDefaultSupervisedUserFilteringBehavior
,
514 SupervisedUserURLFilter::BLOCK
);
515 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
516 url_filter
->GetFilteringBehaviorForURL(example_url
));
518 profile_
->GetPrefs()->SetInteger(
519 prefs::kDefaultSupervisedUserFilteringBehavior
,
520 SupervisedUserURLFilter::WARN
);
521 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
522 url_filter
->GetFilteringBehaviorForURL(example_url
));
525 base::FilePath test_data_dir
;
526 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
527 SupervisedUserWhitelistService
* whitelist_service
=
528 supervised_user_service
->GetWhitelistService();
529 base::FilePath whitelist_path
=
530 test_data_dir
.AppendASCII("whitelists/content_pack/site_list.json");
531 whitelist_service
->LoadWhitelistForTesting("aaaa", whitelist_path
);
532 site_list_observer_
.Wait();
534 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
535 ASSERT_EQ(3u, site_list_observer_
.sites().size());
536 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), site_list_observer_
.sites()[0].name
);
537 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"),
538 site_list_observer_
.sites()[1].name
);
539 EXPECT_EQ(base::string16(), site_list_observer_
.sites()[2].name
);
541 url_filter_observer_
.Wait();
542 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
543 url_filter
->GetFilteringBehaviorForURL(example_url
));
544 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
545 url_filter
->GetFilteringBehaviorForURL(moose_url
));
547 // Load a second whitelist.
549 test_data_dir
.AppendASCII("whitelists/content_pack_2/site_list.json");
550 whitelist_service
->LoadWhitelistForTesting("bbbb", whitelist_path
);
551 site_list_observer_
.Wait();
553 ASSERT_EQ(2u, site_list_observer_
.site_lists().size());
554 ASSERT_EQ(4u, site_list_observer_
.sites().size());
556 // The site lists might be returned in any order, so we put them into a set.
557 std::set
<std::string
> site_names
;
558 for (const SupervisedUserSiteList::Site
& site
: site_list_observer_
.sites())
559 site_names
.insert(base::UTF16ToUTF8(site
.name
));
560 EXPECT_EQ(1u, site_names
.count("YouTube"));
561 EXPECT_EQ(1u, site_names
.count("Homestar Runner"));
562 EXPECT_EQ(1u, site_names
.count(std::string()));
563 EXPECT_EQ(1u, site_names
.count("Moose"));
565 url_filter_observer_
.Wait();
566 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
567 url_filter
->GetFilteringBehaviorForURL(example_url
));
568 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
569 url_filter
->GetFilteringBehaviorForURL(moose_url
));
571 // Unload the first whitelist.
572 whitelist_service
->UnloadWhitelist("aaaa");
573 site_list_observer_
.Wait();
575 ASSERT_EQ(1u, site_list_observer_
.site_lists().size());
576 ASSERT_EQ(1u, site_list_observer_
.sites().size());
577 EXPECT_EQ(base::ASCIIToUTF16("Moose"), site_list_observer_
.sites()[0].name
);
579 url_filter_observer_
.Wait();
580 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
581 url_filter
->GetFilteringBehaviorForURL(example_url
));
582 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
583 url_filter
->GetFilteringBehaviorForURL(moose_url
));
585 #endif // defined(ENABLE_EXTENSIONS)