Home | History | Annotate | Download | only in profiles
      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