Commit 3636d62a authored by Jan Krcal's avatar Jan Krcal Committed by Chromium LUCI CQ

Reland "[Profile picker] Use system profile on startup when showing the picker"

This is a reland of fa8de986

Original change's description:
> [Profile picker] Use system profile on startup when showing the picker
>
> This CL changes the logic to load the startup profile whenever the
> profile picker should be loaded. It instead loads the guest profile
> to indicate the picker should be open. This speeds up showing the picker
> when the last profile used is heavy to load. The CL also unifies the
> logic to decide whether to show the new picker (or the old user manager)
> into one function, GetStartupProfile().
>
> There is one behavioral difference: the new code directly opens browser
> windows if the user had multiple profiles open last time. This is desired
> because having multiple profiles open simultaneously the last time is a
> strong signal the user wants to continue this way. Note that having
> multiple profiles open the last time happens only in limited situations,
> e.g. via chrome://restart or via session restore (when logging out /
> switching off the machine with multiple profiles' windows open).
>
> Bug: 1150330
> Change-Id: Iae9744f44bc242e9aaaf8f287cc29e1089326786
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2532460
> Commit-Queue: Jan Krcal <jkrcal@chromium.org>
> Reviewed-by: David Roger <droger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#828665}

Bug: 1150330
Change-Id: I457871e2041eb09eb90fb31f773d095b47aeb462
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2547040
Commit-Queue: Jan Krcal <jkrcal@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarTommy Martino <tmartino@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837191}
parent 98d68632
...@@ -578,19 +578,23 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session; ...@@ -578,19 +578,23 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session;
- (void)didEndMainMessageLoop { - (void)didEndMainMessageLoop {
if (base::FeatureList::IsEnabled(features::kDestroyProfileOnBrowserClose)) { if (base::FeatureList::IsEnabled(features::kDestroyProfileOnBrowserClose)) {
// With DestroyProfileOnBrowserClose, Profiles get deleted earlier. So // With DestroyProfileOnBrowserClose, Profiles get deleted earlier. So
// _lastProfile is already null, and [self lastProfile] below would load it // _lastProfile is already null, and and we cannot load it from disk now.
// from disk (which we can't do).
DCHECK_EQ(nullptr, _lastProfile); DCHECK_EQ(nullptr, _lastProfile);
return; return;
} }
DCHECK_EQ(0u, chrome::GetBrowserCount([self lastProfile])); if (!_lastProfile) {
if (!chrome::GetBrowserCount([self lastProfile])) { // If only the profile picker is open and closed again, there is no profile
// loaded when main message loop ends and we cannot load it from disk now.
return;
}
DCHECK_EQ(0u, chrome::GetBrowserCount(_lastProfile));
if (!chrome::GetBrowserCount(_lastProfile)) {
// As we're shutting down, we need to nuke the TabRestoreService, which // As we're shutting down, we need to nuke the TabRestoreService, which
// will start the shutdown of the NavigationControllers and allow for // will start the shutdown of the NavigationControllers and allow for
// proper shutdown. If we don't do this, Chrome won't shut down cleanly, // proper shutdown. If we don't do this, Chrome won't shut down cleanly,
// and may end up crashing when some thread tries to use the IO thread (or // and may end up crashing when some thread tries to use the IO thread (or
// another thread) that is no longer valid. // another thread) that is no longer valid.
TabRestoreServiceFactory::ResetForProfile([self lastProfile]); TabRestoreServiceFactory::ResetForProfile(_lastProfile);
} }
} }
...@@ -1305,12 +1309,7 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session; ...@@ -1305,12 +1309,7 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session;
// manager is still shown). // manager is still shown).
UserManager::Show(base::FilePath(), UserManager::Show(base::FilePath(),
profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
} else if (ProfilePicker::ShouldShowAtLaunch( } else if (ProfilePicker::ShouldShowAtLaunch()) {
// Pass an empty command line, because this is not application
// startup. The original arguments (e.g. --incognito) are no
// longer relevant.
base::CommandLine(base::CommandLine::NO_PROGRAM),
/*urls_to_launch=*/std::vector<GURL>())) {
ProfilePicker::Show( ProfilePicker::Show(
ProfilePicker::EntryPoint::kNewSessionOnExistingProcess); ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
} else { } else {
......
...@@ -346,6 +346,7 @@ void AddFirstRunNewTabs(StartupBrowserCreator* browser_creator, ...@@ -346,6 +346,7 @@ void AddFirstRunNewTabs(StartupBrowserCreator* browser_creator,
// should not continue. // should not continue.
Profile* CreatePrimaryProfile(const content::MainFunctionParams& parameters, Profile* CreatePrimaryProfile(const content::MainFunctionParams& parameters,
const base::FilePath& user_data_dir, const base::FilePath& user_data_dir,
const base::FilePath& cur_dir,
const base::CommandLine& parsed_command_line) { const base::CommandLine& parsed_command_line) {
TRACE_EVENT0("startup", "ChromeBrowserMainParts::CreateProfile") TRACE_EVENT0("startup", "ChromeBrowserMainParts::CreateProfile")
base::Time start = base::Time::Now(); base::Time start = base::Time::Now();
...@@ -399,7 +400,7 @@ Profile* CreatePrimaryProfile(const content::MainFunctionParams& parameters, ...@@ -399,7 +400,7 @@ Profile* CreatePrimaryProfile(const content::MainFunctionParams& parameters,
CHECK(profile) << "Cannot get default profile."; CHECK(profile) << "Cannot get default profile.";
#else #else
profile = GetStartupProfile(user_data_dir, parsed_command_line); profile = GetStartupProfile(user_data_dir, cur_dir, parsed_command_line);
if (!profile && !last_used_profile_set) if (!profile && !last_used_profile_set)
profile = GetFallbackStartupProfile(); profile = GetFallbackStartupProfile();
...@@ -1378,9 +1379,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { ...@@ -1378,9 +1379,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
// This step is costly and is already measured in Startup.CreateFirstProfile // This step is costly and is already measured in Startup.CreateFirstProfile
// and more directly Profile.CreateAndInitializeProfile. // and more directly Profile.CreateAndInitializeProfile.
profile_ = CreatePrimaryProfile(parameters(), profile_ = CreatePrimaryProfile(parameters(), user_data_dir_,
user_data_dir_, base::FilePath(), parsed_command_line());
parsed_command_line());
if (!profile_) if (!profile_)
return content::RESULT_CODE_NORMAL_EXIT; return content::RESULT_CODE_NORMAL_EXIT;
......
...@@ -6,24 +6,17 @@ ...@@ -6,24 +6,17 @@
#include <string> #include <string>
#include "base/command_line.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/signin/signin_util.h" #include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/ui_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#if defined(OS_WIN)
#include "chrome/browser/notifications/win/notification_launch_id.h"
#endif
namespace { namespace {
ProfilePicker::AvailabilityOnStartup GetAvailabilityOnStartup() { ProfilePicker::AvailabilityOnStartup GetAvailabilityOnStartup() {
...@@ -45,63 +38,26 @@ ProfilePicker::AvailabilityOnStartup GetAvailabilityOnStartup() { ...@@ -45,63 +38,26 @@ ProfilePicker::AvailabilityOnStartup GetAvailabilityOnStartup() {
} // namespace } // namespace
// static // static
bool ProfilePicker::ShouldShowAtLaunch( bool ProfilePicker::ShouldShowAtLaunch() {
const base::CommandLine& command_line,
const std::vector<GURL>& urls_to_launch) {
AvailabilityOnStartup availability_on_startup = GetAvailabilityOnStartup(); AvailabilityOnStartup availability_on_startup = GetAvailabilityOnStartup();
// Don't show the picker if a certain profile (or an incognito window in the
// default profile) is explicitly requested.
if (profiles::IsGuestModeRequested(command_line,
g_browser_process->local_state(),
/*show_warning=*/false) ||
command_line.HasSwitch(switches::kIncognito) ||
command_line.HasSwitch(switches::kProfileDirectory)) {
return false;
}
// Don't show the picker if an app is explicitly requested to open. This URL
// param should be ideally paired with switches::kProfileDirectory but it's
// better to err on the side of opening the last profile than to err on the
// side of not opening the app directly.
if (command_line.HasSwitch(switches::kApp) ||
command_line.HasSwitch(switches::kAppId)) {
return false;
}
// If the browser is launched due to activation on Windows native notification,
// the profile id encoded in the notification launch id should be chosen over
// the profile picker.
#if defined(OS_WIN)
std::string profile_id =
NotificationLaunchId::GetNotificationLaunchProfileId(command_line);
if (!profile_id.empty()) {
return false;
}
#endif // defined(OS_WIN)
// Don't show the picker if a any URL is requested to launch via the
// command-line.
if (!urls_to_launch.empty()) {
return false;
}
if (signin_util::IsForceSigninEnabled()) if (signin_util::IsForceSigninEnabled())
return false; return false;
if (!base::FeatureList::IsEnabled(features::kNewProfilePicker)) if (!base::FeatureList::IsEnabled(features::kNewProfilePicker))
return false; return false;
// TODO (crbug/1155158): Move this over the urls check once the // TODO (crbug/1155158): Move this over the urls check (in
// profile picker can forward urls specified in command line. // startup_browser_creator.cc) once the profile picker can forward urls
// specified in command line.
if (availability_on_startup == AvailabilityOnStartup::kForced) if (availability_on_startup == AvailabilityOnStartup::kForced)
return true; return true;
size_t number_of_profiles = g_browser_process->profile_manager() size_t number_of_profiles = g_browser_process->profile_manager()
->GetProfileAttributesStorage() ->GetProfileAttributesStorage()
.GetNumberOfProfiles(); .GetNumberOfProfiles();
// Need to consider 0 profiles as this is what happens in some browser-tests.
if (number_of_profiles == 1) if (number_of_profiles <= 1)
return false; return false;
bool pref_enabled = g_browser_process->local_state()->GetBoolean( bool pref_enabled = g_browser_process->local_state()->GetBoolean(
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
class GURL; class GURL;
namespace base { namespace base {
class CommandLine;
class FilePath; class FilePath;
} // namespace base } // namespace base
...@@ -108,14 +107,11 @@ class ProfilePicker { ...@@ -108,14 +107,11 @@ class ProfilePicker {
// Overrides the timeout delay for waiting for extended account info. // Overrides the timeout delay for waiting for extended account info.
static void SetExtendedAccountInfoTimeoutForTesting(base::TimeDelta timeout); static void SetExtendedAccountInfoTimeoutForTesting(base::TimeDelta timeout);
// Returns whether the profile picker at launch. This can be called on // Returns whether to show profile picker at launch. This can be called on
// startup or when Chrome is re-opened, e.g. when clicking on the dock icon on // startup or when Chrome is re-opened, e.g. when clicking on the dock icon on
// MacOS when there are no windows, or from Windows tray icon. // MacOS when there are no windows, or from Windows tray icon.
// This returns true if this is a new session. Returns false if a specific // This returns true if the user has multiple profiles and has not opted-out.
// profile is passed in the command line, or if some parameters (such as the static bool ShouldShowAtLaunch();
// URLs to launch) cannot be handled by the picker.
static bool ShouldShowAtLaunch(const base::CommandLine& command_line,
const std::vector<GURL>& urls_to_launch);
private: private:
DISALLOW_COPY_AND_ASSIGN(ProfilePicker); DISALLOW_COPY_AND_ASSIGN(ProfilePicker);
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "chrome/browser/profiles/profile_observer.h" #include "chrome/browser/profiles/profile_observer.h"
#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
...@@ -278,8 +279,59 @@ bool CanOpenProfileOnStartup(Profile* profile) { ...@@ -278,8 +279,59 @@ bool CanOpenProfileOnStartup(Profile* profile) {
#endif #endif
} }
void ShowUserManagerOnStartup() { bool ShouldShowProfilePickerAtProcessLaunch(
ProfileManager* profile_manager,
const base::CommandLine& command_line) {
#if defined(OS_CHROMEOS)
return false;
#else
// If multiple profiles get restored, do not show the picker.
if (!profile_manager->GetLastOpenedProfiles().empty())
return false;
// Don't show the picker if a certain profile (or an incognito window in the
// default profile) is explicitly requested.
if (profiles::IsGuestModeRequested(command_line,
g_browser_process->local_state(),
/*show_warning=*/false) ||
command_line.HasSwitch(switches::kIncognito) ||
command_line.HasSwitch(switches::kProfileDirectory)) {
return false;
}
// Don't show the picker if an app is explicitly requested to open. This URL
// param should be ideally paired with switches::kProfileDirectory but it's
// better to err on the side of opening the last profile than to err on the
// side of not opening the app directly.
if (command_line.HasSwitch(switches::kApp) ||
command_line.HasSwitch(switches::kAppId)) {
return false;
}
// If the browser is launched due to activation on Windows native notification,
// the profile id encoded in the notification launch id should be chosen over
// the profile picker.
#if defined(OS_WIN)
std::string profile_id =
NotificationLaunchId::GetNotificationLaunchProfileId(command_line);
if (!profile_id.empty()) {
return false;
}
#endif // defined(OS_WIN)
return ProfilePicker::ShouldShowAtLaunch();
#endif // !defined(OS_CHROMEOS)
}
void ShowUserManager(bool is_process_startup) {
#if !BUILDFLAG(IS_CHROMEOS_ASH) #if !BUILDFLAG(IS_CHROMEOS_ASH)
if (!signin_util::IsForceSigninEnabled() &&
base::FeatureList::IsEnabled(features::kNewProfilePicker)) {
ProfilePicker::Show(
is_process_startup
? ProfilePicker::EntryPoint::kOnStartup
: ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
return;
}
UserManager::Show(base::FilePath(), UserManager::Show(base::FilePath(),
profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION); profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
#endif // !BUILDFLAG(IS_CHROMEOS_ASH) #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
...@@ -604,86 +656,6 @@ void StartupBrowserCreator::RegisterProfilePrefs(PrefRegistrySimple* registry) { ...@@ -604,86 +656,6 @@ void StartupBrowserCreator::RegisterProfilePrefs(PrefRegistrySimple* registry) {
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) #endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
} }
// static
std::vector<GURL> StartupBrowserCreator::GetURLsFromCommandLine(
const base::CommandLine& command_line,
const base::FilePath& cur_dir,
Profile* profile) {
DCHECK(profile);
std::vector<GURL> urls;
const base::CommandLine::StringVector& params = command_line.GetArgs();
for (size_t i = 0; i < params.size(); ++i) {
base::FilePath param = base::FilePath(params[i]);
// Handle Vista way of searching - "? <search-term>"
if ((param.value().size() > 2) && (param.value()[0] == '?') &&
(param.value()[1] == ' ')) {
GURL url(GetDefaultSearchURLForSearchTerms(
TemplateURLServiceFactory::GetForProfile(profile),
param.LossyDisplayName().substr(2)));
if (url.is_valid()) {
urls.push_back(url);
continue;
}
}
// Otherwise, fall through to treating it as a URL.
// This will create a file URL or a regular URL.
// This call can (in rare circumstances) block the UI thread.
// Allow it until this bug is fixed.
// http://code.google.com/p/chromium/issues/detail?id=60641
GURL url = GURL(param.MaybeAsASCII());
// http://crbug.com/371030: Only use URLFixerUpper if we don't have a valid
// URL, otherwise we will look in the current directory for a file named
// 'about' if the browser was started with a about:foo argument.
// http://crbug.com/424991: Always use URLFixerUpper on file:// URLs,
// otherwise we wouldn't correctly handle '#' in a file name.
if (!url.is_valid() || url.SchemeIsFile()) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
url = url_formatter::FixupRelativeFile(cur_dir, param);
}
// Exclude dangerous schemes.
if (!url.is_valid())
continue;
const GURL settings_url = GURL(chrome::kChromeUISettingsURL);
bool url_points_to_an_approved_settings_page = false;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// In ChromeOS, allow any settings page to be specified on the command line.
url_points_to_an_approved_settings_page =
url.GetOrigin() == settings_url.GetOrigin();
#else
// Exposed for external cleaners to offer a settings reset to the
// user. The allowed URLs must match exactly.
const GURL reset_settings_url =
settings_url.Resolve(chrome::kResetProfileSettingsSubPage);
url_points_to_an_approved_settings_page = url == reset_settings_url;
#if defined(OS_WIN)
// On Windows, also allow a hash for the Chrome Cleanup Tool.
const GURL reset_settings_url_with_cct_hash = reset_settings_url.Resolve(
std::string("#") +
settings::ResetSettingsHandler::kCctResetSettingsHash);
url_points_to_an_approved_settings_page =
url_points_to_an_approved_settings_page ||
url == reset_settings_url_with_cct_hash;
#endif // defined(OS_WIN)
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
ChildProcessSecurityPolicy* policy =
ChildProcessSecurityPolicy::GetInstance();
if (policy->IsWebSafeScheme(url.scheme()) ||
url.SchemeIs(url::kFileScheme) ||
url_points_to_an_approved_settings_page ||
(url.spec().compare(url::kAboutBlankURL) == 0)) {
urls.push_back(url);
}
}
return urls;
}
bool StartupBrowserCreator::ProcessCmdLineImpl( bool StartupBrowserCreator::ProcessCmdLineImpl(
const base::CommandLine& command_line, const base::CommandLine& command_line,
const base::FilePath& cur_dir, const base::FilePath& cur_dir,
...@@ -962,19 +934,6 @@ bool StartupBrowserCreator::LaunchBrowserForLastProfiles( ...@@ -962,19 +934,6 @@ bool StartupBrowserCreator::LaunchBrowserForLastProfiles(
bool process_startup, bool process_startup,
Profile* last_used_profile, Profile* last_used_profile,
const Profiles& last_opened_profiles) { const Profiles& last_opened_profiles) {
#if !BUILDFLAG(IS_CHROMEOS_ASH)
const std::vector<GURL> urls_to_launch =
StartupBrowserCreator::GetURLsFromCommandLine(command_line, cur_dir,
last_used_profile);
if (ProfilePicker::ShouldShowAtLaunch(command_line, urls_to_launch)) {
ProfilePicker::Show(
process_startup
? ProfilePicker::EntryPoint::kOnStartup
: ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
return true;
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
chrome::startup::IsProcessStartup is_process_startup = chrome::startup::IsProcessStartup is_process_startup =
process_startup ? chrome::startup::IS_PROCESS_STARTUP process_startup ? chrome::startup::IS_PROCESS_STARTUP
: chrome::startup::IS_NOT_PROCESS_STARTUP; : chrome::startup::IS_NOT_PROCESS_STARTUP;
...@@ -1010,7 +969,7 @@ bool StartupBrowserCreator::LaunchBrowserForLastProfiles( ...@@ -1010,7 +969,7 @@ bool StartupBrowserCreator::LaunchBrowserForLastProfiles(
} }
// Show UserManager if |last_used_profile| can't be auto opened. // Show UserManager if |last_used_profile| can't be auto opened.
ShowUserManagerOnStartup(); ShowUserManager(/*is_process_startup=*/process_startup);
return true; return true;
} }
return ProcessLastOpenedProfiles(command_line, cur_dir, is_process_startup, return ProcessLastOpenedProfiles(command_line, cur_dir, is_process_startup,
...@@ -1083,7 +1042,7 @@ bool StartupBrowserCreator::ProcessLastOpenedProfiles( ...@@ -1083,7 +1042,7 @@ bool StartupBrowserCreator::ProcessLastOpenedProfiles(
// activation this one. // activation this one.
#if !BUILDFLAG(IS_CHROMEOS_ASH) #if !BUILDFLAG(IS_CHROMEOS_ASH)
if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP) if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP)
ShowUserManagerOnStartup(); ShowUserManager(/*is_process_startup=*/true);
else else
#endif #endif
profile_launch_observer.Get().set_profile_to_activate(last_used_profile); profile_launch_observer.Get().set_profile_to_activate(last_used_profile);
...@@ -1189,6 +1148,82 @@ bool StartupBrowserCreator::ActivatedProfile() { ...@@ -1189,6 +1148,82 @@ bool StartupBrowserCreator::ActivatedProfile() {
return profile_launch_observer.Get().activated_profile(); return profile_launch_observer.Get().activated_profile();
} }
std::vector<GURL> GetURLsFromCommandLine(const base::CommandLine& command_line,
const base::FilePath& cur_dir,
Profile* profile) {
std::vector<GURL> urls;
const base::CommandLine::StringVector& params = command_line.GetArgs();
for (size_t i = 0; i < params.size(); ++i) {
base::FilePath param = base::FilePath(params[i]);
// Handle Vista way of searching - "? <search-term>"
if ((param.value().size() > 2) && (param.value()[0] == '?') &&
(param.value()[1] == ' ')) {
GURL url(GetDefaultSearchURLForSearchTerms(
TemplateURLServiceFactory::GetForProfile(profile),
param.LossyDisplayName().substr(2)));
if (url.is_valid()) {
urls.push_back(url);
continue;
}
}
// Otherwise, fall through to treating it as a URL.
// This will create a file URL or a regular URL.
// This call can (in rare circumstances) block the UI thread.
// Allow it until this bug is fixed.
// http://code.google.com/p/chromium/issues/detail?id=60641
GURL url = GURL(param.MaybeAsASCII());
// http://crbug.com/371030: Only use URLFixerUpper if we don't have a valid
// URL, otherwise we will look in the current directory for a file named
// 'about' if the browser was started with a about:foo argument.
// http://crbug.com/424991: Always use URLFixerUpper on file:// URLs,
// otherwise we wouldn't correctly handle '#' in a file name.
if (!url.is_valid() || url.SchemeIsFile()) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
url = url_formatter::FixupRelativeFile(cur_dir, param);
}
// Exclude dangerous schemes.
if (!url.is_valid())
continue;
const GURL settings_url = GURL(chrome::kChromeUISettingsURL);
bool url_points_to_an_approved_settings_page = false;
#if defined(OS_CHROMEOS)
// In ChromeOS, allow any settings page to be specified on the command line.
url_points_to_an_approved_settings_page =
url.GetOrigin() == settings_url.GetOrigin();
#else
// Exposed for external cleaners to offer a settings reset to the
// user. The allowed URLs must match exactly.
const GURL reset_settings_url =
settings_url.Resolve(chrome::kResetProfileSettingsSubPage);
url_points_to_an_approved_settings_page = url == reset_settings_url;
#if defined(OS_WIN)
// On Windows, also allow a hash for the Chrome Cleanup Tool.
const GURL reset_settings_url_with_cct_hash = reset_settings_url.Resolve(
std::string("#") +
settings::ResetSettingsHandler::kCctResetSettingsHash);
url_points_to_an_approved_settings_page =
url_points_to_an_approved_settings_page ||
url == reset_settings_url_with_cct_hash;
#endif // defined(OS_WIN)
#endif // defined(OS_CHROMEOS)
ChildProcessSecurityPolicy* policy =
ChildProcessSecurityPolicy::GetInstance();
if (policy->IsWebSafeScheme(url.scheme()) ||
url.SchemeIs(url::kFileScheme) ||
url_points_to_an_approved_settings_page ||
(url.spec().compare(url::kAboutBlankURL) == 0)) {
urls.push_back(url);
}
}
return urls;
}
bool HasPendingUncleanExit(Profile* profile) { bool HasPendingUncleanExit(Profile* profile) {
return profile->GetLastSessionExitType() == Profile::EXIT_CRASHED && return profile->GetLastSessionExitType() == Profile::EXIT_CRASHED &&
!profile_launch_observer.Get().HasBeenLaunched(profile); !profile_launch_observer.Get().HasBeenLaunched(profile);
...@@ -1226,8 +1261,31 @@ base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir, ...@@ -1226,8 +1261,31 @@ base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir,
#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID) #if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
Profile* GetStartupProfile(const base::FilePath& user_data_dir, Profile* GetStartupProfile(const base::FilePath& user_data_dir,
const base::FilePath& cur_dir,
const base::CommandLine& command_line) { const base::CommandLine& command_line) {
ProfileManager* profile_manager = g_browser_process->profile_manager(); ProfileManager* profile_manager = g_browser_process->profile_manager();
#if !defined(OS_CHROMEOS)
if (ShouldShowProfilePickerAtProcessLaunch(profile_manager, command_line)) {
// Open the picker only if no URLs have been provided to launch Chrome. If
// URLs are provided, open them in the last profile, instead.
Profile* guest_profile =
profile_manager->GetProfile(ProfileManager::GetGuestProfilePath());
// TODO(crbug.com/1150326): Consider resolving urls_to_launch without any
// profile so that the guest profile does not need to get created in case
// some URLs are passed and the picker is not shown in the end.
const std::vector<GURL> urls_to_launch =
GetURLsFromCommandLine(command_line, cur_dir, guest_profile);
if (urls_to_launch.empty() &&
profile_manager->GetProfile(ProfileManager::GetSystemProfilePath())) {
// To indicate that we want to show the profile picker, return the guest
// profile. However, we can only do this if the system profile (where the
// profile picker lives) also exists (or is creatable).
// TODO(crbug.com/1150326): Refactor this to indicate more directly that
// profile picker should be shown (returning an enum, or so).
return guest_profile;
}
}
#endif // !defined(OS_CHROMEOS)
base::FilePath profile_path = base::FilePath profile_path =
GetStartupProfilePath(user_data_dir, command_line); GetStartupProfilePath(user_data_dir, command_line);
...@@ -1248,6 +1306,8 @@ Profile* GetStartupProfile(const base::FilePath& user_data_dir, ...@@ -1248,6 +1306,8 @@ Profile* GetStartupProfile(const base::FilePath& user_data_dir,
// We want to show the user manager. To indicate this, return the guest // 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 // profile. However, we can only do this if the system profile (where the user
// manager lives) also exists (or is creatable). // manager lives) also exists (or is creatable).
// TODO(crbug.com/1150326): Refactor this to indicate more directly that
// profile picker should be shown (returning an enum, or so).
return profile_manager->GetProfile(ProfileManager::GetSystemProfilePath()) return profile_manager->GetProfile(ProfileManager::GetSystemProfilePath())
? profile_manager->GetProfile( ? profile_manager->GetProfile(
ProfileManager::GetGuestProfilePath()) ProfileManager::GetGuestProfilePath())
......
...@@ -164,12 +164,6 @@ class StartupBrowserCreator { ...@@ -164,12 +164,6 @@ class StartupBrowserCreator {
Profile* last_used_profile, Profile* last_used_profile,
const Profiles& last_opened_profiles); const Profiles& last_opened_profiles);
// Returns the list of URLs to open from the command line.
static std::vector<GURL> GetURLsFromCommandLine(
const base::CommandLine& command_line,
const base::FilePath& cur_dir,
Profile* profile);
// This function performs command-line handling and is invoked only after // This function performs command-line handling and is invoked only after
// start up (for example when we get a start request for another process). // start up (for example when we get a start request for another process).
// |command_line| holds the command line being processed. // |command_line| holds the command line being processed.
...@@ -205,6 +199,11 @@ class StartupBrowserCreator { ...@@ -205,6 +199,11 @@ class StartupBrowserCreator {
static bool in_synchronous_profile_launch_; static bool in_synchronous_profile_launch_;
}; };
// Returns the list of URLs to open from the command line.
std::vector<GURL> GetURLsFromCommandLine(const base::CommandLine& command_line,
const base::FilePath& cur_dir,
Profile* profile);
// Returns true if |profile| has exited uncleanly and has not been launched // Returns true if |profile| has exited uncleanly and has not been launched
// after the unclean exit. // after the unclean exit.
bool HasPendingUncleanExit(Profile* profile); bool HasPendingUncleanExit(Profile* profile);
...@@ -222,6 +221,7 @@ base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir, ...@@ -222,6 +221,7 @@ base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir,
// opening the user manager, returns null if either the guest profile or the // opening the user manager, returns null if either the guest profile or the
// system profile cannot be opened. // system profile cannot be opened.
Profile* GetStartupProfile(const base::FilePath& user_data_dir, Profile* GetStartupProfile(const base::FilePath& user_data_dir,
const base::FilePath& cur_dir,
const base::CommandLine& command_line); const base::CommandLine& command_line);
// Returns the profile that should be loaded on process startup when // Returns the profile that should be loaded on process startup when
......
...@@ -2179,8 +2179,8 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -2179,8 +2179,8 @@ INSTANTIATE_TEST_SUITE_P(
/*switch_name=*/base::nullopt, /*switch_name=*/base::nullopt,
/*switch_value_ascii=*/base::nullopt, /*switch_value_ascii=*/base::nullopt,
/*url_arg=*/GURL("https://www.foo.com/")}, /*url_arg=*/GURL("https://www.foo.com/")},
// Picker should be shown also in session restore. // Picker should also not be shown in session restore.
ProfilePickerSetup{/*expected_to_show=*/true, ProfilePickerSetup{/*expected_to_show=*/false,
/*switch_name=*/base::nullopt, /*switch_name=*/base::nullopt,
/*switch_value_ascii=*/base::nullopt, /*switch_value_ascii=*/base::nullopt,
/*url_arg=*/base::nullopt, /*url_arg=*/base::nullopt,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment