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/profiles/profile_info_cache.h" 10 #include "chrome/browser/profiles/profile_info_cache_observer.h" 11 #include "chrome/browser/profiles/profile_manager.h" 12 #include "chrome/browser/profiles/profile_window.h" 13 #include "chrome/browser/profiles/profiles_state.h" 14 #include "chrome/browser/ui/browser_finder.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/browser_window.h" 17 #include "chrome/browser/ui/host_desktop.h" 18 #include "chrome/common/pref_names.h" 19 #include "chrome/test/base/in_process_browser_test.h" 20 #include "chrome/test/base/test_switches.h" 21 #include "chrome/test/base/testing_browser_process.h" 22 #include "chrome/test/base/ui_test_utils.h" 23 24 #if defined(OS_CHROMEOS) 25 #include "base/path_service.h" 26 #include "chrome/common/chrome_constants.h" 27 #include "chrome/common/chrome_paths.h" 28 #include "chromeos/chromeos_switches.h" 29 #include "testing/gtest/include/gtest/gtest.h" 30 #endif 31 32 namespace { 33 34 const profiles::ProfileSwitchingDoneCallback kOnProfileSwitchDoNothing; 35 36 // An observer that returns back to test code after a new profile is 37 // initialized. 38 void OnUnblockOnProfileCreation(Profile* profile, 39 Profile::CreateStatus status) { 40 if (status == Profile::CREATE_STATUS_INITIALIZED) 41 base::MessageLoop::current()->Quit(); 42 } 43 44 void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) { 45 ASSERT_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL); 46 ASSERT_NE(status, Profile::CREATE_STATUS_REMOTE_FAIL); 47 // No browser should have been created for this profile yet. 48 EXPECT_EQ(chrome::GetTotalBrowserCountForProfile(profile), 0U); 49 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 50 if (status == Profile::CREATE_STATUS_INITIALIZED) 51 base::MessageLoop::current()->Quit(); 52 } 53 54 void EphemeralProfileCreationComplete(Profile* profile, 55 Profile::CreateStatus status) { 56 if (status == Profile::CREATE_STATUS_INITIALIZED) 57 profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); 58 ProfileCreationComplete(profile, status); 59 } 60 61 class ProfileRemovalObserver : public ProfileInfoCacheObserver { 62 public: 63 ProfileRemovalObserver() { 64 g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver( 65 this); 66 } 67 68 virtual ~ProfileRemovalObserver() { 69 g_browser_process->profile_manager()->GetProfileInfoCache().RemoveObserver( 70 this); 71 } 72 73 std::string last_used_profile_name() { return last_used_profile_name_; } 74 75 // ProfileInfoCacheObserver overrides: 76 virtual void OnProfileWillBeRemoved( 77 const base::FilePath& profile_path) OVERRIDE { 78 last_used_profile_name_ = g_browser_process->local_state()->GetString( 79 prefs::kProfileLastUsed); 80 } 81 82 private: 83 std::string last_used_profile_name_; 84 85 DISALLOW_COPY_AND_ASSIGN(ProfileRemovalObserver); 86 }; 87 88 } // namespace 89 90 // This file contains tests for the ProfileManager that require a heavyweight 91 // InProcessBrowserTest. These include tests involving profile deletion. 92 93 // TODO(jeremy): crbug.com/103355 - These tests should be enabled on all 94 // platforms. 95 class ProfileManagerBrowserTest : public InProcessBrowserTest { 96 protected: 97 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 98 #if defined(OS_CHROMEOS) 99 command_line->AppendSwitch( 100 chromeos::switches::kIgnoreUserProfileMappingForTests); 101 #endif 102 } 103 }; 104 105 #if defined(OS_MACOSX) 106 107 // Delete single profile and make sure a new one is created. 108 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { 109 ProfileManager* profile_manager = g_browser_process->profile_manager(); 110 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 111 ProfileRemovalObserver observer; 112 113 // We should start out with 1 profile. 114 ASSERT_EQ(cache.GetNumberOfProfiles(), 1U); 115 116 // Delete singleton profile. 117 base::FilePath singleton_profile_path = cache.GetPathOfProfileAtIndex(0); 118 EXPECT_FALSE(singleton_profile_path.empty()); 119 profile_manager->ScheduleProfileForDeletion(singleton_profile_path, 120 ProfileManager::CreateCallback()); 121 122 // Spin things till profile is actually deleted. 123 content::RunAllPendingInMessageLoop(); 124 125 // Make sure a new profile was created automatically. 126 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 127 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 128 EXPECT_NE(new_profile_path, singleton_profile_path); 129 130 // Make sure that last used profile preference is set correctly. 131 Profile* last_used = ProfileManager::GetLastUsedProfile(); 132 EXPECT_EQ(new_profile_path, last_used->GetPath()); 133 134 // Make sure the last used profile was set correctly before the notification 135 // was sent. 136 std::string last_used_profile_name = 137 last_used->GetPath().BaseName().MaybeAsASCII(); 138 EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name()); 139 } 140 141 // Delete all profiles in a multi profile setup and make sure a new one is 142 // created. 143 // Crashes/CHECKs. See crbug.com/104851 144 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { 145 ProfileManager* profile_manager = g_browser_process->profile_manager(); 146 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 147 148 // Create an additional profile. 149 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); 150 profile_manager->CreateProfileAsync(new_path, 151 base::Bind(&OnUnblockOnProfileCreation), 152 base::string16(), base::string16(), 153 std::string()); 154 155 // Spin to allow profile creation to take place, loop is terminated 156 // by OnUnblockOnProfileCreation when the profile is created. 157 content::RunMessageLoop(); 158 159 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 160 161 // Delete all profiles. 162 base::FilePath profile_path1 = cache.GetPathOfProfileAtIndex(0); 163 base::FilePath profile_path2 = cache.GetPathOfProfileAtIndex(1); 164 EXPECT_FALSE(profile_path1.empty()); 165 EXPECT_FALSE(profile_path2.empty()); 166 profile_manager->ScheduleProfileForDeletion(profile_path1, 167 ProfileManager::CreateCallback()); 168 profile_manager->ScheduleProfileForDeletion(profile_path2, 169 ProfileManager::CreateCallback()); 170 171 // Spin things so deletion can take place. 172 content::RunAllPendingInMessageLoop(); 173 174 // Make sure a new profile was created automatically. 175 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 176 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 177 EXPECT_NE(new_profile_path, profile_path1); 178 EXPECT_NE(new_profile_path, profile_path2); 179 180 // Make sure that last used profile preference is set correctly. 181 Profile* last_used = ProfileManager::GetLastUsedProfile(); 182 EXPECT_EQ(new_profile_path, last_used->GetPath()); 183 } 184 #endif // OS_MACOSX 185 186 #if defined(OS_CHROMEOS) 187 188 class ProfileManagerCrOSBrowserTest : public ProfileManagerBrowserTest { 189 protected: 190 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 191 // Use a user hash other than the default chrome::kTestUserProfileDir 192 // so that the prefix case is tested. 193 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, 194 "test-user-hash"); 195 } 196 }; 197 198 IN_PROC_BROWSER_TEST_F(ProfileManagerCrOSBrowserTest, GetLastUsedProfile) { 199 // Make sure that last used profile is correct. 200 Profile* last_used_profile = ProfileManager::GetLastUsedProfile(); 201 EXPECT_TRUE(last_used_profile != NULL); 202 203 base::FilePath profile_path; 204 PathService::Get(chrome::DIR_USER_DATA, &profile_path); 205 206 profile_path = profile_path.AppendASCII( 207 std::string(chrome::kProfileDirPrefix) + "test-user-hash"); 208 EXPECT_EQ(profile_path.value(), last_used_profile->GetPath().value()); 209 } 210 211 #endif // OS_CHROMEOS 212 213 // Times out (http://crbug.com/159002) 214 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 215 DISABLED_CreateProfileWithCallback) { 216 ProfileManager* profile_manager = g_browser_process->profile_manager(); 217 218 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 219 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 220 221 // Create a profile, make sure callback is invoked before any callbacks are 222 // invoked (so they can do things like sign in the profile, etc). 223 ProfileManager::CreateMultiProfileAsync( 224 base::string16(), // name 225 base::string16(), // icon url 226 base::Bind(ProfileCreationComplete), 227 std::string()); 228 // Wait for profile to finish loading. 229 content::RunMessageLoop(); 230 EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U); 231 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 232 233 // Now close all browser windows. 234 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 235 for (std::vector<Profile*>::const_iterator it = profiles.begin(); 236 it != profiles.end(); ++it) { 237 BrowserList::CloseAllBrowsersWithProfile(*it); 238 } 239 } 240 241 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 242 SwitchToProfile) { 243 #if defined(OS_WIN) && defined(USE_ASH) 244 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 245 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 246 return; 247 #endif 248 249 // If multiprofile mode is not enabled, you can't switch between profiles. 250 if (!profiles::IsMultipleProfilesEnabled()) 251 return; 252 253 ProfileManager* profile_manager = g_browser_process->profile_manager(); 254 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 255 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 256 257 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 258 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 259 260 // Create an additional profile. 261 base::FilePath path_profile2 = 262 profile_manager->GenerateNextProfileDirectoryPath(); 263 profile_manager->CreateProfileAsync(path_profile2, 264 base::Bind(&OnUnblockOnProfileCreation), 265 base::string16(), base::string16(), 266 std::string()); 267 268 // Spin to allow profile creation to take place, loop is terminated 269 // by OnUnblockOnProfileCreation when the profile is created. 270 content::RunMessageLoop(); 271 272 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 273 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 274 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 275 EXPECT_EQ(1U, browser_list->size()); 276 277 // Open a browser window for the first profile. 278 profiles::SwitchToProfile(path_profile1, desktop_type, false, 279 kOnProfileSwitchDoNothing, 280 ProfileMetrics::SWITCH_PROFILE_ICON); 281 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 282 EXPECT_EQ(1U, browser_list->size()); 283 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 284 285 // Open a browser window for the second profile. 286 profiles::SwitchToProfile(path_profile2, desktop_type, false, 287 kOnProfileSwitchDoNothing, 288 ProfileMetrics::SWITCH_PROFILE_ICON); 289 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 290 EXPECT_EQ(2U, browser_list->size()); 291 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 292 293 // Switch to the first profile without opening a new window. 294 profiles::SwitchToProfile(path_profile1, desktop_type, false, 295 kOnProfileSwitchDoNothing, 296 ProfileMetrics::SWITCH_PROFILE_ICON); 297 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 298 EXPECT_EQ(2U, browser_list->size()); 299 300 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 301 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 302 } 303 304 // This test used to be flakily timing out on Windows: http://crbug.com/314905. 305 // If this happens again please make it a MAYBE_ test and reopen that bug. 306 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, EphemeralProfile) { 307 #if defined(OS_WIN) && defined(USE_ASH) 308 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 309 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 310 return; 311 #endif 312 313 // If multiprofile mode is not enabled, you can't switch between profiles. 314 if (!profiles::IsMultipleProfilesEnabled()) 315 return; 316 317 ProfileManager* profile_manager = g_browser_process->profile_manager(); 318 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 319 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 320 321 ASSERT_EQ(1U, profile_manager->GetNumberOfProfiles()); 322 EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); 323 324 // Create an ephemeral profile. 325 base::FilePath path_profile2 = 326 profile_manager->GenerateNextProfileDirectoryPath(); 327 profile_manager->CreateProfileAsync( 328 path_profile2, 329 base::Bind(&EphemeralProfileCreationComplete), 330 base::string16(), base::string16(), std::string()); 331 332 // Spin to allow profile creation to take place. 333 content::RunMessageLoop(); 334 335 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 336 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 337 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 338 EXPECT_EQ(1U, browser_list->size()); 339 340 // Open a browser window for the second profile. 341 profiles::SwitchToProfile(path_profile2, desktop_type, false, 342 kOnProfileSwitchDoNothing, 343 ProfileMetrics::SWITCH_PROFILE_ICON); 344 EXPECT_EQ(2U, chrome::GetTotalBrowserCount()); 345 EXPECT_EQ(2U, browser_list->size()); 346 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 347 348 // Create a second window for the ephemeral profile. 349 profiles::SwitchToProfile(path_profile2, desktop_type, true, 350 kOnProfileSwitchDoNothing, 351 ProfileMetrics::SWITCH_PROFILE_ICON); 352 EXPECT_EQ(3U, chrome::GetTotalBrowserCount()); 353 EXPECT_EQ(3U, browser_list->size()); 354 355 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 356 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 357 EXPECT_EQ(path_profile2, browser_list->get(2)->profile()->GetPath()); 358 359 // Closing the first window of the ephemeral profile should not delete it. 360 browser_list->get(2)->window()->Close(); 361 content::RunAllPendingInMessageLoop(); 362 EXPECT_EQ(2U, browser_list->size()); 363 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 364 365 // The second should though. 366 browser_list->get(1)->window()->Close(); 367 content::RunAllPendingInMessageLoop(); 368 EXPECT_EQ(1U, browser_list->size()); 369 ASSERT_EQ(1U, cache.GetNumberOfProfiles()); 370 } 371 372