Index: chrome/browser/profiles/profile_manager_browsertest.cc |
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc |
index f0287d73c6b953d7a3c65518adb11d0e0178910c..8fe136558033ff529d6c254210af40f35488f75f 100644 |
--- a/chrome/browser/profiles/profile_manager_browsertest.cc |
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc |
@@ -7,8 +7,11 @@ |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/macros.h" |
+#include "base/stl_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "build/build_config.h" |
+#include "chrome/browser/lifetime/keep_alive_types.h" |
+#include "chrome/browser/lifetime/scoped_keep_alive.h" |
#include "chrome/browser/password_manager/password_store_factory.h" |
#include "chrome/browser/profiles/profile_attributes_entry.h" |
#include "chrome/browser/profiles/profile_attributes_storage.h" |
@@ -59,6 +62,39 @@ void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) { |
base::MessageLoop::current()->QuitWhenIdle(); |
} |
+// An observer returns back to test code after one or more profiles was deleted. |
+// It has ScopedKeepAlive object to prevent browser shutdown started in case |
+// browser become windowless. |
+class MultipleProfileDeletionObserver { |
+ public: |
+ MultipleProfileDeletionObserver(size_t callbacks_calls_expected) |
+ : callback_calls_left_(callbacks_calls_expected) { |
+ EXPECT_LT(0u, callback_calls_left_); |
+ } |
+ ProfileManager::CreateCallback QuitAttemptClosure() { |
+ return base::Bind(&MultipleProfileDeletionObserver::QuitAttempt, |
+ base::Unretained(this)); |
+ } |
+ void Wait() { |
+ keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::PROFILE_HELPER, |
Bernhard Bauer
2017/03/16 16:31:52
Can you use base::MakeUnique<ScopedKeepAlive>() an
|
+ KeepAliveRestartOption::DISABLED)); |
+ loop_.Run(); |
+ } |
+ |
+ private: |
+ void QuitAttempt(Profile* profile, Profile::CreateStatus status) { |
+ EXPECT_EQ(Profile::CREATE_STATUS_INITIALIZED, status); |
+ if (--callback_calls_left_) |
+ return; |
+ keep_alive_.reset(nullptr); |
+ loop_.Quit(); |
+ } |
+ |
+ base::RunLoop loop_; |
+ size_t callback_calls_left_; |
+ std::unique_ptr<ScopedKeepAlive> keep_alive_; |
+}; |
+ |
void EphemeralProfileCreationComplete(Profile* profile, |
Profile::CreateStatus status) { |
if (status == Profile::CREATE_STATUS_INITIALIZED) |
@@ -80,14 +116,21 @@ class ProfileRemovalObserver : public ProfileAttributesStorage::Observer { |
std::string last_used_profile_name() { return last_used_profile_name_; } |
+ void set_on_profile_removal_callback(base::Closure callback) { |
Bernhard Bauer
2017/03/16 16:31:52
Nit: Pass the callback by const-ref.
|
+ on_profile_removal_callback_ = callback; |
+ } |
+ |
// ProfileAttributesStorage::Observer overrides: |
void OnProfileWillBeRemoved(const base::FilePath& profile_path) override { |
last_used_profile_name_ = g_browser_process->local_state()->GetString( |
prefs::kProfileLastUsed); |
+ if (!on_profile_removal_callback_.is_null()) |
+ on_profile_removal_callback_.Run(); |
} |
private: |
std::string last_used_profile_name_; |
+ base::Closure on_profile_removal_callback_; |
DISALLOW_COPY_AND_ASSIGN(ProfileRemovalObserver); |
}; |
@@ -152,7 +195,7 @@ class ProfileManagerBrowserTest : public InProcessBrowserTest { |
} |
}; |
-#if defined(OS_MACOSX) |
+#if !defined(OS_ANDROID) |
// Delete single profile and make sure a new one is created. |
IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { |
@@ -168,14 +211,13 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { |
base::FilePath singleton_profile_path = |
storage.GetAllProfilesAttributes().front()->GetPath(); |
EXPECT_FALSE(singleton_profile_path.empty()); |
- base::RunLoop run_loop; |
+ MultipleProfileDeletionObserver profile_deletion_observer(1u); |
profile_manager->ScheduleProfileForDeletion( |
- singleton_profile_path, |
- base::Bind(&OnUnblockOnProfileCreation, &run_loop)); |
+ singleton_profile_path, profile_deletion_observer.QuitAttemptClosure()); |
// Run the message loop until the profile is actually deleted (as indicated |
// by the callback above being called). |
- run_loop.Run(); |
+ profile_deletion_observer.Wait(); |
// Make sure a new profile was created automatically. |
EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
@@ -194,10 +236,79 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteSingletonProfile) { |
EXPECT_EQ(last_used_profile_name, observer.last_used_profile_name()); |
} |
+// Delete inactive profile in a multi profile setup and make sure current |
+// browser is not affected. |
+IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteInactiveProfile) { |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+ ProfileAttributesStorage& storage = |
+ profile_manager->GetProfileAttributesStorage(); |
+ base::FilePath current_profile_path = browser()->profile()->GetPath(); |
+ |
+ // Create an additional profile. |
+ base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
+ base::RunLoop run_loop; |
+ profile_manager->CreateProfileAsync( |
+ new_path, base::Bind(&OnUnblockOnProfileCreation, &run_loop), |
+ base::string16(), std::string(), std::string()); |
+ run_loop.Run(); |
+ |
+ ASSERT_EQ(2u, storage.GetNumberOfProfiles()); |
+ |
+ // Delete inactive profile. |
+ base::RunLoop loop; |
+ ProfileRemovalObserver observer; |
+ observer.set_on_profile_removal_callback(loop.QuitClosure()); |
+ profile_manager->ScheduleProfileForDeletion(new_path, |
+ ProfileManager::CreateCallback()); |
+ loop.Run(); |
+ |
+ // Make sure there only preexisted profile left. |
+ EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
+ EXPECT_EQ(current_profile_path, |
+ storage.GetAllProfilesAttributes().front()->GetPath()); |
+ |
+ // Make sure that last used profile preference is set correctly. |
+ Profile* last_used = ProfileManager::GetLastUsedProfile(); |
+ EXPECT_EQ(current_profile_path, last_used->GetPath()); |
+} |
+ |
+// Delete current profile in a multi profile setup and make sure an existing one |
+// is loaded. |
+IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteCurrentProfile) { |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+ ProfileAttributesStorage& storage = |
+ profile_manager->GetProfileAttributesStorage(); |
+ |
+ // Create an additional profile. |
+ base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath(); |
+ base::RunLoop run_loop; |
+ profile_manager->CreateProfileAsync( |
+ new_path, base::Bind(&OnUnblockOnProfileCreation, &run_loop), |
+ base::string16(), std::string(), std::string()); |
+ run_loop.Run(); |
+ |
+ ASSERT_EQ(2u, storage.GetNumberOfProfiles()); |
+ |
+ // Delete current profile. |
+ MultipleProfileDeletionObserver profile_deletion_observer(1u); |
+ profile_manager->ScheduleProfileForDeletion( |
+ browser()->profile()->GetPath(), |
+ profile_deletion_observer.QuitAttemptClosure()); |
+ profile_deletion_observer.Wait(); |
+ |
+ // Make sure a profile created earlier become the only profile. |
+ EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
+ EXPECT_EQ(new_path, storage.GetAllProfilesAttributes().front()->GetPath()); |
+ |
+ // Make sure that last used profile preference is set correctly. |
+ Profile* last_used = ProfileManager::GetLastUsedProfile(); |
+ EXPECT_EQ(new_path, last_used->GetPath()); |
+} |
+ |
// Delete all profiles in a multi profile setup and make sure a new one is |
// created. |
-// Crashes/CHECKs. See crbug.com/104851 |
-IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { |
+// Should be fixed: Crashes/CHECKs. See crbug.com/104851 |
Bernhard Bauer
2017/03/16 16:31:52
Does this test still crash? If so, we probably sho
|
+IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DeleteAllProfiles) { |
ProfileManager* profile_manager = g_browser_process->profile_manager(); |
ProfileAttributesStorage& storage = |
profile_manager->GetProfileAttributesStorage(); |
@@ -216,6 +327,7 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { |
ASSERT_EQ(2u, storage.GetNumberOfProfiles()); |
// Delete all profiles. |
+ MultipleProfileDeletionObserver profile_deletion_observer(2u); |
std::vector<ProfileAttributesEntry*> entries = |
storage.GetAllProfilesAttributes(); |
std::vector<base::FilePath> old_profile_paths; |
@@ -223,12 +335,10 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { |
base::FilePath profile_path = entry->GetPath(); |
EXPECT_FALSE(profile_path.empty()); |
profile_manager->ScheduleProfileForDeletion( |
- profile_path, ProfileManager::CreateCallback()); |
+ profile_path, profile_deletion_observer.QuitAttemptClosure()); |
old_profile_paths.push_back(profile_path); |
} |
- |
- // Spin things so deletion can take place. |
- content::RunAllPendingInMessageLoop(); |
+ profile_deletion_observer.Wait(); |
// Make sure a new profile was created automatically. |
EXPECT_EQ(1u, storage.GetNumberOfProfiles()); |
@@ -241,7 +351,7 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, DISABLED_DeleteAllProfiles) { |
Profile* last_used = ProfileManager::GetLastUsedProfile(); |
EXPECT_EQ(new_profile_path, last_used->GetPath()); |
} |
-#endif // OS_MACOSX |
+#endif // !defined(OS_ANDROID) |
#if defined(OS_CHROMEOS) |