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/host_desktop.h" 17 #include "chrome/common/pref_names.h" 18 #include "chrome/test/base/in_process_browser_test.h" 19 #include "chrome/test/base/test_switches.h" 20 #include "chrome/test/base/testing_browser_process.h" 21 #include "chrome/test/base/ui_test_utils.h" 22 23 namespace { 24 25 // An observer that returns back to test code after a new profile is 26 // initialized. 27 void OnUnblockOnProfileCreation(Profile* profile, 28 Profile::CreateStatus status) { 29 if (status == Profile::CREATE_STATUS_INITIALIZED) 30 base::MessageLoop::current()->Quit(); 31 } 32 33 void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) { 34 ASSERT_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL); 35 ASSERT_NE(status, Profile::CREATE_STATUS_REMOTE_FAIL); 36 // No browser should have been created for this profile yet. 37 EXPECT_EQ(chrome::GetTotalBrowserCountForProfile(profile), 0U); 38 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 39 if (status == Profile::CREATE_STATUS_INITIALIZED) 40 base::MessageLoop::current()->Quit(); 41 } 42 43 class ProfileRemovalObserver : public ProfileInfoCacheObserver { 44 public: 45 ProfileRemovalObserver() { 46 g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver( 47 this); 48 } 49 50 virtual ~ProfileRemovalObserver() { 51 g_browser_process->profile_manager()->GetProfileInfoCache().RemoveObserver( 52 this); 53 } 54 55 std::string last_used_profile_name() { return last_used_profile_name_; } 56 57 // ProfileInfoCacheObserver overrides: 58 virtual void OnProfileWillBeRemoved( 59 const base::FilePath& profile_path) OVERRIDE { 60 last_used_profile_name_ = g_browser_process->local_state()->GetString( 61 prefs::kProfileLastUsed); 62 } 63 64 private: 65 std::string last_used_profile_name_; 66 67 DISALLOW_COPY_AND_ASSIGN(ProfileRemovalObserver); 68 }; 69 70 } // namespace 71 72 // This file contains tests for the ProfileManager that require a heavyweight 73 // InProcessBrowserTest. These include tests involving profile deletion. 74 75 // TODO(jeremy): crbug.com/103355 - These tests should be enabled on all 76 // platforms. 77 class ProfileManagerBrowserTest : public InProcessBrowserTest { 78 }; 79 80 #if defined(OS_MACOSX) 81 82 // Delete single profile and make sure a new one is created. 83 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { 84 ProfileManager* profile_manager = g_browser_process->profile_manager(); 85 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 86 ProfileRemovalObserver observer; 87 88 // We should start out with 1 profile. 89 ASSERT_EQ(cache.GetNumberOfProfiles(), 1U); 90 91 // Delete singleton profile. 92 base::FilePath singleton_profile_path = cache.GetPathOfProfileAtIndex(0); 93 EXPECT_FALSE(singleton_profile_path.empty()); 94 profile_manager->ScheduleProfileForDeletion(singleton_profile_path, 95 ProfileManager::CreateCallback()); 96 97 // Spin things till profile is actually deleted. 98 content::RunAllPendingInMessageLoop(); 99 100 // Make sure a new profile was created automatically. 101 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 102 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 103 EXPECT_NE(new_profile_path, singleton_profile_path); 104 105 // Make sure that last used profile preference is set correctly. 106 Profile* last_used = ProfileManager::GetLastUsedProfile(); 107 EXPECT_EQ(new_profile_path, last_used->GetPath()); 108 109 // Make sure the last used profile was set correctly before the notification 110 // was sent. 111 std::string last_used_profile_name = 112 last_used->GetPath().BaseName().MaybeAsASCII(); 113 EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name()); 114 } 115 116 // Delete all profiles in a multi profile setup and make sure a new one is 117 // created. 118 // Crashes/CHECKs. See crbug.com/104851 119 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { 120 ProfileManager* profile_manager = g_browser_process->profile_manager(); 121 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 122 123 // Create an additional profile. 124 base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); 125 profile_manager->CreateProfileAsync(new_path, 126 base::Bind(&OnUnblockOnProfileCreation), 127 string16(), string16(), std::string()); 128 129 // Spin to allow profile creation to take place, loop is terminated 130 // by OnUnblockOnProfileCreation when the profile is created. 131 content::RunMessageLoop(); 132 133 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 134 135 // Delete all profiles. 136 base::FilePath profile_path1 = cache.GetPathOfProfileAtIndex(0); 137 base::FilePath profile_path2 = cache.GetPathOfProfileAtIndex(1); 138 EXPECT_FALSE(profile_path1.empty()); 139 EXPECT_FALSE(profile_path2.empty()); 140 profile_manager->ScheduleProfileForDeletion(profile_path1, 141 ProfileManager::CreateCallback()); 142 profile_manager->ScheduleProfileForDeletion(profile_path2, 143 ProfileManager::CreateCallback()); 144 145 // Spin things so deletion can take place. 146 content::RunAllPendingInMessageLoop(); 147 148 // Make sure a new profile was created automatically. 149 EXPECT_EQ(cache.GetNumberOfProfiles(), 1U); 150 base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0); 151 EXPECT_NE(new_profile_path, profile_path1); 152 EXPECT_NE(new_profile_path, profile_path2); 153 154 // Make sure that last used profile preference is set correctly. 155 Profile* last_used = ProfileManager::GetLastUsedProfile(); 156 EXPECT_EQ(new_profile_path, last_used->GetPath()); 157 } 158 #endif // OS_MACOSX 159 160 // Times out (http://crbug.com/159002) 161 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 162 DISABLED_CreateProfileWithCallback) { 163 ProfileManager* profile_manager = g_browser_process->profile_manager(); 164 165 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 166 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 167 168 // Create a profile, make sure callback is invoked before any callbacks are 169 // invoked (so they can do things like sign in the profile, etc). 170 ProfileManager::CreateMultiProfileAsync( 171 string16(), // name 172 string16(), // icon url 173 base::Bind(ProfileCreationComplete), 174 std::string()); 175 // Wait for profile to finish loading. 176 content::RunMessageLoop(); 177 EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U); 178 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 179 180 // Now close all browser windows. 181 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 182 for (std::vector<Profile*>::const_iterator it = profiles.begin(); 183 it != profiles.end(); ++it) { 184 BrowserList::CloseAllBrowsersWithProfile(*it); 185 } 186 } 187 188 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, 189 SwitchToProfile) { 190 #if defined(OS_WIN) && defined(USE_ASH) 191 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 192 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 193 return; 194 #endif 195 196 // If multiprofile mode is not enabled, you can't switch between profiles. 197 if (!profiles::IsMultipleProfilesEnabled()) 198 return; 199 200 ProfileManager* profile_manager = g_browser_process->profile_manager(); 201 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 202 base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0); 203 204 ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U); 205 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 206 207 // Create an additional profile. 208 base::FilePath path_profile2 = 209 profile_manager->GenerateNextProfileDirectoryPath(); 210 profile_manager->CreateProfileAsync(path_profile2, 211 base::Bind(&OnUnblockOnProfileCreation), 212 string16(), string16(), std::string()); 213 214 // Spin to allow profile creation to take place, loop is terminated 215 // by OnUnblockOnProfileCreation when the profile is created. 216 content::RunMessageLoop(); 217 218 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 219 BrowserList* browser_list = BrowserList::GetInstance(desktop_type); 220 ASSERT_EQ(cache.GetNumberOfProfiles(), 2U); 221 EXPECT_EQ(1U, browser_list->size()); 222 223 // Open a browser window for the first profile. 224 profiles::SwitchToProfile(path_profile1, desktop_type, false); 225 EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); 226 EXPECT_EQ(1U, browser_list->size()); 227 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 228 229 // Open a browser window for the second profile. 230 profiles::SwitchToProfile(path_profile2, desktop_type, false); 231 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 232 EXPECT_EQ(2U, browser_list->size()); 233 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 234 235 // Switch to the first profile without opening a new window. 236 profiles::SwitchToProfile(path_profile1, desktop_type, false); 237 EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U); 238 EXPECT_EQ(2U, browser_list->size()); 239 240 EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath()); 241 EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath()); 242 } 243