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
36namespace {
37
38const ProfileManager::CreateCallback kOnProfileSwitchDoNothing;
39
40// An observer that returns back to test code after a new profile is
41// initialized.
42void OnUnblockOnProfileCreation(Profile* profile,
43                                Profile::CreateStatus status) {
44  if (status == Profile::CREATE_STATUS_INITIALIZED)
45    base::MessageLoop::current()->Quit();
46}
47
48void 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
58void 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
65class 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.
94class 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.
124class 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.
137IN_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
173IN_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
217class 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
227IN_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)
243IN_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
270IN_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
339IN_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)
407IN_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