Add fallback behavior if the last used profile cannot initialize
Before this CL, if the last used profile cannot be initialized, it will
be a silent exit in Windows and a CHECK failure in other platforms.
In this CL a list of possible fall-back behavior are used (from the top
to the bottom):
(1) open other last opened profiles which was not signed out.
(2) open the user manager (guest profile & system profile)
(3) open other profiles which was not signed out.
(4) at last, show a message box and do not start chromium.
BUG=614753
Review-Url: https://codereview.chromium.org/2047483003
Cr-Commit-Position: refs/heads/master@{#409023}
diff --git a/chrome/browser/ui/profile_error_dialog.h b/chrome/browser/ui/profile_error_dialog.h
index eec7ba9..e9d1d529 100644
--- a/chrome/browser/ui/profile_error_dialog.h
+++ b/chrome/browser/ui/profile_error_dialog.h
@@ -18,6 +18,8 @@
PROFILE_ERROR_DB_TOKEN_WEB_DATA,
PROFILE_ERROR_DB_WEB_DATA,
PROFILE_ERROR_DB_KEYWORD_WEB_DATA,
+ PROFILE_ERROR_CREATE_FAILURE_SPECIFIED,
+ PROFILE_ERROR_CREATE_FAILURE_ALL,
PROFILE_ERROR_END
};
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 2af51d8..639d5b2c 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -887,3 +887,76 @@
return g_browser_process->profile_manager()->GetLastUsedProfileDir(
user_data_dir);
}
+
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+Profile* GetStartupProfile(const base::FilePath& user_data_dir,
+ const base::CommandLine& command_line) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+
+ base::FilePath profile_path =
+ GetStartupProfilePath(user_data_dir, command_line);
+ Profile* profile = profile_manager->GetProfile(profile_path);
+
+ // If there is no entry in profile attributes storage, the profile is deleted,
+ // and we should show the user manager. Also, when using
+ // --new-profile-management, if the profile is locked we should show the user
+ // manager as well. When neither of these is true, we can safely start up with
+ // |profile|.
+ auto* storage = &profile_manager->GetProfileAttributesStorage();
+ ProfileAttributesEntry* entry;
+ bool has_entry = storage->GetProfileAttributesWithPath(profile_path, &entry);
+ if (has_entry && (!switches::IsNewProfileManagement() ||
+ !entry->IsSigninRequired() || !profile)) {
+ return profile;
+ }
+
+ // We want to show the user manager. To indicate this, return the guest
+ // profile. However, we can only do this if the system profile (where the user
+ // manager lives) also exists (or is creatable).
+ return profile_manager->GetProfile(ProfileManager::GetSystemProfilePath()) ?
+ profile_manager->GetProfile(ProfileManager::GetGuestProfilePath()) :
+ nullptr;
+}
+
+Profile* GetFallbackStartupProfile() {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ // The only known reason for profiles to fail initialization is being unable
+ // to create the profile directory, and this has already happened in
+ // GetStartupProfilePath() before calling this function. In this case,
+ // creation of new profiles is expected to fail. So only existing profiles are
+ // attempted for fallback.
+
+ // If the last used profile could not be initialized, see if any of other last
+ // opened profiles can be initialized successfully.
+ auto* storage = &profile_manager->GetProfileAttributesStorage();
+ for (Profile* profile : ProfileManager::GetLastOpenedProfiles()) {
+ // Return any profile that is not locked.
+ ProfileAttributesEntry* entry;
+ bool has_entry = storage->GetProfileAttributesWithPath(profile->GetPath(),
+ &entry);
+ if (!has_entry || !entry->IsSigninRequired())
+ return profile;
+ }
+
+ // Couldn't initialize any last opened profiles. Try to show the user manager,
+ // which requires successful initialization of the guest and system profiles.
+ Profile* guest_profile =
+ profile_manager->GetProfile(ProfileManager::GetGuestProfilePath());
+ Profile* system_profile =
+ profile_manager->GetProfile(ProfileManager::GetSystemProfilePath());
+ if (guest_profile && system_profile)
+ return guest_profile;
+
+ // Couldn't show the user manager either. Try to open any profile that is not
+ // locked.
+ for (ProfileAttributesEntry* entry : storage->GetAllProfilesAttributes()) {
+ if (!entry->IsSigninRequired()) {
+ Profile* profile = profile_manager->GetProfile(entry->GetPath());
+ if (profile)
+ return profile;
+ }
+ }
+
+ return nullptr;
+}
+#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
diff --git a/chrome/browser/ui/startup/startup_browser_creator.h b/chrome/browser/ui/startup/startup_browser_creator.h
index f2e3c0a..1081c16 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.h
+++ b/chrome/browser/ui/startup/startup_browser_creator.h
@@ -179,4 +179,21 @@
base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir,
const base::CommandLine& command_line);
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+// Returns the profile that should be loaded on process startup. This is either
+// the profile returned by GetStartupProfilePath, or the guest profile if the
+// above profile is locked. The guest profile denotes that we should open the
+// user manager. Returns null if the above profile cannot be opened. In case of
+// opening the user manager, returns null if either the guest profile or the
+// system profile cannot be opened.
+Profile* GetStartupProfile(const base::FilePath& user_data_dir,
+ const base::CommandLine& command_line);
+
+// Returns the profile that should be loaded on process startup when
+// GetStartupProfile() returns null. As with GetStartupProfile(), returning the
+// guest profile means the caller should open the user manager. This may return
+// null if neither any profile nor the user manager can be opened.
+Profile* GetFallbackStartupProfile();
+#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+
#endif // CHROME_BROWSER_UI_STARTUP_STARTUP_BROWSER_CREATOR_H_
diff --git a/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc
new file mode 100644
index 0000000..3c4fe5e
--- /dev/null
+++ b/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc
@@ -0,0 +1,420 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/base_switches.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/test/test_file_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/user_manager.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+
+namespace {
+
+void UnblockOnProfileCreation(Profile::CreateStatus expected_final_status,
+ const base::Closure& quit_closure,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ // If the status is CREATE_STATUS_CREATED, then the function will be called
+ // again with CREATE_STATUS_INITIALIZED.
+ if (status == Profile::CREATE_STATUS_CREATED)
+ return;
+
+ EXPECT_EQ(expected_final_status, status);
+ quit_closure.Run();
+}
+
+void UnblockOnProfileInitialized(const base::Closure& quit_closure,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ UnblockOnProfileCreation(Profile::CREATE_STATUS_INITIALIZED, quit_closure,
+ profile, status);
+}
+
+void OnCloseAllBrowsersSucceeded(const base::Closure& quit_closure,
+ const base::FilePath& path) {
+ quit_closure.Run();
+}
+
+void CreateAndSwitchToProfile(const std::string& basepath) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ ASSERT_TRUE(profile_manager);
+
+ base::FilePath path = profile_manager->user_data_dir().AppendASCII(basepath);
+ base::RunLoop run_loop;
+ profile_manager->CreateProfileAsync(
+ path, base::Bind(&UnblockOnProfileInitialized, run_loop.QuitClosure()),
+ base::string16(), std::string(), std::string());
+ // Run the message loop to allow profile creation to take place; the loop is
+ // terminated by UnblockOnProfileCreation when the profile is created.
+ run_loop.Run();
+
+ profiles::SwitchToProfile(path, false, ProfileManager::CreateCallback(),
+ ProfileMetrics::SWITCH_PROFILE_ICON);
+}
+
+void CheckBrowserWindows(const std::vector<std::string>& expected_basepaths) {
+ std::vector<std::string> actual_basepaths;
+ for (const Browser* browser : *BrowserList::GetInstance()) {
+ actual_basepaths.push_back(
+ browser->profile()->GetPath().BaseName().AsUTF8Unsafe());
+ }
+
+ if (actual_basepaths.size() != expected_basepaths.size() ||
+ !std::is_permutation(actual_basepaths.cbegin(), actual_basepaths.cend(),
+ expected_basepaths.cbegin())) {
+ ADD_FAILURE()
+ << "Expected profile paths are different from actual profile paths."
+ "\n Actual profile paths: "
+ << base::JoinString(actual_basepaths, ", ")
+ << "\n Expected profile paths: "
+ << base::JoinString(expected_basepaths, ", ");
+ }
+}
+
+void ExpectUserManagerToShow() {
+ // If the user manager is not shown yet, wait for the user manager to appear.
+ if (!UserManager::IsShowing()) {
+ base::RunLoop run_loop;
+ UserManager::AddOnUserManagerShownCallbackForTesting(
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+ ASSERT_TRUE(UserManager::IsShowing());
+
+ // We must hide the user manager before the test ends.
+ UserManager::Hide();
+}
+
+} // namespace
+
+class StartupBrowserCreatorCorruptProfileTest : public InProcessBrowserTest {
+ public:
+ StartupBrowserCreatorCorruptProfileTest()
+ : test_body_has_run_(false), expect_test_body_to_run_(true) {}
+
+ void SetExpectTestBodyToRun(bool expected_result) {
+ expect_test_body_to_run_ = expected_result;
+ }
+
+ bool DeleteProfileData(const std::string& basepath) {
+ base::FilePath user_data_dir;
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
+ return false;
+
+ base::FilePath dir_to_delete = user_data_dir.AppendASCII(basepath);
+ return base::DirectoryExists(dir_to_delete) &&
+ base::DeleteFile(dir_to_delete, true);
+ }
+
+ bool RemoveCreateDirectoryPermissionForUserDataDirectory() {
+ base::FilePath user_data_dir;
+ return PathService::Get(chrome::DIR_USER_DATA, &user_data_dir) &&
+ base::DenyFilePermission(user_data_dir, FILE_ADD_SUBDIRECTORY);
+ }
+
+ protected:
+ // For each test, declare a bool SetUpUserDataDirectory[testname] function.
+ bool SetUpUserDataDirectoryForLastOpenedProfileMissing();
+ bool SetUpUserDataDirectoryForLastUsedProfileFallbackToLastOpenedProfiles();
+ bool SetUpUserDataDirectoryForLastUsedProfileFallbackToUserManager();
+ bool SetUpUserDataDirectoryForCannotCreateSystemProfile();
+ bool SetUpUserDataDirectoryForLastUsedProfileFallbackToAnyProfile();
+ bool SetUpUserDataDirectoryForLastUsedProfileFallbackFail();
+ bool SetUpUserDataDirectoryForDoNotStartLockedProfile();
+ bool SetUpUserDataDirectoryForNoFallbackForUserSelectedProfile();
+ bool SetUpUserDataDirectoryForDeletedProfileFallbackToUserManager();
+
+ void CloseBrowsersSynchronouslyForProfileBasePath(
+ const std::string& basepath) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ ASSERT_TRUE(profile_manager);
+
+ Profile* profile =
+ profile_manager->GetProfileByPath(
+ profile_manager->user_data_dir().AppendASCII(basepath));
+ ASSERT_TRUE(profile);
+
+ base::RunLoop run_loop;
+ BrowserList::GetInstance()->CloseAllBrowsersWithProfile(
+ profile, base::Bind(&OnCloseAllBrowsersSucceeded,
+ run_loop.QuitClosure()));
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kRestoreLastSession);
+ command_line->AppendSwitch(switches::kNoErrorDialogs);
+ }
+
+ // In this test fixture, SetUpUserDataDirectory must be handled for all
+ // non-PRE_ tests.
+ bool SetUpUserDataDirectory() override {
+#define SET_UP_USER_DATA_DIRECTORY_FOR(testname) \
+if (testing::UnitTest::GetInstance()->current_test_info()->name() == \
+ std::string(#testname)) {\
+ return this->SetUpUserDataDirectoryFor ## testname(); \
+}
+
+ SET_UP_USER_DATA_DIRECTORY_FOR(LastOpenedProfileMissing);
+ SET_UP_USER_DATA_DIRECTORY_FOR(LastUsedProfileFallbackToLastOpenedProfiles);
+ SET_UP_USER_DATA_DIRECTORY_FOR(LastUsedProfileFallbackToUserManager);
+ SET_UP_USER_DATA_DIRECTORY_FOR(CannotCreateSystemProfile);
+ SET_UP_USER_DATA_DIRECTORY_FOR(LastUsedProfileFallbackToAnyProfile);
+ SET_UP_USER_DATA_DIRECTORY_FOR(LastUsedProfileFallbackFail);
+ SET_UP_USER_DATA_DIRECTORY_FOR(DoNotStartLockedProfile);
+ SET_UP_USER_DATA_DIRECTORY_FOR(NoFallbackForUserSelectedProfile);
+ SET_UP_USER_DATA_DIRECTORY_FOR(DeletedProfileFallbackToUserManager);
+
+#undef SET_UP_USER_DATA_DIRECTORY_FOR
+
+ // If control goes here, it means SetUpUserDataDirectory is not handled.
+ // This is okay for PRE_ tests, but not acceptable for main tests.
+ if (base::StartsWith(
+ testing::UnitTest::GetInstance()->current_test_info()->name(),
+ "PRE_", base::CompareCase::SENSITIVE)) {
+ return true;
+ }
+
+ ADD_FAILURE() << "SetUpUserDataDirectory is not handled by the test.";
+ return false;
+ }
+
+ void TearDownOnMainThread() override {
+ test_body_has_run_ = true;
+ InProcessBrowserTest::TearDownOnMainThread();
+ }
+
+ void TearDown() override {
+ EXPECT_EQ(expect_test_body_to_run_, test_body_has_run_);
+ InProcessBrowserTest::TearDown();
+ }
+
+ private:
+ bool test_body_has_run_;
+ bool expect_test_body_to_run_;
+ DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorCorruptProfileTest);
+};
+
+// Most of the tests below have three sections:
+// (1) PRE_ test, which is used to create profiles. Most of these profiles are
+// meant to be opened in (3) during startup.
+// (2) StartupBrowserCreatorCorruptProfileTest::SetUpUserDataDirectoryFor...
+// which sets up the user data directory, i.e. to remove profile directories
+// and to prevent the profile directories from being created again in (3).
+// We cannot remove these directories while the browser process is running,
+// so that cannot be done during (1) or (3).
+// (3) The test itself. With the |kRestoreLastSession| switch set, profiles
+// opened in (1) are reopened. However, since the directories of some
+// profiles are removed in (2), these profiles are unable to be initialized.
+// We are testing whether the correct fallback action is taken.
+
+// LastOpenedProfileMissing : If any last opened profile is missing, that
+// profile is skipped, but other last opened profiles should be opened in the
+// browser.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_LastOpenedProfileMissing) {
+ CreateAndSwitchToProfile("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForLastOpenedProfileMissing() {
+ return DeleteProfileData("Profile 1") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ LastOpenedProfileMissing) {
+ CheckBrowserWindows({"Default", "Profile 2"});
+}
+
+// LastUsedProfileFallbackToLastOpenedProfiles : If the last used profile is
+// missing, it should fall back to any last opened profiles.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_LastUsedProfileFallbackToLastOpenedProfiles) {
+ CreateAndSwitchToProfile("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForLastUsedProfileFallbackToLastOpenedProfiles() {
+ return DeleteProfileData("Profile 2") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ LastUsedProfileFallbackToLastOpenedProfiles) {
+ CheckBrowserWindows({"Default", "Profile 1"});
+}
+
+// LastUsedProfileFallbackToUserManager : If all last opened profiles are
+// missing, it should fall back to user manager. To open the user manager, both
+// the guest profile and the system profile must be creatable.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_LastUsedProfileFallbackToUserManager) {
+ CreateAndSwitchToProfile("Profile 1");
+ CloseBrowsersSynchronouslyForProfileBasePath("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+
+ ASSERT_TRUE(base::CreateDirectory(ProfileManager::GetGuestProfilePath()));
+ ASSERT_TRUE(base::CreateDirectory(ProfileManager::GetSystemProfilePath()));
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForLastUsedProfileFallbackToUserManager() {
+ return DeleteProfileData("Default") &&
+ DeleteProfileData("Profile 2") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ LastUsedProfileFallbackToUserManager) {
+ CheckBrowserWindows({});
+ ExpectUserManagerToShow();
+}
+
+
+// CannotCreateSystemProfile : If the system profile cannot be created, the user
+// manager should not be shown. Fallback to any other profile.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_CannotCreateSystemProfile) {
+ CreateAndSwitchToProfile("Profile 1");
+ CloseBrowsersSynchronouslyForProfileBasePath("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+
+ // Create the guest profile path, but not the system profile one. This will
+ // make it impossible to create the system profile once the permissions are
+ // locked down during setup.
+ ASSERT_TRUE(base::CreateDirectory(ProfileManager::GetGuestProfilePath()));
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForCannotCreateSystemProfile() {
+ return DeleteProfileData("Default") &&
+ DeleteProfileData("Profile 2") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ CannotCreateSystemProfile) {
+ CheckBrowserWindows({"Profile 1"});
+}
+
+// LastUsedProfileFallbackToAnyProfile : If all the last opened profiles and the
+// guest profile cannot be opened, fall back to any profile that is not locked.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_LastUsedProfileFallbackToAnyProfile) {
+ CreateAndSwitchToProfile("Profile 1");
+ CloseBrowsersSynchronouslyForProfileBasePath("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForLastUsedProfileFallbackToAnyProfile() {
+ return DeleteProfileData("Default") &&
+ DeleteProfileData("Profile 2") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ LastUsedProfileFallbackToAnyProfile) {
+ CheckBrowserWindows({"Profile 1"});
+}
+
+// LastUsedProfileFallbackFail : If no startup option is feasible, the browser
+// should quit cleanly.
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForLastUsedProfileFallbackFail() {
+ SetExpectTestBodyToRun(false);
+ return RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ LastUsedProfileFallbackFail) {
+ ADD_FAILURE() << "Test body is not expected to run.";
+}
+
+// DoNotStartLockedProfile : Profiles that are locked should never be
+// initialized. Since there are no unlocked profiles, the browser should not
+// start.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_DoNotStartLockedProfile) {
+ // Lock the default profile. The user manager is shown after the profile is
+ // locked.
+ profiles::LockProfile(browser()->profile());
+ ExpectUserManagerToShow();
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForDoNotStartLockedProfile() {
+ SetExpectTestBodyToRun(false);
+ return RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ DoNotStartLockedProfile) {
+ ADD_FAILURE() << "Test body is not expected to run.";
+}
+
+// NoFallbackForUserSelectedProfile : No fallback should be attempted if the
+// profile is selected by the --profile-directory switch. The browser should not
+// start if the specified profile could not be initialized.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_NoFallbackForUserSelectedProfile) {
+ CreateAndSwitchToProfile("Profile 1");
+ CreateAndSwitchToProfile("Profile 2");
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForNoFallbackForUserSelectedProfile() {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->AppendSwitchASCII(switches::kProfileDirectory, "Profile 1");
+ SetExpectTestBodyToRun(false);
+ return DeleteProfileData("Profile 1") &&
+ RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ NoFallbackForUserSelectedProfile) {
+ ADD_FAILURE() << "Test body is not expected to run.";
+}
+
+// DeletedProfileFallbackToUserManager : If the profile's entry in
+// ProfileAttributesStorage is missing, it means the profile is deleted. The
+// browser should not attempt to open the profile, but should show the user
+// manager instead.
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ PRE_DeletedProfileFallbackToUserManager) {
+ ASSERT_TRUE(base::CreateDirectory(ProfileManager::GetGuestProfilePath()));
+ ASSERT_TRUE(base::CreateDirectory(ProfileManager::GetSystemProfilePath()));
+}
+
+bool StartupBrowserCreatorCorruptProfileTest::
+ SetUpUserDataDirectoryForDeletedProfileFallbackToUserManager() {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // Simulate a deleted profile by not creating the profile at the first place.
+ command_line->AppendSwitchASCII(switches::kProfileDirectory, "Not Found");
+ return RemoveCreateDirectoryPermissionForUserDataDirectory();
+}
+
+IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorCorruptProfileTest,
+ DeletedProfileFallbackToUserManager) {
+ CheckBrowserWindows({});
+ ExpectUserManagerToShow();
+}