Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / supervised_user / supervised_user_service_unittest.cc
blob96b477356384d33051b0b8029b399b60bcf81f19
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"
40 #endif
42 using content::MessageLoopRunner;
44 namespace {
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.";
50 #endif
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 {
56 public:
57 void Wait() {
58 run_loop_->Run();
59 Reset();
62 protected:
63 AsyncTestHelper() {
64 // |quit_called_| will be initialized in Reset().
65 Reset();
68 ~AsyncTestHelper() {
69 EXPECT_FALSE(quit_called_);
72 void QuitRunLoop() {
73 // QuitRunLoop() can not be called more than once between calls to Wait().
74 ASSERT_FALSE(quit_called_);
75 quit_called_ = true;
76 run_loop_->Quit();
79 private:
80 void Reset() {
81 quit_called_ = false;
82 run_loop_.reset(new base::RunLoop);
85 scoped_ptr<base::RunLoop> run_loop_;
86 bool quit_called_;
88 DISALLOW_COPY_AND_ASSIGN(AsyncTestHelper);
91 class SupervisedUserURLFilterObserver
92 : public AsyncTestHelper,
93 public SupervisedUserURLFilter::Observer {
94 public:
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 {
104 QuitRunLoop();
107 private:
108 ScopedObserver<SupervisedUserURLFilter, SupervisedUserURLFilter::Observer>
109 scoped_observer_;
111 DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilterObserver);
114 class SiteListObserver : public AsyncTestHelper {
115 public:
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().
125 Wait();
128 const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists() {
129 return site_lists_;
132 const std::vector<SupervisedUserSiteList::Site>& sites() {
133 return sites_;
136 private:
137 void OnSiteListsChanged(
138 const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists) {
139 site_lists_ = site_lists;
140 sites_.clear();
141 for (const scoped_refptr<SupervisedUserSiteList>& site_list : site_lists) {
142 const std::vector<SupervisedUserSiteList::Site>& sites =
143 site_list->sites();
144 sites_.insert(sites_.end(), sites.begin(), sites.end());
147 QuitRunLoop();
150 std::vector<scoped_refptr<SupervisedUserSiteList>> site_lists_;
151 std::vector<SupervisedUserSiteList::Site> sites_;
153 DISALLOW_COPY_AND_ASSIGN(SiteListObserver);
156 class AsyncResultHolder {
157 public:
158 AsyncResultHolder() : result_(false) {}
159 ~AsyncResultHolder() {}
161 void SetResult(bool result) {
162 result_ = result;
163 run_loop_.Quit();
166 bool GetResult() {
167 run_loop_.Run();
168 return result_;
171 private:
172 base::RunLoop run_loop_;
173 bool result_;
175 DISALLOW_COPY_AND_ASSIGN(AsyncResultHolder);
178 class SupervisedUserServiceTest : public ::testing::Test {
179 public:
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 {}
195 protected:
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_;
207 } // namespace
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));
229 #endif
231 namespace {
233 class MockPermissionRequestCreator : public PermissionRequestCreator {
234 public:
235 MockPermissionRequestCreator() : enabled_(false) {}
236 ~MockPermissionRequestCreator() override {}
238 void set_enabled(bool enabled) {
239 enabled_ = 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);
253 private:
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 {
266 FAIL();
269 bool enabled_;
270 std::vector<GURL> requested_urls_;
271 std::vector<SuccessCallback> callbacks_;
273 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
276 } // namespace
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 {
363 public:
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());
377 service->Init();
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();
394 protected:
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();
403 return extension;
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")
410 .Build();
411 int creation_flags = extensions::Extension::NO_FLAGS;
412 if (by_custodian)
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();
417 return extension;
420 bool is_supervised_;
421 extensions::ScopedCurrentChannel channel_;
422 SiteListObserver site_list_observer_;
423 SupervisedUserURLFilterObserver url_filter_observer_;
426 class SupervisedUserServiceExtensionTestUnsupervised
427 : public SupervisedUserServiceExtensionTestBase {
428 public:
429 SupervisedUserServiceExtensionTestUnsupervised()
430 : SupervisedUserServiceExtensionTestBase(false) {}
433 class SupervisedUserServiceExtensionTest
434 : public SupervisedUserServiceExtensionTestBase {
435 public:
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;
454 EXPECT_FALSE(
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
460 // able to load it.
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
471 // uninstalled.
472 scoped_refptr<extensions::Extension> extension = MakeExtension(true);
474 base::string16 error_1;
475 EXPECT_TRUE(
476 supervised_user_service->UserMayLoad(extension.get(), &error_1));
477 EXPECT_TRUE(error_1.empty());
479 base::string16 error_2;
480 EXPECT_TRUE(
481 supervised_user_service->MustRemainInstalled(extension.get(),
482 &error_2));
483 EXPECT_FALSE(error_2.empty());
486 #ifndef NDEBUG
487 EXPECT_FALSE(supervised_user_service->GetDebugPolicyProviderName().empty());
488 #endif
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));
529 // Load a whitelist.
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.
553 whitelist_path =
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)