1 // Copyright (c) 2012 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/bind.h" 6 #include "base/command_line.h" 7 #include "base/prefs/pref_service.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/password_manager/password_store_factory.h" 10 #include "chrome/browser/profiles/profile_info_cache.h" 11 #include "chrome/browser/profiles/profile_info_cache_observer.h" 12 #include "chrome/browser/profiles/profile_manager.h" 13 #include "chrome/browser/profiles/profile_window.h" 14 #include "chrome/browser/profiles/profiles_state.h" 15 #include "chrome/browser/ui/browser_finder.h" 16 #include "chrome/browser/ui/browser_list.h" 17 #include "chrome/browser/ui/browser_window.h" 18 #include "chrome/browser/ui/host_desktop.h" 19 #include "chrome/common/pref_names.h" 20 #include "chrome/test/base/in_process_browser_test.h" 21 #include "chrome/test/base/test_switches.h" 22 #include "chrome/test/base/testing_browser_process.h" 23 #include "chrome/test/base/ui_test_utils.h" 24 #include "components/autofill/core/common/password_form.h" 25 #include "components/password_manager/core/browser/password_store.h" 26 #include "components/password_manager/core/browser/password_store_consumer.h" 27 28 #if defined(OS_CHROMEOS) 29 #include "base/path_service.h" 30 #include "chrome/common/chrome_constants.h" 31 #include "chrome/common/chrome_paths.h" 32 #include "chromeos/chromeos_switches.h" 33 #include "testing/gtest/include/gtest/gtest.h" 34 #endif 35 36 namespace { 37 38 const ProfileManager::CreateCallback kOnProfileSwitchDoNothing; 39 40 // An observer that returns back to test code after a new profile is 41 // initialized. 42 void OnUnblockOnProfileCreation(Profile* profile, 43 Profile::CreateStatus status) { 44 if (status == Profile::CREATE_STATUS_INITIALIZED) 45 base::MessageLoop::current()->Quit(); 46 } 47 48 void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) { 49 ASSERT_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL); 50 ASSERT_NE(status, Profile::CREATE_STATUS_REMOTE_FAIL); 51 // No browser should have been created for this profile yet. 52 EXPECT_EQ(chrome::GetTotalBrowserCountForProfile(profile), 0U); 53 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 54 if (status == Profile::CREATE_STATUS_INITIALIZED) 55 base::MessageLoop::current()->Quit(); 56 } 57 58 void EphemeralProfileCreationComplete(Profile* profile, 59 Profile::CreateStatus status) { 60 if (status == Profile::CREATE_STATUS_INITIALIZED) 61 profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); 62 ProfileCreationComplete(profile, status); 63 } 64 65 class ProfileRemovalObserver : public ProfileInfoCacheObserver { 66 public: 67 ProfileRemovalObserver() { 68 g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver( 69 this); 70 } 71 72 virtual ~ProfileRemovalObserver() { 73 g_browser_process->profile_manager()->GetProfileInfoCache().RemoveObserver( 74 this); 75 } 76 77 std::string last_used_profile_name() { return last_used_profile_name_; } 78 79 // ProfileInfoCacheObserver overrides: 80 virtual void OnProfileWillBeRemoved( 81 const base::FilePath& profile_path) OVERRIDE { 82 last_used_profile_name_ = g_browser_process->local_state()->GetString( 83 prefs::kProfileLastUsed); 84 } 85 86 private: 87 std::string last_used_profile_name_; 88 89 DISALLOW_COPY_AND_ASSIGN(ProfileRemovalObserver); 90 }; 91 92 // The class serves to retrieve passwords from PasswordStore asynchronously. It 93 // used by ProfileManagerBrowserTest.DeletePasswords on some platforms. 94 class PasswordStoreConsumerVerifier : 95 public password_manager::PasswordStoreConsumer { 96 public: 97 PasswordStoreConsumerVerifier() : called_(false) {} 98 99 virtual void OnGetPasswordStoreResults( 100 const std::vector<autofill::PasswordForm*>& results) OVERRIDE { 101 EXPECT_FALSE(called_); 102 called_ = true; 103 password_entries_.clear(); 104 password_entries_.assign(results.begin(), results.end()); 105 } 106 107 bool IsCalled() const { return called_; } 108 109 const std::vector<autofill::PasswordForm*>& GetPasswords() const { 110 return password_entries_.get(); 111 } 112 private: 113 ScopedVector<autofill::PasswordForm> password_entries_; 114 bool called_; 115 }; 116 117 } // namespace 118 119 // This file contains tests for the ProfileManager that require a heavyweight 120 // InProcessBrowserTest. These include tests involving profile deletion. 121 122 // TODO(jeremy): crbug.com/103355 - These tests should be enabled on all 123 // platforms. 124 class ProfileManagerBrowserTest : public InProcessBrowserTest { 125 protected: 126 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 127 #if defined(OS_CHROMEOS) 128 command_line->AppendSwitch( 129 chromeos::switches::kIgnoreUserProfileMappingForTests); 130 #endif 131 } 132 }; 133 134 #if defined(OS_MACOSX) 135 136 // Delete single profile and make sure a new one is created. 137 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { 138 ProfileManager* profile_manager = g_browser_process->profile_manager(); 139 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 140 ProfileRemovalObserver observer; 141 142 // We should start out with 1 profile. 143 ASSERT_EQ(cache.GetNumberOfProfiles(), 1U); 144 145 // Delete singleton profile. 146 base::FilePath singleton_profile_path = cache.GetPathOfProfileAtIndex(0); 147 EXPECT_FALSE(singleton_profile_path.empty()); 148 profile_manager->ScheduleProfileForDeletion(singleton_profile_path, 149 ProfileManager::CreateCallback()); 150 151 // Spin things till profile is actually deleted. 152 content::RunAllPendingInMessageLoop(); 153 154 // Make sure a new profile was created automatically. 155 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 156 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 157 EXPECT_NE(new_profile_path, singleton_profile_path); 158 159 // Make sure that last used profile preference is set correctly. 160 Profile* last_used = ProfileManager::GetLastUsedProfile(); 161 EXPECT_EQ(new_profile_path, last_used->GetPath()); 162 163 // Make sure the last used profile was set correctly before the notification 164 // was sent. 165 std::string last_used_profile_name = 166 last_used->GetPath().BaseName().MaybeAsASCII(); 167 EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name()); 168 } 169 170 // Delete all profiles in a multi profile setup and make sure a new one is 171 // created. 172 // Crashes/CHECKs. See crbug.com/104851 173 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { 174 ProfileManager* profile_manager = g_browser_process->profile_manager(); 175 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 176 177 // Create an additional profile. 178 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); 179 profile_manager->CreateProfileAsync(new_path, 180 base::Bind(&OnUnblockOnProfileCreation), 181 base::string16(), base::string16(), 182 std::string()); 183 184 // Spin to allow profile creation to take place, loop is terminated 185 // by OnUnblockOnProfileCreation when the profile is created. 186 content::RunMessageLoop(); 187 188 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 189 190 // Delete all profiles. 191 base::FilePath profile_path1 = cache.GetPathOfProfileAtIndex(0); 192 base::FilePath profile_path2 = cache.GetPathOfProfileAtIndex(1); 193 EXPECT_FALSE(profile_path1.empty()); 194 EXPECT_FALSE(profile_path2.empty()); 195 profile_manager->ScheduleProfileForDeletion(profile_path1, 196 ProfileManager::CreateCallback()); 197 profile_manager->ScheduleProfileForDeletion(profile_path2, 198 ProfileManager::CreateCallback()); 199 200 // Spin things so deletion can take place. 201 content::RunAllPendingInMessageLoop(); 202 203 // Make sure a new profile was created automatically. 204 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 205 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 206 EXPECT_NE(new_profile_path, profile_path1); 207 EXPECT_NE(new_profile_path, profile_path2); 208 209 // Make sure that last used profile preference is set correctly. 210 Profile* last_used = ProfileManager::GetLastUsedProfile(); 211 EXPECT_EQ(new_profile_path, last_used->GetPath()); 212 } 213 #endif // OS_MACOSX 214 215 #if defined(OS_CHROMEOS) 216 217 class ProfileManagerCrOSBrowserTest : public ProfileManagerBrowserTest { 218 protected: 219 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 220 // Use a user hash other than the default chrome::kTestUserProfileDir 221 // so that the prefix case is tested. 222 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, 223 "test-user-hash"); 224 } 225 }; 226 227 IN_PROC_BROWSER_TEST_F(ProfileManagerCrOSBrowserTest, GetLastUsedProfile) { 228 // Make sure that last used profile is correct. 229 Profile* last_used_profile = ProfileManager::GetLastUsedProfile(); 230 EXPECT_TRUE(last_used_profile != NULL); 231 232 base::FilePath profile_path; 233 PathService::Get(chrome::DIR_USER_DATA, &profile_path); 234 235 profile_path = profile_path.AppendASCII( 236 std::string(chrome::kProfileDirPrefix) + "test-user-hash"); 237 EXPECT_EQ(profile_path.value(), last_used_profile->GetPath().value()); 238 } 239 240 #endif // OS_CHROMEOS 241 242 // Times out (http://crbug.com/159002) 243 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 244 DISABLED_CreateProfileWithCallback) { 245 ProfileManager* profile_manager = g_browser_process->profile_manager(); 246 247 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 248 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 249 250 // Create a profile, make sure callback is invoked before any callbacks are 251 // invoked (so they can do things like sign in the profile, etc). 252 ProfileManager::CreateMultiProfileAsync( 253 base::string16(), // name 254 base::string16(), // icon url 255 base::Bind(ProfileCreationComplete), 256 std::string()); 257 // Wait for profile to finish loading. 258 content::RunMessageLoop(); 259 EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U); 260 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 261 262 // Now close all browser windows. 263 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 264 for (std::vector<Profile*>::const_iterator it = profiles.begin(); 265 it != profiles.end(); ++it) { 266 BrowserList::CloseAllBrowsersWithProfile(*it); 267 } 268 } 269 270 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 271 SwitchToProfile) { 272 #if defined(OS_WIN) && defined(USE_ASH) 273 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 274 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 275 return; 276 #endif 277 278 // If multiprofile mode is not enabled, you can't switch between profiles. 279 if (!profiles::IsMultipleProfilesEnabled()) 280 return; 281 282 ProfileManager* profile_manager = g_browser_process->profile_manager(); 283 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 284 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 285 286 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 287 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 288 289 // Create an additional profile. 290 base::FilePath path_profile2 = 291 profile_manager->GenerateNextProfileDirectoryPath(); 292 profile_manager->CreateProfileAsync(path_profile2, 293 base::Bind(&OnUnblockOnProfileCreation), 294 base::string16(), base::string16(), 295 std::string()); 296 297 // Spin to allow profile creation to take place, loop is terminated 298 // by OnUnblockOnProfileCreation when the profile is created. 299 content::RunMessageLoop(); 300 301 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 302 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 303 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 304 EXPECT_EQ(1U, browser_list->size()); 305 306 // Open a browser window for the first profile. 307 profiles::SwitchToProfile(path_profile1, desktop_type, false, 308 kOnProfileSwitchDoNothing, 309 ProfileMetrics::SWITCH_PROFILE_ICON); 310 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 311 EXPECT_EQ(1U, browser_list->size()); 312 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 313 314 // Open a browser window for the second profile. 315 profiles::SwitchToProfile(path_profile2, desktop_type, false, 316 kOnProfileSwitchDoNothing, 317 ProfileMetrics::SWITCH_PROFILE_ICON); 318 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 319 EXPECT_EQ(2U, browser_list->size()); 320 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 321 322 // Switch to the first profile without opening a new window. 323 profiles::SwitchToProfile(path_profile1, desktop_type, false, 324 kOnProfileSwitchDoNothing, 325 ProfileMetrics::SWITCH_PROFILE_ICON); 326 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 327 EXPECT_EQ(2U, browser_list->size()); 328 329 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 330 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 331 } 332 333 // Flakes on Windows: http://crbug.com/314905 334 #if defined(OS_WIN) 335 #define MAYBE_EphemeralProfile DISABLED_EphemeralProfile 336 #else 337 #define MAYBE_EphemeralProfile EphemeralProfile 338 #endif 339 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, MAYBE_EphemeralProfile) { 340 #if defined(OS_WIN) && defined(USE_ASH) 341 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 342 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 343 return; 344 #endif 345 346 // If multiprofile mode is not enabled, you can't switch between profiles. 347 if (!profiles::IsMultipleProfilesEnabled()) 348 return; 349 350 ProfileManager* profile_manager = g_browser_process->profile_manager(); 351 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 352 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 353 354 ASSERT_EQ(1U, profile_manager->GetNumberOfProfiles()); 355 EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); 356 357 // Create an ephemeral profile. 358 base::FilePath path_profile2 = 359 profile_manager->GenerateNextProfileDirectoryPath(); 360 profile_manager->CreateProfileAsync( 361 path_profile2, 362 base::Bind(&EphemeralProfileCreationComplete), 363 base::string16(), base::string16(), std::string()); 364 365 // Spin to allow profile creation to take place. 366 content::RunMessageLoop(); 367 368 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 369 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 370 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 371 EXPECT_EQ(1U, browser_list->size()); 372 373 // Open a browser window for the second profile. 374 profiles::SwitchToProfile(path_profile2, desktop_type, false, 375 kOnProfileSwitchDoNothing, 376 ProfileMetrics::SWITCH_PROFILE_ICON); 377 EXPECT_EQ(2U, chrome::GetTotalBrowserCount()); 378 EXPECT_EQ(2U, browser_list->size()); 379 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 380 381 // Create a second window for the ephemeral profile. 382 profiles::SwitchToProfile(path_profile2, desktop_type, true, 383 kOnProfileSwitchDoNothing, 384 ProfileMetrics::SWITCH_PROFILE_ICON); 385 EXPECT_EQ(3U, chrome::GetTotalBrowserCount()); 386 EXPECT_EQ(3U, browser_list->size()); 387 388 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 389 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 390 EXPECT_EQ(path_profile2, browser_list->get(2)->profile()->GetPath()); 391 392 // Closing the first window of the ephemeral profile should not delete it. 393 browser_list->get(2)->window()->Close(); 394 content::RunAllPendingInMessageLoop(); 395 EXPECT_EQ(2U, browser_list->size()); 396 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 397 398 // The second should though. 399 browser_list->get(1)->window()->Close(); 400 content::RunAllPendingInMessageLoop(); 401 EXPECT_EQ(1U, browser_list->size()); 402 ASSERT_EQ(1U, cache.GetNumberOfProfiles()); 403 } 404 405 // The test makes sense on those platforms where the keychain exists. 406 #if !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) 407 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeletePasswords) { 408 Profile* profile = ProfileManager::GetActiveUserProfile(); 409 ASSERT_TRUE(profile); 410 411 autofill::PasswordForm form; 412 form.scheme = autofill::PasswordForm::SCHEME_HTML; 413 form.origin = GURL("http://accounts.google.com/LoginAuth"); 414 form.signon_realm = "http://accounts.google.com/"; 415 form.username_value = base::ASCIIToUTF16("my_username"); 416 form.password_value = base::ASCIIToUTF16("my_password"); 417 form.ssl_valid = false; 418 form.preferred = true; 419 form.blacklisted_by_user = false; 420 421 scoped_refptr<password_manager::PasswordStore> password_store = 422 PasswordStoreFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS) 423 .get(); 424 ASSERT_TRUE(password_store.get()); 425 426 password_store->AddLogin(form); 427 PasswordStoreConsumerVerifier verify_add; 428 password_store->GetAutofillableLogins(&verify_add); 429 430 ProfileManager* profile_manager = g_browser_process->profile_manager(); 431 profile_manager->ScheduleProfileForDeletion(profile->GetPath(), 432 ProfileManager::CreateCallback()); 433 content::RunAllPendingInMessageLoop(); 434 PasswordStoreConsumerVerifier verify_delete; 435 password_store->GetAutofillableLogins(&verify_delete); 436 437 // Run the password background thread. 438 base::RunLoop run_loop; 439 base::Closure task = base::Bind( 440 base::IgnoreResult(&content::BrowserThread::PostTask), 441 content::BrowserThread::UI, 442 FROM_HERE, 443 run_loop.QuitClosure()); 444 EXPECT_TRUE(password_store->ScheduleTask(task)); 445 run_loop.Run(); 446 447 EXPECT_TRUE(verify_add.IsCalled()); 448 EXPECT_EQ(1u, verify_add.GetPasswords().size()); 449 EXPECT_TRUE(verify_delete.IsCalled()); 450 EXPECT_EQ(0u, verify_delete.GetPasswords().size()); 451 } 452 #endif // !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) 453