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/password_manager/password_store_factory.h"
     10 #include "chrome/browser/profiles/profile_info_cache.h"
     11 #include "chrome/browser/profiles/profile_info_cache_observer.h"
     12 #include "chrome/browser/profiles/profile_manager.h"
     13 #include "chrome/browser/profiles/profile_window.h"
     14 #include "chrome/browser/profiles/profiles_state.h"
     15 #include "chrome/browser/ui/browser_finder.h"
     16 #include "chrome/browser/ui/browser_list.h"
     17 #include "chrome/browser/ui/browser_window.h"
     18 #include "chrome/browser/ui/host_desktop.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 #include "components/autofill/core/common/password_form.h"
     25 #include "components/password_manager/core/browser/password_store.h"
     26 #include "components/password_manager/core/browser/password_store_consumer.h"
     27 
     28 #if defined(OS_CHROMEOS)
     29 #include "base/path_service.h"
     30 #include "chrome/common/chrome_constants.h"
     31 #include "chrome/common/chrome_paths.h"
     32 #include "chromeos/chromeos_switches.h"
     33 #include "testing/gtest/include/gtest/gtest.h"
     34 #endif
     35 
     36 namespace {
     37 
     38 const ProfileManager::CreateCallback kOnProfileSwitchDoNothing;
     39 
     40 // An observer that returns back to test code after a new profile is
     41 // initialized.
     42 void OnUnblockOnProfileCreation(Profile* profile,
     43                                 Profile::CreateStatus status) {
     44   if (status == Profile::CREATE_STATUS_INITIALIZED)
     45     base::MessageLoop::current()->Quit();
     46 }
     47 
     48 void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) {
     49   ASSERT_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL);
     50   ASSERT_NE(status, Profile::CREATE_STATUS_REMOTE_FAIL);
     51   // No browser should have been created for this profile yet.
     52   EXPECT_EQ(chrome::GetTotalBrowserCountForProfile(profile), 0U);
     53   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
     54   if (status == Profile::CREATE_STATUS_INITIALIZED)
     55     base::MessageLoop::current()->Quit();
     56 }
     57 
     58 void EphemeralProfileCreationComplete(Profile* profile,
     59                                       Profile::CreateStatus status) {
     60   if (status == Profile::CREATE_STATUS_INITIALIZED)
     61     profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true);
     62   ProfileCreationComplete(profile, status);
     63 }
     64 
     65 class ProfileRemovalObserver : public ProfileInfoCacheObserver {
     66  public:
     67   ProfileRemovalObserver() {
     68     g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(
     69         this);
     70   }
     71 
     72   virtual ~ProfileRemovalObserver() {
     73     g_browser_process->profile_manager()->GetProfileInfoCache().RemoveObserver(
     74         this);
     75   }
     76 
     77   std::string last_used_profile_name() { return last_used_profile_name_; }
     78 
     79   // ProfileInfoCacheObserver overrides:
     80   virtual void OnProfileWillBeRemoved(
     81       const base::FilePath& profile_path) OVERRIDE {
     82     last_used_profile_name_ = g_browser_process->local_state()->GetString(
     83         prefs::kProfileLastUsed);
     84   }
     85 
     86  private:
     87   std::string last_used_profile_name_;
     88 
     89   DISALLOW_COPY_AND_ASSIGN(ProfileRemovalObserver);
     90 };
     91 
     92 // The class serves to retrieve passwords from PasswordStore asynchronously. It
     93 // used by ProfileManagerBrowserTest.DeletePasswords on some platforms.
     94 class PasswordStoreConsumerVerifier :
     95     public password_manager::PasswordStoreConsumer {
     96  public:
     97   PasswordStoreConsumerVerifier() : called_(false) {}
     98 
     99   virtual void OnGetPasswordStoreResults(
    100       const std::vector<autofill::PasswordForm*>& results) OVERRIDE {
    101     EXPECT_FALSE(called_);
    102     called_ = true;
    103     password_entries_.clear();
    104     password_entries_.assign(results.begin(), results.end());
    105   }
    106 
    107   bool IsCalled() const { return called_; }
    108 
    109   const std::vector<autofill::PasswordForm*>& GetPasswords() const {
    110     return password_entries_.get();
    111   }
    112  private:
    113   ScopedVector<autofill::PasswordForm> password_entries_;
    114   bool called_;
    115 };
    116 
    117 } // namespace
    118 
    119 // This file contains tests for the ProfileManager that require a heavyweight
    120 // InProcessBrowserTest.  These include tests involving profile deletion.
    121 
    122 // TODO(jeremy): crbug.com/103355 - These tests should be enabled on all
    123 // platforms.
    124 class ProfileManagerBrowserTest : public InProcessBrowserTest {
    125  protected:
    126   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    127 #if defined(OS_CHROMEOS)
    128     command_line->AppendSwitch(
    129         chromeos::switches::kIgnoreUserProfileMappingForTests);
    130 #endif
    131   }
    132 };
    133 
    134 #if defined(OS_MACOSX)
    135 
    136 // Delete single profile and make sure a new one is created.
    137 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) {
    138   ProfileManager* profile_manager = g_browser_process->profile_manager();
    139   ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
    140   ProfileRemovalObserver observer;
    141 
    142   // We should start out with 1 profile.
    143   ASSERT_EQ(cache.GetNumberOfProfiles(), 1U);
    144 
    145   // Delete singleton profile.
    146   base::FilePath singleton_profile_path = cache.GetPathOfProfileAtIndex(0);
    147   EXPECT_FALSE(singleton_profile_path.empty());
    148   profile_manager->ScheduleProfileForDeletion(singleton_profile_path,
    149                                               ProfileManager::CreateCallback());
    150 
    151   // Spin things till profile is actually deleted.
    152   content::RunAllPendingInMessageLoop();
    153 
    154   // Make sure a new profile was created automatically.
    155   EXPECT_EQ(cache.GetNumberOfProfiles(), 1U);
    156   base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0);
    157   EXPECT_NE(new_profile_path, singleton_profile_path);
    158 
    159   // Make sure that last used profile preference is set correctly.
    160   Profile* last_used = ProfileManager::GetLastUsedProfile();
    161   EXPECT_EQ(new_profile_path, last_used->GetPath());
    162 
    163   // Make sure the last used profile was set correctly before the notification
    164   // was sent.
    165   std::string last_used_profile_name =
    166       last_used->GetPath().BaseName().MaybeAsASCII();
    167   EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name());
    168 }
    169 
    170 // Delete all profiles in a multi profile setup and make sure a new one is
    171 // created.
    172 // Crashes/CHECKs. See crbug.com/104851
    173 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) {
    174   ProfileManager* profile_manager = g_browser_process->profile_manager();
    175   ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
    176 
    177   // Create an additional profile.
    178   base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
    179   profile_manager->CreateProfileAsync(new_path,
    180                                       base::Bind(&OnUnblockOnProfileCreation),
    181                                       base::string16(), base::string16(),
    182                                       std::string());
    183 
    184   // Spin to allow profile creation to take place, loop is terminated
    185   // by OnUnblockOnProfileCreation when the profile is created.
    186   content::RunMessageLoop();
    187 
    188   ASSERT_EQ(cache.GetNumberOfProfiles(), 2U);
    189 
    190   // Delete all profiles.
    191   base::FilePath profile_path1 = cache.GetPathOfProfileAtIndex(0);
    192   base::FilePath profile_path2 = cache.GetPathOfProfileAtIndex(1);
    193   EXPECT_FALSE(profile_path1.empty());
    194   EXPECT_FALSE(profile_path2.empty());
    195   profile_manager->ScheduleProfileForDeletion(profile_path1,
    196                                               ProfileManager::CreateCallback());
    197   profile_manager->ScheduleProfileForDeletion(profile_path2,
    198                                               ProfileManager::CreateCallback());
    199 
    200   // Spin things so deletion can take place.
    201   content::RunAllPendingInMessageLoop();
    202 
    203   // Make sure a new profile was created automatically.
    204   EXPECT_EQ(cache.GetNumberOfProfiles(), 1U);
    205   base::FilePath new_profile_path = cache.GetPathOfProfileAtIndex(0);
    206   EXPECT_NE(new_profile_path, profile_path1);
    207   EXPECT_NE(new_profile_path, profile_path2);
    208 
    209   // Make sure that last used profile preference is set correctly.
    210   Profile* last_used = ProfileManager::GetLastUsedProfile();
    211   EXPECT_EQ(new_profile_path, last_used->GetPath());
    212 }
    213 #endif  // OS_MACOSX
    214 
    215 #if defined(OS_CHROMEOS)
    216 
    217 class ProfileManagerCrOSBrowserTest : public ProfileManagerBrowserTest {
    218  protected:
    219   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    220     // Use a user hash other than the default chrome::kTestUserProfileDir
    221     // so that the prefix case is tested.
    222     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
    223                                     "test-user-hash");
    224   }
    225 };
    226 
    227 IN_PROC_BROWSER_TEST_F(ProfileManagerCrOSBrowserTest, GetLastUsedProfile) {
    228   // Make sure that last used profile is correct.
    229   Profile* last_used_profile = ProfileManager::GetLastUsedProfile();
    230   EXPECT_TRUE(last_used_profile != NULL);
    231 
    232   base::FilePath profile_path;
    233   PathService::Get(chrome::DIR_USER_DATA, &profile_path);
    234 
    235   profile_path = profile_path.AppendASCII(
    236       std::string(chrome::kProfileDirPrefix) + "test-user-hash");
    237   EXPECT_EQ(profile_path.value(), last_used_profile->GetPath().value());
    238 }
    239 
    240 #endif  // OS_CHROMEOS
    241 
    242 // Times out (http://crbug.com/159002)
    243 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest,
    244                        DISABLED_CreateProfileWithCallback) {
    245   ProfileManager* profile_manager = g_browser_process->profile_manager();
    246 
    247   ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
    248   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
    249 
    250   // Create a profile, make sure callback is invoked before any callbacks are
    251   // invoked (so they can do things like sign in the profile, etc).
    252   ProfileManager::CreateMultiProfileAsync(
    253       base::string16(), // name
    254       base::string16(), // icon url
    255       base::Bind(ProfileCreationComplete),
    256       std::string());
    257   // Wait for profile to finish loading.
    258   content::RunMessageLoop();
    259   EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U);
    260   EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U);
    261 
    262   // Now close all browser windows.
    263   std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
    264   for (std::vector<Profile*>::const_iterator it = profiles.begin();
    265        it != profiles.end(); ++it) {
    266     BrowserList::CloseAllBrowsersWithProfile(*it);
    267   }
    268 }
    269 
    270 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest,
    271                        SwitchToProfile) {
    272 #if defined(OS_WIN) && defined(USE_ASH)
    273   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    274   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    275     return;
    276 #endif
    277 
    278   // If multiprofile mode is not enabled, you can't switch between profiles.
    279   if (!profiles::IsMultipleProfilesEnabled())
    280     return;
    281 
    282   ProfileManager* profile_manager = g_browser_process->profile_manager();
    283   ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
    284   base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0);
    285 
    286   ASSERT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
    287   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
    288 
    289   // Create an additional profile.
    290   base::FilePath path_profile2 =
    291       profile_manager->GenerateNextProfileDirectoryPath();
    292   profile_manager->CreateProfileAsync(path_profile2,
    293                                       base::Bind(&OnUnblockOnProfileCreation),
    294                                       base::string16(), base::string16(),
    295                                       std::string());
    296 
    297   // Spin to allow profile creation to take place, loop is terminated
    298   // by OnUnblockOnProfileCreation when the profile is created.
    299   content::RunMessageLoop();
    300 
    301   chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
    302   BrowserList* browser_list = BrowserList::GetInstance(desktop_type);
    303   ASSERT_EQ(cache.GetNumberOfProfiles(), 2U);
    304   EXPECT_EQ(1U, browser_list->size());
    305 
    306   // Open a browser window for the first profile.
    307   profiles::SwitchToProfile(path_profile1, desktop_type, false,
    308                             kOnProfileSwitchDoNothing,
    309                             ProfileMetrics::SWITCH_PROFILE_ICON);
    310   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
    311   EXPECT_EQ(1U, browser_list->size());
    312   EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
    313 
    314   // Open a browser window for the second profile.
    315   profiles::SwitchToProfile(path_profile2, desktop_type, false,
    316                             kOnProfileSwitchDoNothing,
    317                             ProfileMetrics::SWITCH_PROFILE_ICON);
    318   EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U);
    319   EXPECT_EQ(2U, browser_list->size());
    320   EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
    321 
    322   // Switch to the first profile without opening a new window.
    323   profiles::SwitchToProfile(path_profile1, desktop_type, false,
    324                             kOnProfileSwitchDoNothing,
    325                             ProfileMetrics::SWITCH_PROFILE_ICON);
    326   EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U);
    327   EXPECT_EQ(2U, browser_list->size());
    328 
    329   EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
    330   EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
    331 }
    332 
    333 // Flakes on Windows: http://crbug.com/314905
    334 #if defined(OS_WIN)
    335 #define MAYBE_EphemeralProfile DISABLED_EphemeralProfile
    336 #else
    337 #define MAYBE_EphemeralProfile EphemeralProfile
    338 #endif
    339 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, MAYBE_EphemeralProfile) {
    340 #if defined(OS_WIN) && defined(USE_ASH)
    341   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
    342   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
    343     return;
    344 #endif
    345 
    346   // If multiprofile mode is not enabled, you can't switch between profiles.
    347   if (!profiles::IsMultipleProfilesEnabled())
    348     return;
    349 
    350   ProfileManager* profile_manager = g_browser_process->profile_manager();
    351   ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
    352   base::FilePath path_profile1 = cache.GetPathOfProfileAtIndex(0);
    353 
    354   ASSERT_EQ(1U, profile_manager->GetNumberOfProfiles());
    355   EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
    356 
    357   // Create an ephemeral profile.
    358   base::FilePath path_profile2 =
    359       profile_manager->GenerateNextProfileDirectoryPath();
    360   profile_manager->CreateProfileAsync(
    361       path_profile2,
    362       base::Bind(&EphemeralProfileCreationComplete),
    363       base::string16(), base::string16(), std::string());
    364 
    365   // Spin to allow profile creation to take place.
    366   content::RunMessageLoop();
    367 
    368   chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
    369   BrowserList* browser_list = BrowserList::GetInstance(desktop_type);
    370   ASSERT_EQ(2U, cache.GetNumberOfProfiles());
    371   EXPECT_EQ(1U, browser_list->size());
    372 
    373   // Open a browser window for the second profile.
    374   profiles::SwitchToProfile(path_profile2, desktop_type, false,
    375                             kOnProfileSwitchDoNothing,
    376                             ProfileMetrics::SWITCH_PROFILE_ICON);
    377   EXPECT_EQ(2U, chrome::GetTotalBrowserCount());
    378   EXPECT_EQ(2U, browser_list->size());
    379   EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
    380 
    381   // Create a second window for the ephemeral profile.
    382   profiles::SwitchToProfile(path_profile2, desktop_type, true,
    383                             kOnProfileSwitchDoNothing,
    384                             ProfileMetrics::SWITCH_PROFILE_ICON);
    385   EXPECT_EQ(3U, chrome::GetTotalBrowserCount());
    386   EXPECT_EQ(3U, browser_list->size());
    387 
    388   EXPECT_EQ(path_profile1, browser_list->get(0)->profile()->GetPath());
    389   EXPECT_EQ(path_profile2, browser_list->get(1)->profile()->GetPath());
    390   EXPECT_EQ(path_profile2, browser_list->get(2)->profile()->GetPath());
    391 
    392   // Closing the first window of the ephemeral profile should not delete it.
    393   browser_list->get(2)->window()->Close();
    394   content::RunAllPendingInMessageLoop();
    395   EXPECT_EQ(2U, browser_list->size());
    396   ASSERT_EQ(2U, cache.GetNumberOfProfiles());
    397 
    398   // The second should though.
    399   browser_list->get(1)->window()->Close();
    400   content::RunAllPendingInMessageLoop();
    401   EXPECT_EQ(1U, browser_list->size());
    402   ASSERT_EQ(1U, cache.GetNumberOfProfiles());
    403 }
    404 
    405 // The test makes sense on those platforms where the keychain exists.
    406 #if !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
    407 IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeletePasswords) {
    408   Profile* profile = ProfileManager::GetActiveUserProfile();
    409   ASSERT_TRUE(profile);
    410 
    411   autofill::PasswordForm form;
    412   form.scheme = autofill::PasswordForm::SCHEME_HTML;
    413   form.origin = GURL("http://accounts.google.com/LoginAuth");
    414   form.signon_realm = "http://accounts.google.com/";
    415   form.username_value = base::ASCIIToUTF16("my_username");
    416   form.password_value = base::ASCIIToUTF16("my_password");
    417   form.ssl_valid = false;
    418   form.preferred = true;
    419   form.blacklisted_by_user = false;
    420 
    421   scoped_refptr<password_manager::PasswordStore> password_store =
    422       PasswordStoreFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS)
    423           .get();
    424   ASSERT_TRUE(password_store.get());
    425 
    426   password_store->AddLogin(form);
    427   PasswordStoreConsumerVerifier verify_add;
    428   password_store->GetAutofillableLogins(&verify_add);
    429 
    430   ProfileManager* profile_manager = g_browser_process->profile_manager();
    431   profile_manager->ScheduleProfileForDeletion(profile->GetPath(),
    432                                               ProfileManager::CreateCallback());
    433   content::RunAllPendingInMessageLoop();
    434   PasswordStoreConsumerVerifier verify_delete;
    435   password_store->GetAutofillableLogins(&verify_delete);
    436 
    437   // Run the password background thread.
    438   base::RunLoop run_loop;
    439   base::Closure task = base::Bind(
    440       base::IgnoreResult(&content::BrowserThread::PostTask),
    441       content::BrowserThread::UI,
    442       FROM_HERE,
    443       run_loop.QuitClosure());
    444   EXPECT_TRUE(password_store->ScheduleTask(task));
    445   run_loop.Run();
    446 
    447   EXPECT_TRUE(verify_add.IsCalled());
    448   EXPECT_EQ(1u, verify_add.GetPasswords().size());
    449   EXPECT_TRUE(verify_delete.IsCalled());
    450   EXPECT_EQ(0u, verify_delete.GetPasswords().size());
    451 }
    452 #endif  // !defined(OS_WIN) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
    453