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/chrome_switches.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 25#if defined(OS_CHROMEOS) 26#include "base/path_service.h" 27#include "chrome/common/chrome_constants.h" 28#include "chrome/common/chrome_paths.h" 29#include "testing/gtest/include/gtest/gtest.h" 30#endif 31 32namespace { 33 34const profiles::ProfileSwitchingDoneCallback kOnProfileSwitchDoNothing; 35 36// An observer that returns back to test code after a new profile is 37// initialized. 38void OnUnblockOnProfileCreation(Profile* profile, 39 Profile::CreateStatus status) { 40 if (status == Profile::CREATE_STATUS_INITIALIZED) 41 base::MessageLoop::current()->Quit(); 42} 43 44void 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 54void 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 61class 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. 95class ProfileManagerBrowserTest : public InProcessBrowserTest { 96}; 97 98#if defined(OS_MACOSX) 99 100// Delete single profile and make sure a new one is created. 101IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { 102 ProfileManager* profile_manager = g_browser_process->profile_manager(); 103 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 104 ProfileRemovalObserver observer; 105 106 // We should start out with 1 profile. 107 ASSERT_EQ(cache.GetNumberOfProfiles(), 1U); 108 109 // Delete singleton profile. 110 base::FilePath singleton_profile_path = cache.GetPathOfProfileAtIndex(0); 111 EXPECT_FALSE(singleton_profile_path.empty()); 112 profile_manager->ScheduleProfileForDeletion(singleton_profile_path, 113 ProfileManager::CreateCallback()); 114 115 // Spin things till profile is actually deleted. 116 content::RunAllPendingInMessageLoop(); 117 118 // Make sure a new profile was created automatically. 119 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 120 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 121 EXPECT_NE(new_profile_path, singleton_profile_path); 122 123 // Make sure that last used profile preference is set correctly. 124 Profile* last_used = ProfileManager::GetLastUsedProfile(); 125 EXPECT_EQ(new_profile_path, last_used->GetPath()); 126 127 // Make sure the last used profile was set correctly before the notification 128 // was sent. 129 std::string last_used_profile_name = 130 last_used->GetPath().BaseName().MaybeAsASCII(); 131 EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name()); 132} 133 134// Delete all profiles in a multi profile setup and make sure a new one is 135// created. 136// Crashes/CHECKs. See crbug.com/104851 137IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { 138 ProfileManager* profile_manager = g_browser_process->profile_manager(); 139 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 140 141 // Create an additional profile. 142 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); 143 profile_manager->CreateProfileAsync(new_path, 144 base::Bind(&OnUnblockOnProfileCreation), 145 base::string16(), base::string16(), 146 std::string()); 147 148 // Spin to allow profile creation to take place, loop is terminated 149 // by OnUnblockOnProfileCreation when the profile is created. 150 content::RunMessageLoop(); 151 152 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 153 154 // Delete all profiles. 155 base::FilePath profile_path1 = cache.GetPathOfProfileAtIndex(0); 156 base::FilePath profile_path2 = cache.GetPathOfProfileAtIndex(1); 157 EXPECT_FALSE(profile_path1.empty()); 158 EXPECT_FALSE(profile_path2.empty()); 159 profile_manager->ScheduleProfileForDeletion(profile_path1, 160 ProfileManager::CreateCallback()); 161 profile_manager->ScheduleProfileForDeletion(profile_path2, 162 ProfileManager::CreateCallback()); 163 164 // Spin things so deletion can take place. 165 content::RunAllPendingInMessageLoop(); 166 167 // Make sure a new profile was created automatically. 168 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 169 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 170 EXPECT_NE(new_profile_path, profile_path1); 171 EXPECT_NE(new_profile_path, profile_path2); 172 173 // Make sure that last used profile preference is set correctly. 174 Profile* last_used = ProfileManager::GetLastUsedProfile(); 175 EXPECT_EQ(new_profile_path, last_used->GetPath()); 176} 177#endif // OS_MACOSX 178 179#if defined(OS_CHROMEOS) 180 181class ProfileManagerCrOSBrowserTest : public ProfileManagerBrowserTest, 182 public testing::WithParamInterface<bool> { 183 protected: 184 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 185 if (GetParam()) 186 command_line->AppendSwitch(::switches::kMultiProfiles); 187 } 188}; 189 190IN_PROC_BROWSER_TEST_P(ProfileManagerCrOSBrowserTest, GetLastUsedProfile) { 191 // Make sure that last used profile is correct. 192 Profile* last_used_profile = ProfileManager::GetLastUsedProfile(); 193 EXPECT_TRUE(last_used_profile != NULL); 194 195 base::FilePath profile_path; 196 PathService::Get(chrome::DIR_USER_DATA, &profile_path); 197 198 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 199 if (command_line.HasSwitch(switches::kMultiProfiles)) { 200 profile_path = profile_path.Append(base::FilePath( 201 std::string(chrome::kProfileDirPrefix) + chrome::kTestUserProfileDir)); 202 } else { 203 profile_path = profile_path.Append( 204 base::FilePath(chrome::kTestUserProfileDir)); 205 } 206 EXPECT_EQ(profile_path.value(), last_used_profile->GetPath().value()); 207} 208 209INSTANTIATE_TEST_CASE_P(ProfileManagerCrOSBrowserTestInstantiation, 210 ProfileManagerCrOSBrowserTest, 211 testing::Bool()); 212 213#endif // OS_CHROMEOS 214 215// Times out (http://crbug.com/159002) 216IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 217 DISABLED_CreateProfileWithCallback) { 218 ProfileManager* profile_manager = g_browser_process->profile_manager(); 219 220 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 221 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 222 223 // Create a profile, make sure callback is invoked before any callbacks are 224 // invoked (so they can do things like sign in the profile, etc). 225 ProfileManager::CreateMultiProfileAsync( 226 base::string16(), // name 227 base::string16(), // icon url 228 base::Bind(ProfileCreationComplete), 229 std::string()); 230 // Wait for profile to finish loading. 231 content::RunMessageLoop(); 232 EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U); 233 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 234 235 // Now close all browser windows. 236 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 237 for (std::vector<Profile*>::const_iterator it = profiles.begin(); 238 it != profiles.end(); ++it) { 239 BrowserList::CloseAllBrowsersWithProfile(*it); 240 } 241} 242 243IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 244 SwitchToProfile) { 245#if defined(OS_WIN) && defined(USE_ASH) 246 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 247 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 248 return; 249#endif 250 251 // If multiprofile mode is not enabled, you can't switch between profiles. 252 if (!profiles::IsMultipleProfilesEnabled()) 253 return; 254 255 ProfileManager* profile_manager = g_browser_process->profile_manager(); 256 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 257 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 258 259 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 260 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 261 262 // Create an additional profile. 263 base::FilePath path_profile2 = 264 profile_manager->GenerateNextProfileDirectoryPath(); 265 profile_manager->CreateProfileAsync(path_profile2, 266 base::Bind(&OnUnblockOnProfileCreation), 267 base::string16(), base::string16(), 268 std::string()); 269 270 // Spin to allow profile creation to take place, loop is terminated 271 // by OnUnblockOnProfileCreation when the profile is created. 272 content::RunMessageLoop(); 273 274 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 275 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 276 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 277 EXPECT_EQ(1U, browser_list->size()); 278 279 // Open a browser window for the first profile. 280 profiles::SwitchToProfile(path_profile1, desktop_type, false, 281 kOnProfileSwitchDoNothing); 282 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 283 EXPECT_EQ(1U, browser_list->size()); 284 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 285 286 // Open a browser window for the second profile. 287 profiles::SwitchToProfile(path_profile2, desktop_type, false, 288 kOnProfileSwitchDoNothing); 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 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 297 EXPECT_EQ(2U, browser_list->size()); 298 299 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 300 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 301} 302 303// This test used to be flakily timing out on Windows: http://crbug.com/314905. 304// If this happens again please make it a MAYBE_ test and reopen that bug. 305IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, EphemeralProfile) { 306#if defined(OS_WIN) && defined(USE_ASH) 307 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 308 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 309 return; 310#endif 311 312 // If multiprofile mode is not enabled, you can't switch between profiles. 313 if (!profiles::IsMultipleProfilesEnabled()) 314 return; 315 316 ProfileManager* profile_manager = g_browser_process->profile_manager(); 317 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 318 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 319 320 ASSERT_EQ(1U, profile_manager->GetNumberOfProfiles()); 321 EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); 322 323 // Create an ephemeral profile. 324 base::FilePath path_profile2 = 325 profile_manager->GenerateNextProfileDirectoryPath(); 326 profile_manager->CreateProfileAsync( 327 path_profile2, 328 base::Bind(&EphemeralProfileCreationComplete), 329 base::string16(), base::string16(), std::string()); 330 331 // Spin to allow profile creation to take place. 332 content::RunMessageLoop(); 333 334 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 335 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 336 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 337 EXPECT_EQ(1U, browser_list->size()); 338 339 // Open a browser window for the second profile. 340 profiles::SwitchToProfile(path_profile2, desktop_type, false, 341 kOnProfileSwitchDoNothing); 342 EXPECT_EQ(2U, chrome::GetTotalBrowserCount()); 343 EXPECT_EQ(2U, browser_list->size()); 344 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 345 346 // Create a second window for the ephemeral profile. 347 profiles::SwitchToProfile(path_profile2, desktop_type, true, 348 kOnProfileSwitchDoNothing); 349 EXPECT_EQ(3U, chrome::GetTotalBrowserCount()); 350 EXPECT_EQ(3U, browser_list->size()); 351 352 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 353 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 354 EXPECT_EQ(path_profile2, browser_list->get(2)->profile()->GetPath()); 355 356 // Closing the first window of the ephemeral profile should not delete it. 357 browser_list->get(2)->window()->Close(); 358 content::RunAllPendingInMessageLoop(); 359 EXPECT_EQ(2U, browser_list->size()); 360 ASSERT_EQ(2U, cache.GetNumberOfProfiles()); 361 362 // The second should though. 363 browser_list->get(1)->window()->Close(); 364 content::RunAllPendingInMessageLoop(); 365 EXPECT_EQ(1U, browser_list->size()); 366 ASSERT_EQ(1U, cache.GetNumberOfProfiles()); 367} 368