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_test_base.h" 11#include "chrome/browser/extensions/unpacked_installer.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 14#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 15#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 16#include "chrome/browser/supervised_user/custodian_profile_downloader_service.h" 17#include "chrome/browser/supervised_user/custodian_profile_downloader_service_factory.h" 18#include "chrome/browser/supervised_user/supervised_user_service.h" 19#include "chrome/browser/supervised_user/supervised_user_service_factory.h" 20#include "chrome/browser/ui/browser_list.h" 21#include "chrome/common/chrome_paths.h" 22#include "chrome/common/extensions/features/feature_channel.h" 23#include "chrome/common/pref_names.h" 24#include "chrome/test/base/testing_profile.h" 25#include "content/public/test/test_browser_thread_bundle.h" 26#include "content/public/test/test_utils.h" 27#include "extensions/common/extension.h" 28#include "extensions/common/extension_builder.h" 29#include "extensions/common/manifest_constants.h" 30#include "testing/gtest/include/gtest/gtest.h" 31 32using content::MessageLoopRunner; 33 34namespace { 35 36void OnProfileDownloadedFail(const base::string16& full_name) { 37 ASSERT_TRUE(false) << "Profile download should not have succeeded."; 38} 39 40class SupervisedUserURLFilterObserver : 41 public SupervisedUserURLFilter::Observer { 42 public: 43 explicit SupervisedUserURLFilterObserver(SupervisedUserURLFilter* url_filter) 44 : url_filter_(url_filter) { 45 Reset(); 46 url_filter_->AddObserver(this); 47 } 48 49 ~SupervisedUserURLFilterObserver() { 50 url_filter_->RemoveObserver(this); 51 } 52 53 void Wait() { 54 message_loop_runner_->Run(); 55 Reset(); 56 } 57 58 // SupervisedUserURLFilter::Observer 59 virtual void OnSiteListUpdated() OVERRIDE { 60 message_loop_runner_->Quit(); 61 } 62 63 private: 64 void Reset() { 65 message_loop_runner_ = new MessageLoopRunner; 66 } 67 68 SupervisedUserURLFilter* url_filter_; 69 scoped_refptr<MessageLoopRunner> message_loop_runner_; 70}; 71 72class SupervisedUserServiceTest : public ::testing::Test { 73 public: 74 SupervisedUserServiceTest() {} 75 76 virtual void SetUp() OVERRIDE { 77 TestingProfile::Builder builder; 78 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), 79 BuildFakeProfileOAuth2TokenService); 80 profile_ = builder.Build(); 81 supervised_user_service_ = 82 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 83 } 84 85 virtual void TearDown() OVERRIDE { 86 profile_.reset(); 87 } 88 89 virtual ~SupervisedUserServiceTest() {} 90 91 protected: 92 content::TestBrowserThreadBundle thread_bundle_; 93 scoped_ptr<TestingProfile> profile_; 94 SupervisedUserService* supervised_user_service_; 95}; 96 97} // namespace 98 99TEST_F(SupervisedUserServiceTest, GetManualExceptionsForHost) { 100 GURL kExampleFooURL("http://www.example.com/foo"); 101 GURL kExampleBarURL("http://www.example.com/bar"); 102 GURL kExampleFooNoWWWURL("http://example.com/foo"); 103 GURL kBlurpURL("http://blurp.net/bla"); 104 GURL kMooseURL("http://moose.org/baz"); 105 { 106 DictionaryPrefUpdate update(profile_->GetPrefs(), 107 prefs::kSupervisedUserManualURLs); 108 base::DictionaryValue* dict = update.Get(); 109 dict->SetBooleanWithoutPathExpansion(kExampleFooURL.spec(), true); 110 dict->SetBooleanWithoutPathExpansion(kExampleBarURL.spec(), false); 111 dict->SetBooleanWithoutPathExpansion(kExampleFooNoWWWURL.spec(), true); 112 dict->SetBooleanWithoutPathExpansion(kBlurpURL.spec(), true); 113 } 114 115 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW, 116 supervised_user_service_->GetManualBehaviorForURL(kExampleFooURL)); 117 EXPECT_EQ(SupervisedUserService::MANUAL_BLOCK, 118 supervised_user_service_->GetManualBehaviorForURL(kExampleBarURL)); 119 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW, 120 supervised_user_service_->GetManualBehaviorForURL( 121 kExampleFooNoWWWURL)); 122 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW, 123 supervised_user_service_->GetManualBehaviorForURL(kBlurpURL)); 124 EXPECT_EQ(SupervisedUserService::MANUAL_NONE, 125 supervised_user_service_->GetManualBehaviorForURL(kMooseURL)); 126 std::vector<GURL> exceptions; 127 supervised_user_service_->GetManualExceptionsForHost("www.example.com", 128 &exceptions); 129 ASSERT_EQ(2u, exceptions.size()); 130 EXPECT_EQ(kExampleBarURL, exceptions[0]); 131 EXPECT_EQ(kExampleFooURL, exceptions[1]); 132 133 { 134 DictionaryPrefUpdate update(profile_->GetPrefs(), 135 prefs::kSupervisedUserManualURLs); 136 base::DictionaryValue* dict = update.Get(); 137 for (std::vector<GURL>::iterator it = exceptions.begin(); 138 it != exceptions.end(); ++it) { 139 dict->RemoveWithoutPathExpansion(it->spec(), NULL); 140 } 141 } 142 143 EXPECT_EQ(SupervisedUserService::MANUAL_NONE, 144 supervised_user_service_->GetManualBehaviorForURL(kExampleFooURL)); 145 EXPECT_EQ(SupervisedUserService::MANUAL_NONE, 146 supervised_user_service_->GetManualBehaviorForURL(kExampleBarURL)); 147 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW, 148 supervised_user_service_->GetManualBehaviorForURL( 149 kExampleFooNoWWWURL)); 150 EXPECT_EQ(SupervisedUserService::MANUAL_ALLOW, 151 supervised_user_service_->GetManualBehaviorForURL(kBlurpURL)); 152 EXPECT_EQ(SupervisedUserService::MANUAL_NONE, 153 supervised_user_service_->GetManualBehaviorForURL(kMooseURL)); 154} 155 156// Ensure that the CustodianProfileDownloaderService shuts down cleanly. If no 157// DCHECK is hit when the service is destroyed, this test passed. 158TEST_F(SupervisedUserServiceTest, ShutDownCustodianProfileDownloader) { 159 CustodianProfileDownloaderService* downloader_service = 160 CustodianProfileDownloaderServiceFactory::GetForProfile(profile_.get()); 161 162 // Emulate being logged in, then start to download a profile so a 163 // ProfileDownloader gets created. 164 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, "Logged In"); 165 downloader_service->DownloadProfile(base::Bind(&OnProfileDownloadedFail)); 166} 167 168#if !defined(OS_ANDROID) 169class SupervisedUserServiceExtensionTestBase 170 : public extensions::ExtensionServiceTestBase { 171 public: 172 explicit SupervisedUserServiceExtensionTestBase(bool is_supervised) 173 : is_supervised_(is_supervised), 174 channel_(chrome::VersionInfo::CHANNEL_DEV) {} 175 virtual ~SupervisedUserServiceExtensionTestBase() {} 176 177 virtual void SetUp() OVERRIDE { 178 ExtensionServiceTestBase::SetUp(); 179 ExtensionServiceTestBase::ExtensionServiceInitParams params = 180 CreateDefaultInitParams(); 181 params.profile_is_supervised = is_supervised_; 182 InitializeExtensionService(params); 183 SupervisedUserServiceFactory::GetForProfile(profile_.get())->Init(); 184 } 185 186 protected: 187 ScopedVector<SupervisedUserSiteList> GetActiveSiteLists( 188 SupervisedUserService* supervised_user_service) { 189 return supervised_user_service->GetActiveSiteLists(); 190 } 191 192 scoped_refptr<extensions::Extension> MakeThemeExtension() { 193 scoped_ptr<base::DictionaryValue> source(new base::DictionaryValue()); 194 source->SetString(extensions::manifest_keys::kName, "Theme"); 195 source->Set(extensions::manifest_keys::kTheme, new base::DictionaryValue()); 196 source->SetString(extensions::manifest_keys::kVersion, "1.0"); 197 extensions::ExtensionBuilder builder; 198 scoped_refptr<extensions::Extension> extension = 199 builder.SetManifest(source.Pass()).Build(); 200 return extension; 201 } 202 203 scoped_refptr<extensions::Extension> MakeExtension() { 204 scoped_ptr<base::DictionaryValue> manifest = extensions::DictionaryBuilder() 205 .Set(extensions::manifest_keys::kName, "Extension") 206 .Set(extensions::manifest_keys::kVersion, "1.0") 207 .Build(); 208 extensions::ExtensionBuilder builder; 209 scoped_refptr<extensions::Extension> extension = 210 builder.SetManifest(manifest.Pass()).Build(); 211 return extension; 212 } 213 214 bool is_supervised_; 215 extensions::ScopedCurrentChannel channel_; 216}; 217 218class SupervisedUserServiceExtensionTestUnsupervised 219 : public SupervisedUserServiceExtensionTestBase { 220 public: 221 SupervisedUserServiceExtensionTestUnsupervised() 222 : SupervisedUserServiceExtensionTestBase(false) {} 223}; 224 225class SupervisedUserServiceExtensionTest 226 : public SupervisedUserServiceExtensionTestBase { 227 public: 228 SupervisedUserServiceExtensionTest() 229 : SupervisedUserServiceExtensionTestBase(true) {} 230}; 231 232TEST_F(SupervisedUserServiceExtensionTestUnsupervised, 233 ExtensionManagementPolicyProvider) { 234 SupervisedUserService* supervised_user_service = 235 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 236 EXPECT_FALSE(profile_->IsSupervised()); 237 238 scoped_refptr<extensions::Extension> extension = MakeExtension(); 239 base::string16 error_1; 240 EXPECT_TRUE(supervised_user_service->UserMayLoad(extension.get(), &error_1)); 241 EXPECT_EQ(base::string16(), error_1); 242 243 base::string16 error_2; 244 EXPECT_TRUE( 245 supervised_user_service->UserMayModifySettings(extension.get(), 246 &error_2)); 247 EXPECT_EQ(base::string16(), error_2); 248} 249 250TEST_F(SupervisedUserServiceExtensionTest, ExtensionManagementPolicyProvider) { 251 SupervisedUserService* supervised_user_service = 252 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 253 SupervisedUserURLFilterObserver observer( 254 supervised_user_service->GetURLFilterForUIThread()); 255 ASSERT_TRUE(profile_->IsSupervised()); 256 // Wait for the initial update to finish (otherwise we'll get leaks). 257 observer.Wait(); 258 259 // Check that a supervised user can install a theme. 260 scoped_refptr<extensions::Extension> theme = MakeThemeExtension(); 261 base::string16 error_1; 262 EXPECT_TRUE(supervised_user_service->UserMayLoad(theme.get(), &error_1)); 263 EXPECT_TRUE(error_1.empty()); 264 EXPECT_TRUE( 265 supervised_user_service->UserMayModifySettings(theme.get(), &error_1)); 266 EXPECT_TRUE(error_1.empty()); 267 268 // Now check a different kind of extension. 269 scoped_refptr<extensions::Extension> extension = MakeExtension(); 270 EXPECT_FALSE(supervised_user_service->UserMayLoad(extension.get(), &error_1)); 271 EXPECT_FALSE(error_1.empty()); 272 273 base::string16 error_2; 274 EXPECT_FALSE( 275 supervised_user_service->UserMayModifySettings(extension.get(), 276 &error_2)); 277 EXPECT_FALSE(error_2.empty()); 278 279#ifndef NDEBUG 280 EXPECT_FALSE(supervised_user_service->GetDebugPolicyProviderName().empty()); 281#endif 282} 283 284TEST_F(SupervisedUserServiceExtensionTest, NoContentPacks) { 285 SupervisedUserService* supervised_user_service = 286 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 287 SupervisedUserURLFilter* url_filter = 288 supervised_user_service->GetURLFilterForUIThread(); 289 290 GURL url("http://youtube.com"); 291 ScopedVector<SupervisedUserSiteList> site_lists = 292 GetActiveSiteLists(supervised_user_service); 293 ASSERT_EQ(0u, site_lists.size()); 294 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 295 url_filter->GetFilteringBehaviorForURL(url)); 296} 297 298TEST_F(SupervisedUserServiceExtensionTest, InstallContentPacks) { 299 SupervisedUserService* supervised_user_service = 300 SupervisedUserServiceFactory::GetForProfile(profile_.get()); 301 SupervisedUserURLFilter* url_filter = 302 supervised_user_service->GetURLFilterForUIThread(); 303 SupervisedUserURLFilterObserver observer(url_filter); 304 observer.Wait(); 305 306 GURL example_url("http://example.com"); 307 GURL moose_url("http://moose.org"); 308 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 309 url_filter->GetFilteringBehaviorForURL(example_url)); 310 311 profile_->GetPrefs()->SetInteger( 312 prefs::kDefaultSupervisedUserFilteringBehavior, 313 SupervisedUserURLFilter::BLOCK); 314 EXPECT_EQ(SupervisedUserURLFilter::BLOCK, 315 url_filter->GetFilteringBehaviorForURL(example_url)); 316 317 profile_->GetPrefs()->SetInteger( 318 prefs::kDefaultSupervisedUserFilteringBehavior, 319 SupervisedUserURLFilter::WARN); 320 EXPECT_EQ(SupervisedUserURLFilter::WARN, 321 url_filter->GetFilteringBehaviorForURL(example_url)); 322 323 supervised_user_service->set_elevated_for_testing(true); 324 325 // Load a content pack. 326 scoped_refptr<extensions::UnpackedInstaller> installer( 327 extensions::UnpackedInstaller::Create(service_)); 328 installer->set_prompt_for_plugins(false); 329 base::FilePath test_data_dir; 330 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); 331 base::FilePath extension_path = 332 test_data_dir.AppendASCII("extensions/managed_mode/content_pack"); 333 content::WindowedNotificationObserver extension_load_observer( 334 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 335 content::Source<Profile>(profile_.get())); 336 installer->Load(extension_path); 337 extension_load_observer.Wait(); 338 observer.Wait(); 339 content::Details<extensions::Extension> details = 340 extension_load_observer.details(); 341 scoped_refptr<extensions::Extension> extension = 342 make_scoped_refptr(details.ptr()); 343 ASSERT_TRUE(extension.get()); 344 345 ScopedVector<SupervisedUserSiteList> site_lists = 346 GetActiveSiteLists(supervised_user_service); 347 ASSERT_EQ(1u, site_lists.size()); 348 std::vector<SupervisedUserSiteList::Site> sites; 349 site_lists[0]->GetSites(&sites); 350 ASSERT_EQ(3u, sites.size()); 351 EXPECT_EQ(base::ASCIIToUTF16("YouTube"), sites[0].name); 352 EXPECT_EQ(base::ASCIIToUTF16("Homestar Runner"), sites[1].name); 353 EXPECT_EQ(base::string16(), sites[2].name); 354 355 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 356 url_filter->GetFilteringBehaviorForURL(example_url)); 357 EXPECT_EQ(SupervisedUserURLFilter::WARN, 358 url_filter->GetFilteringBehaviorForURL(moose_url)); 359 360 // Load a second content pack. 361 installer = extensions::UnpackedInstaller::Create(service_); 362 extension_path = 363 test_data_dir.AppendASCII("extensions/managed_mode/content_pack_2"); 364 installer->Load(extension_path); 365 observer.Wait(); 366 367 site_lists = GetActiveSiteLists(supervised_user_service); 368 ASSERT_EQ(2u, site_lists.size()); 369 sites.clear(); 370 site_lists[0]->GetSites(&sites); 371 site_lists[1]->GetSites(&sites); 372 ASSERT_EQ(4u, sites.size()); 373 // The site lists might be returned in any order, so we put them into a set. 374 std::set<std::string> site_names; 375 for (std::vector<SupervisedUserSiteList::Site>::const_iterator it = 376 sites.begin(); it != sites.end(); ++it) { 377 site_names.insert(base::UTF16ToUTF8(it->name)); 378 } 379 EXPECT_TRUE(site_names.count("YouTube") == 1u); 380 EXPECT_TRUE(site_names.count("Homestar Runner") == 1u); 381 EXPECT_TRUE(site_names.count(std::string()) == 1u); 382 EXPECT_TRUE(site_names.count("Moose") == 1u); 383 384 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 385 url_filter->GetFilteringBehaviorForURL(example_url)); 386 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 387 url_filter->GetFilteringBehaviorForURL(moose_url)); 388 389 // Disable the first content pack. 390 service_->DisableExtension(extension->id(), 391 extensions::Extension::DISABLE_USER_ACTION); 392 observer.Wait(); 393 394 site_lists = GetActiveSiteLists(supervised_user_service); 395 ASSERT_EQ(1u, site_lists.size()); 396 sites.clear(); 397 site_lists[0]->GetSites(&sites); 398 ASSERT_EQ(1u, sites.size()); 399 EXPECT_EQ(base::ASCIIToUTF16("Moose"), sites[0].name); 400 401 EXPECT_EQ(SupervisedUserURLFilter::WARN, 402 url_filter->GetFilteringBehaviorForURL(example_url)); 403 EXPECT_EQ(SupervisedUserURLFilter::ALLOW, 404 url_filter->GetFilteringBehaviorForURL(moose_url)); 405} 406#endif // !defined(OS_ANDROID) 407