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. 4 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" 32 33using content::MessageLoopRunner; 34 35namespace { 36 37void OnProfileDownloadedFail(const base::string16& full_name) { 38 ASSERT_TRUE(false) << "Profile download should not have succeeded."; 39} 40 41class SupervisedUserURLFilterObserver : 42 public SupervisedUserURLFilter::Observer { 43 public: 44 explicit SupervisedUserURLFilterObserver(SupervisedUserURLFilter* url_filter) 45 : url_filter_(url_filter) { 46 Reset(); 47 url_filter_->AddObserver(this); 48 } 49 50 ~SupervisedUserURLFilterObserver() { 51 url_filter_->RemoveObserver(this); 52 } 53 54 void Wait() { 55 message_loop_runner_->Run(); 56 Reset(); 57 } 58 59 // SupervisedUserURLFilter::Observer 60 virtual void OnSiteListUpdated() OVERRIDE { 61 message_loop_runner_->Quit(); 62 } 63 64 private: 65 void Reset() { 66 message_loop_runner_ = new MessageLoopRunner; 67 } 68 69 SupervisedUserURLFilter* url_filter_; 70 scoped_refptr<MessageLoopRunner> message_loop_runner_; 71}; 72 73class SupervisedUserServiceTest : public ::testing::Test { 74 public: 75 SupervisedUserServiceTest() {} 76 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()); 84 } 85 86 virtual void TearDown() OVERRIDE { 87 profile_.reset(); 88 } 89 90 virtual ~SupervisedUserServiceTest() {} 91 92 protected: 93 content::TestBrowserThreadBundle thread_bundle_; 94 scoped_ptr<TestingProfile> profile_; 95 SupervisedUserService* supervised_user_service_; 96}; 97 98} // namespace 99 100TEST_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"); 106 { 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); 114 } 115 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", 129 &exceptions); 130 ASSERT_EQ(2u, exceptions.size()); 131 EXPECT_EQ(kExampleBarURL, exceptions[0]); 132 EXPECT_EQ(kExampleFooURL, exceptions[1]); 133 134 { 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); 141 } 142 } 143 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)); 155} 156 157// Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no 158// DCHECK is hit when the service is destroyed, this test passed. 159TEST_F(SupervisedUserServiceTest, ShutDownCustodianProfileDownloader) { 160 CustodianProfileDownloaderService* downloader_service = 161 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_.get()); 162 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)); 167} 168 169#if !defined(OS_ANDROID) 170class SupervisedUserServiceExtensionTestBase 171 : public extensions::ExtensionServiceTestBase { 172 public: 173 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised) 174 : is_supervised_(is_supervised), 175 channel_(chrome::VersionInfo::CHANNEL_DEV) {} 176 virtual ~SupervisedUserServiceExtensionTestBase() {} 177 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(); 185 } 186 187 protected: 188 ScopedVector<SupervisedUserSiteList> GetActiveSiteLists( 189 SupervisedUserService* supervised_user_service) { 190 return supervised_user_service->GetActiveSiteLists(); 191 } 192 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(); 201 return extension; 202 } 203 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") 208 .Build(); 209 int creation_flags = extensions::Extension::NO_FLAGS; 210 if (by_custodian) 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(); 215 return extension; 216 } 217 218 bool is_supervised_; 219 extensions::ScopedCurrentChannel channel_; 220}; 221 222class SupervisedUserServiceExtensionTestUnsupervised 223 : public SupervisedUserServiceExtensionTestBase { 224 public: 225 SupervisedUserServiceExtensionTestUnsupervised() 226 : SupervisedUserServiceExtensionTestBase(false) {} 227}; 228 229class SupervisedUserServiceExtensionTest 230 : public SupervisedUserServiceExtensionTestBase { 231 public: 232 SupervisedUserServiceExtensionTest() 233 : SupervisedUserServiceExtensionTestBase(true) {} 234}; 235 236TEST_F(SupervisedUserServiceExtensionTestUnsupervised, 237 ExtensionManagementPolicyProvider) { 238 SupervisedUserService* supervised_user_service = 239 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 240 EXPECT_FALSE(profile_->IsSupervised()); 241 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); 246 247 base::string16 error_2; 248 EXPECT_TRUE( 249 supervised_user_service->UserMayModifySettings(extension.get(), 250 &error_2)); 251 EXPECT_EQ(base::string16(), error_2); 252} 253 254TEST_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). 261 observer.Wait(); 262 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()); 268 EXPECT_TRUE( 269 supervised_user_service->UserMayModifySettings(theme.get(), &error_1)); 270 EXPECT_TRUE(error_1.empty()); 271 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()); 276 277 base::string16 error_2; 278 EXPECT_FALSE(supervised_user_service->UserMayModifySettings(extension.get(), 279 &error_2)); 280 EXPECT_FALSE(error_2.empty()); 281 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(), 286 &error_3)); 287 EXPECT_TRUE(error_3.empty()); 288 289 // The supervised user should still not be able to uninstall or disable the 290 // extension. 291 base::string16 error_4; 292 EXPECT_FALSE(supervised_user_service->UserMayModifySettings(extension_2.get(), 293 &error_4)); 294 EXPECT_FALSE(error_4.empty()); 295 296#ifndef NDEBUG 297 EXPECT_FALSE(supervised_user_service->GetDebugPolicyProviderName().empty()); 298#endif 299} 300 301TEST_F(SupervisedUserServiceExtensionTest, NoContentPacks) { 302 SupervisedUserService* supervised_user_service = 303 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 304 SupervisedUserURLFilter* url_filter = 305 supervised_user_service->GetURLFilterForUIThread(); 306 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)); 313} 314 315TEST_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); 321 observer.Wait(); 322 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)); 327 328 profile_->GetPrefs()->SetInteger( 329 prefs::kDefaultSupervisedUserFilteringBehavior, 330 SupervisedUserURLFilter::BLOCK); 331 EXPECT_EQ(SupervisedUserURLFilter::BLOCK, 332 url_filter->GetFilteringBehaviorForURL(example_url)); 333 334 profile_->GetPrefs()->SetInteger( 335 prefs::kDefaultSupervisedUserFilteringBehavior, 336 SupervisedUserURLFilter::WARN); 337 EXPECT_EQ(SupervisedUserURLFilter::WARN, 338 url_filter->GetFilteringBehaviorForURL(example_url)); 339 340 supervised_user_service->set_elevated_for_testing(true); 341 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(); 355 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()); 361 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); 371 372 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 373 url_filter->GetFilteringBehaviorForURL(example_url)); 374 EXPECT_EQ(SupervisedUserURLFilter::WARN, 375 url_filter->GetFilteringBehaviorForURL(moose_url)); 376 377 // Load a second content pack. 378 installer = extensions::UnpackedInstaller::Create(service_); 379 extension_path = 380 test_data_dir.AppendASCII("extensions/supervised_user/content_pack_2"); 381 installer->Load(extension_path); 382 observer.Wait(); 383 384 site_lists = GetActiveSiteLists(supervised_user_service); 385 ASSERT_EQ(2u, site_lists.size()); 386 sites.clear(); 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)); 395 } 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); 400 401 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 402 url_filter->GetFilteringBehaviorForURL(example_url)); 403 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 404 url_filter->GetFilteringBehaviorForURL(moose_url)); 405 406 // Disable the first content pack. 407 service_->DisableExtension(extension->id(), 408 extensions::Extension::DISABLE_USER_ACTION); 409 observer.Wait(); 410 411 site_lists = GetActiveSiteLists(supervised_user_service); 412 ASSERT_EQ(1u, site_lists.size()); 413 sites.clear(); 414 site_lists[0]->GetSites(&sites); 415 ASSERT_EQ(1u, sites.size()); 416 EXPECT_EQ(base::ASCIIToUTF16("Moose"), sites[0].name); 417 418 EXPECT_EQ(SupervisedUserURLFilter::WARN, 419 url_filter->GetFilteringBehaviorForURL(example_url)); 420 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 421 url_filter->GetFilteringBehaviorForURL(moose_url)); 422} 423#endif // !defined(OS_ANDROID) 424