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