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/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 
     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 };
     97 
     98 #if defined(OS_MACOSX)
     99 
    100 // Delete single profile and make sure a new one is created.
    101 IN_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
    137 IN_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 
    181 class 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 
    190 IN_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 
    209 INSTANTIATE_TEST_CASE_P(ProfileManagerCrOSBrowserTestInstantiation,
    210                         ProfileManagerCrOSBrowserTest,
    211                         testing::Bool());
    212 
    213 #endif  // OS_CHROMEOS
    214 
    215 // Times out (http://crbug.com/159002)
    216 IN_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 
    243 IN_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.
    305 IN_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