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/path_service.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/prefs/scoped_user_pref_update.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_service_test_base.h"
12 #include "chrome/browser/extensions/unpacked_installer.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
15 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
16 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
17 #include "chrome/browser/supervised_user/custodian_profile_downloader_service.h"
18 #include "chrome/browser/supervised_user/custodian_profile_downloader_service_factory.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/ui/browser_list.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/extensions/features/feature_channel.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "content/public/test/test_utils.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/common/extension_builder.h"
30 #include "extensions/common/manifest_constants.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 using content::MessageLoopRunner
;
37 void OnProfileDownloadedFail(const base::string16
& full_name
) {
38 ASSERT_TRUE(false) << "Profile download should not have succeeded.";
41 class SupervisedUserURLFilterObserver
:
42 public SupervisedUserURLFilter::Observer
{
44 explicit SupervisedUserURLFilterObserver(SupervisedUserURLFilter
* url_filter
)
45 : url_filter_(url_filter
) {
47 url_filter_
->AddObserver(this);
50 ~SupervisedUserURLFilterObserver() {
51 url_filter_
->RemoveObserver(this);
55 message_loop_runner_
->Run();
59 // SupervisedUserURLFilter::Observer
60 virtual void OnSiteListUpdated() OVERRIDE
{
61 message_loop_runner_
->Quit();
66 message_loop_runner_
= new MessageLoopRunner
;
69 SupervisedUserURLFilter
* url_filter_
;
70 scoped_refptr
<MessageLoopRunner
> message_loop_runner_
;
73 class SupervisedUserServiceTest
: public ::testing::Test
{
75 SupervisedUserServiceTest() {}
77 virtual void SetUp() OVERRIDE
{
78 TestingProfile::Builder builder
;
79 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
80 BuildFakeProfileOAuth2TokenService
);
81 profile_
= builder
.Build();
82 supervised_user_service_
=
83 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
86 virtual void TearDown() OVERRIDE
{
90 virtual ~SupervisedUserServiceTest() {}
93 content::TestBrowserThreadBundle thread_bundle_
;
94 scoped_ptr
<TestingProfile
> profile_
;
95 SupervisedUserService
* supervised_user_service_
;
100 TEST_F(SupervisedUserServiceTest
, GetManualExceptionsForHost
) {
101 GURL
kExampleFooURL("http://www.example.com/foo");
102 GURL
kExampleBarURL("http://www.example.com/bar");
103 GURL
kExampleFooNoWWWURL("http://example.com/foo");
104 GURL
kBlurpURL("http://blurp.net/bla");
105 GURL
kMooseURL("http://moose.org/baz");
107 DictionaryPrefUpdate
update(profile_
->GetPrefs(),
108 prefs::kSupervisedUserManualURLs
);
109 base::DictionaryValue
* dict
= update
.Get();
110 dict
->SetBooleanWithoutPathExpansion(kExampleFooURL
.spec(), true);
111 dict
->SetBooleanWithoutPathExpansion(kExampleBarURL
.spec(), false);
112 dict
->SetBooleanWithoutPathExpansion(kExampleFooNoWWWURL
.spec(), true);
113 dict
->SetBooleanWithoutPathExpansion(kBlurpURL
.spec(), true);
116 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
117 supervised_user_service_
->GetManualBehaviorForURL(kExampleFooURL
));
118 EXPECT_EQ(SupervisedUserService::MANUAL_BLOCK
,
119 supervised_user_service_
->GetManualBehaviorForURL(kExampleBarURL
));
120 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
121 supervised_user_service_
->GetManualBehaviorForURL(
122 kExampleFooNoWWWURL
));
123 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
124 supervised_user_service_
->GetManualBehaviorForURL(kBlurpURL
));
125 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
126 supervised_user_service_
->GetManualBehaviorForURL(kMooseURL
));
127 std::vector
<GURL
> exceptions
;
128 supervised_user_service_
->GetManualExceptionsForHost("www.example.com",
130 ASSERT_EQ(2u, exceptions
.size());
131 EXPECT_EQ(kExampleBarURL
, exceptions
[0]);
132 EXPECT_EQ(kExampleFooURL
, exceptions
[1]);
135 DictionaryPrefUpdate
update(profile_
->GetPrefs(),
136 prefs::kSupervisedUserManualURLs
);
137 base::DictionaryValue
* dict
= update
.Get();
138 for (std::vector
<GURL
>::iterator it
= exceptions
.begin();
139 it
!= exceptions
.end(); ++it
) {
140 dict
->RemoveWithoutPathExpansion(it
->spec(), NULL
);
144 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
145 supervised_user_service_
->GetManualBehaviorForURL(kExampleFooURL
));
146 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
147 supervised_user_service_
->GetManualBehaviorForURL(kExampleBarURL
));
148 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
149 supervised_user_service_
->GetManualBehaviorForURL(
150 kExampleFooNoWWWURL
));
151 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW
,
152 supervised_user_service_
->GetManualBehaviorForURL(kBlurpURL
));
153 EXPECT_EQ(SupervisedUserService::MANUAL_NONE
,
154 supervised_user_service_
->GetManualBehaviorForURL(kMooseURL
));
157 // Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no
158 // DCHECK is hit when the service is destroyed, this test passed.
159 TEST_F(SupervisedUserServiceTest
, ShutDownCustodianProfileDownloader
) {
160 CustodianProfileDownloaderService
* downloader_service
=
161 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_
.get());
163 // Emulate being logged in, then start to download a profile so a
164 // ProfileDownloader gets created.
165 profile_
->GetPrefs()->SetString(prefs::kGoogleServicesUsername
, "Logged In");
166 downloader_service
->DownloadProfile(base::Bind(&OnProfileDownloadedFail
));
169 #if !defined(OS_ANDROID)
170 class SupervisedUserServiceExtensionTestBase
171 : public extensions::ExtensionServiceTestBase
{
173 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised
)
174 : is_supervised_(is_supervised
),
175 channel_(chrome::VersionInfo::CHANNEL_DEV
) {}
176 virtual ~SupervisedUserServiceExtensionTestBase() {}
178 virtual void SetUp() OVERRIDE
{
179 ExtensionServiceTestBase::SetUp();
180 ExtensionServiceTestBase::ExtensionServiceInitParams params
=
181 CreateDefaultInitParams();
182 params
.profile_is_supervised
= is_supervised_
;
183 InitializeExtensionService(params
);
184 SupervisedUserServiceFactory::GetForProfile(profile_
.get())->Init();
188 ScopedVector
<SupervisedUserSiteList
> GetActiveSiteLists(
189 SupervisedUserService
* supervised_user_service
) {
190 return supervised_user_service
->GetActiveSiteLists();
193 scoped_refptr
<extensions::Extension
> MakeThemeExtension() {
194 scoped_ptr
<base::DictionaryValue
> source(new base::DictionaryValue());
195 source
->SetString(extensions::manifest_keys::kName
, "Theme");
196 source
->Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
197 source
->SetString(extensions::manifest_keys::kVersion
, "1.0");
198 extensions::ExtensionBuilder builder
;
199 scoped_refptr
<extensions::Extension
> extension
=
200 builder
.SetManifest(source
.Pass()).Build();
204 scoped_refptr
<extensions::Extension
> MakeExtension(bool by_custodian
) {
205 scoped_ptr
<base::DictionaryValue
> manifest
= extensions::DictionaryBuilder()
206 .Set(extensions::manifest_keys::kName
, "Extension")
207 .Set(extensions::manifest_keys::kVersion
, "1.0")
209 int creation_flags
= extensions::Extension::NO_FLAGS
;
211 creation_flags
|= extensions::Extension::WAS_INSTALLED_BY_CUSTODIAN
;
212 extensions::ExtensionBuilder builder
;
213 scoped_refptr
<extensions::Extension
> extension
=
214 builder
.SetManifest(manifest
.Pass()).AddFlags(creation_flags
).Build();
219 extensions::ScopedCurrentChannel channel_
;
222 class SupervisedUserServiceExtensionTestUnsupervised
223 : public SupervisedUserServiceExtensionTestBase
{
225 SupervisedUserServiceExtensionTestUnsupervised()
226 : SupervisedUserServiceExtensionTestBase(false) {}
229 class SupervisedUserServiceExtensionTest
230 : public SupervisedUserServiceExtensionTestBase
{
232 SupervisedUserServiceExtensionTest()
233 : SupervisedUserServiceExtensionTestBase(true) {}
236 TEST_F(SupervisedUserServiceExtensionTestUnsupervised
,
237 ExtensionManagementPolicyProvider
) {
238 SupervisedUserService
* supervised_user_service
=
239 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
240 EXPECT_FALSE(profile_
->IsSupervised());
242 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
243 base::string16 error_1
;
244 EXPECT_TRUE(supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
245 EXPECT_EQ(base::string16(), error_1
);
247 base::string16 error_2
;
249 supervised_user_service
->UserMayModifySettings(extension
.get(),
251 EXPECT_EQ(base::string16(), error_2
);
254 TEST_F(SupervisedUserServiceExtensionTest
, ExtensionManagementPolicyProvider
) {
255 SupervisedUserService
* supervised_user_service
=
256 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
257 SupervisedUserURLFilterObserver
observer(
258 supervised_user_service
->GetURLFilterForUIThread());
259 ASSERT_TRUE(profile_
->IsSupervised());
260 // Wait for the initial update to finish (otherwise we'll get leaks).
263 // Check that a supervised user can install a theme.
264 scoped_refptr
<extensions::Extension
> theme
= MakeThemeExtension();
265 base::string16 error_1
;
266 EXPECT_TRUE(supervised_user_service
->UserMayLoad(theme
.get(), &error_1
));
267 EXPECT_TRUE(error_1
.empty());
269 supervised_user_service
->UserMayModifySettings(theme
.get(), &error_1
));
270 EXPECT_TRUE(error_1
.empty());
272 // Now check a different kind of extension.
273 scoped_refptr
<extensions::Extension
> extension
= MakeExtension(false);
274 EXPECT_FALSE(supervised_user_service
->UserMayLoad(extension
.get(), &error_1
));
275 EXPECT_FALSE(error_1
.empty());
277 base::string16 error_2
;
278 EXPECT_FALSE(supervised_user_service
->UserMayModifySettings(extension
.get(),
280 EXPECT_FALSE(error_2
.empty());
282 // Check that an extension that was installed by the custodian may be loaded.
283 base::string16 error_3
;
284 scoped_refptr
<extensions::Extension
> extension_2
= MakeExtension(true);
285 EXPECT_TRUE(supervised_user_service
->UserMayLoad(extension_2
.get(),
287 EXPECT_TRUE(error_3
.empty());
289 // The supervised user should still not be able to uninstall or disable the
291 base::string16 error_4
;
292 EXPECT_FALSE(supervised_user_service
->UserMayModifySettings(extension_2
.get(),
294 EXPECT_FALSE(error_4
.empty());
297 EXPECT_FALSE(supervised_user_service
->GetDebugPolicyProviderName().empty());
301 TEST_F(SupervisedUserServiceExtensionTest
, NoContentPacks
) {
302 SupervisedUserService
* supervised_user_service
=
303 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
304 SupervisedUserURLFilter
* url_filter
=
305 supervised_user_service
->GetURLFilterForUIThread();
307 GURL
url("http://youtube.com");
308 ScopedVector
<SupervisedUserSiteList
> site_lists
=
309 GetActiveSiteLists(supervised_user_service
);
310 ASSERT_EQ(0u, site_lists
.size());
311 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
312 url_filter
->GetFilteringBehaviorForURL(url
));
315 TEST_F(SupervisedUserServiceExtensionTest
, InstallContentPacks
) {
316 SupervisedUserService
* supervised_user_service
=
317 SupervisedUserServiceFactory::GetForProfile(profile_
.get());
318 SupervisedUserURLFilter
* url_filter
=
319 supervised_user_service
->GetURLFilterForUIThread();
320 SupervisedUserURLFilterObserver
observer(url_filter
);
323 GURL
example_url("http://example.com");
324 GURL
moose_url("http://moose.org");
325 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
326 url_filter
->GetFilteringBehaviorForURL(example_url
));
328 profile_
->GetPrefs()->SetInteger(
329 prefs::kDefaultSupervisedUserFilteringBehavior
,
330 SupervisedUserURLFilter::BLOCK
);
331 EXPECT_EQ(SupervisedUserURLFilter::BLOCK
,
332 url_filter
->GetFilteringBehaviorForURL(example_url
));
334 profile_
->GetPrefs()->SetInteger(
335 prefs::kDefaultSupervisedUserFilteringBehavior
,
336 SupervisedUserURLFilter::WARN
);
337 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
338 url_filter
->GetFilteringBehaviorForURL(example_url
));
340 supervised_user_service
->set_elevated_for_testing(true);
342 // Load a content pack.
343 scoped_refptr
<extensions::UnpackedInstaller
> installer(
344 extensions::UnpackedInstaller::Create(service_
));
345 installer
->set_prompt_for_plugins(false);
346 base::FilePath test_data_dir
;
347 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
348 base::FilePath extension_path
=
349 test_data_dir
.AppendASCII("extensions/supervised_user/content_pack");
350 content::WindowedNotificationObserver
extension_load_observer(
351 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
,
352 content::Source
<Profile
>(profile_
.get()));
353 installer
->Load(extension_path
);
354 extension_load_observer
.Wait();
356 content::Details
<extensions::Extension
> details
=
357 extension_load_observer
.details();
358 scoped_refptr
<extensions::Extension
> extension
=
359 make_scoped_refptr(details
.ptr());
360 ASSERT_TRUE(extension
.get());
362 ScopedVector
<SupervisedUserSiteList
> site_lists
=
363 GetActiveSiteLists(supervised_user_service
);
364 ASSERT_EQ(1u, site_lists
.size());
365 std::vector
<SupervisedUserSiteList::Site
> sites
;
366 site_lists
[0]->GetSites(&sites
);
367 ASSERT_EQ(3u, sites
.size());
368 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), sites
[0].name
);
369 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"), sites
[1].name
);
370 EXPECT_EQ(base::string16(), sites
[2].name
);
372 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
373 url_filter
->GetFilteringBehaviorForURL(example_url
));
374 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
375 url_filter
->GetFilteringBehaviorForURL(moose_url
));
377 // Load a second content pack.
378 installer
= extensions::UnpackedInstaller::Create(service_
);
380 test_data_dir
.AppendASCII("extensions/supervised_user/content_pack_2");
381 installer
->Load(extension_path
);
384 site_lists
= GetActiveSiteLists(supervised_user_service
);
385 ASSERT_EQ(2u, site_lists
.size());
387 site_lists
[0]->GetSites(&sites
);
388 site_lists
[1]->GetSites(&sites
);
389 ASSERT_EQ(4u, sites
.size());
390 // The site lists might be returned in any order, so we put them into a set.
391 std::set
<std::string
> site_names
;
392 for (std::vector
<SupervisedUserSiteList::Site
>::const_iterator it
=
393 sites
.begin(); it
!= sites
.end(); ++it
) {
394 site_names
.insert(base::UTF16ToUTF8(it
->name
));
396 EXPECT_TRUE(site_names
.count("YouTube") == 1u);
397 EXPECT_TRUE(site_names
.count("Homestar Runner") == 1u);
398 EXPECT_TRUE(site_names
.count(std::string()) == 1u);
399 EXPECT_TRUE(site_names
.count("Moose") == 1u);
401 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
402 url_filter
->GetFilteringBehaviorForURL(example_url
));
403 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
404 url_filter
->GetFilteringBehaviorForURL(moose_url
));
406 // Disable the first content pack.
407 service_
->DisableExtension(extension
->id(),
408 extensions::Extension::DISABLE_USER_ACTION
);
411 site_lists
= GetActiveSiteLists(supervised_user_service
);
412 ASSERT_EQ(1u, site_lists
.size());
414 site_lists
[0]->GetSites(&sites
);
415 ASSERT_EQ(1u, sites
.size());
416 EXPECT_EQ(base::ASCIIToUTF16("Moose"), sites
[0].name
);
418 EXPECT_EQ(SupervisedUserURLFilter::WARN
,
419 url_filter
->GetFilteringBehaviorForURL(example_url
));
420 EXPECT_EQ(SupervisedUserURLFilter::ALLOW
,
421 url_filter
->GetFilteringBehaviorForURL(moose_url
));
423 #endif // !defined(OS_ANDROID)