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 "chrome/browser/ui/startup/startup_browser_creator.h"
6 
7 #include <stddef.h>
8 
9 #include <set>
10 #include <string>
11 #include <utility>
12 
13 #include "apps/switches.h"
14 #include "base/bind.h"
15 #include "base/callback_helpers.h"
16 #include "base/command_line.h"
17 #include "base/feature_list.h"
18 #include "base/files/file_path.h"
19 #include "base/files/file_util.h"
20 #include "base/lazy_instance.h"
21 #include "base/logging.h"
22 #include "base/memory/ptr_util.h"
23 #include "base/metrics/histogram_base.h"
24 #include "base/metrics/histogram_macros.h"
25 #include "base/metrics/statistics_recorder.h"
26 #include "base/scoped_observer.h"
27 #include "base/strings/string16.h"
28 #include "base/strings/string_tokenizer.h"
29 #include "base/task/thread_pool.h"
30 #include "base/threading/scoped_blocking_call.h"
31 #include "base/trace_event/trace_event.h"
32 #include "build/branding_buildflags.h"
33 #include "build/build_config.h"
34 #include "chrome/browser/app_mode/app_mode_utils.h"
35 #include "chrome/browser/apps/platform_apps/app_load_service.h"
36 #include "chrome/browser/browser_process.h"
37 #include "chrome/browser/chromeos/app_mode/kiosk_app_types.h"
38 #include "chrome/browser/chromeos/profiles/profile_helper.h"
39 #include "chrome/browser/extensions/startup_helper.h"
40 #include "chrome/browser/first_run/first_run.h"
41 #include "chrome/browser/prefs/incognito_mode_prefs.h"
42 #include "chrome/browser/prefs/session_startup_pref.h"
43 #include "chrome/browser/profiles/profile.h"
44 #include "chrome/browser/profiles/profile_attributes_entry.h"
45 #include "chrome/browser/profiles/profile_attributes_storage.h"
46 #include "chrome/browser/profiles/profile_manager.h"
47 #include "chrome/browser/profiles/profile_observer.h"
48 #include "chrome/browser/profiles/profiles_state.h"
49 #include "chrome/browser/search_engines/template_url_service_factory.h"
50 #include "chrome/browser/ui/browser.h"
51 #include "chrome/browser/ui/browser_finder.h"
52 #include "chrome/browser/ui/browser_list.h"
53 #include "chrome/browser/ui/browser_list_observer.h"
54 #include "chrome/browser/ui/browser_window.h"
55 #include "chrome/browser/ui/startup/launch_mode_recorder.h"
56 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
57 #include "chrome/browser/ui/ui_features.h"
58 #include "chrome/common/buildflags.h"
59 #include "chrome/common/chrome_constants.h"
60 #include "chrome/common/chrome_features.h"
61 #include "chrome/common/chrome_switches.h"
62 #include "chrome/common/pref_names.h"
63 #include "chrome/common/url_constants.h"
64 #include "components/prefs/pref_registry_simple.h"
65 #include "components/prefs/pref_service.h"
66 #include "components/search_engines/util.h"
67 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
68 #include "components/url_formatter/url_fixer.h"
69 #include "content/public/browser/browser_task_traits.h"
70 #include "content/public/browser/browser_thread.h"
71 #include "content/public/browser/child_process_security_policy.h"
72 #include "content/public/browser/navigation_controller.h"
73 #include "content/public/common/content_switches.h"
74 #include "extensions/common/switches.h"
75 #include "printing/buildflags/buildflags.h"
76 
77 #if defined(OS_CHROMEOS)
78 #include "chrome/browser/chromeos/app_mode/app_launch_utils.h"
79 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
80 #include "chrome/browser/lifetime/application_lifetime.h"
81 #include "chromeos/constants/chromeos_switches.h"
82 #include "chromeos/cryptohome/cryptohome_parameters.h"
83 #include "components/user_manager/user_manager.h"
84 #else
85 #include "chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.h"
86 #include "chrome/browser/ui/profile_picker.h"
87 #include "chrome/browser/ui/user_manager.h"
88 #endif
89 
90 #if defined(TOOLKIT_VIEWS) && defined(USE_X11)
91 #include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
92 #endif
93 
94 #if defined(OS_MAC)
95 #include "chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h"
96 #endif
97 
98 #if defined(OS_WIN)
99 #include "base/strings/utf_string_conversions.h"
100 #include "chrome/browser/metrics/jumplist_metrics_win.h"
101 #include "chrome/browser/notifications/notification_platform_bridge_win.h"
102 #include "chrome/browser/notifications/win/notification_launch_id.h"
103 #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win.h"
104 #include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
105 #include "chrome/credential_provider/common/gcp_strings.h"
106 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
107 #include "chrome/browser/printing/print_dialog_cloud_win.h"
108 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
109 #endif  // defined(OS_WIN)
110 
111 #if defined(USE_X11)
112 #include "ui/base/ui_base_features.h"
113 #endif
114 
115 using content::BrowserThread;
116 using content::ChildProcessSecurityPolicy;
117 
118 namespace {
119 
120 // Keeps track on which profiles have been launched.
121 class ProfileLaunchObserver : public ProfileObserver,
122                               public BrowserListObserver {
123  public:
ProfileLaunchObserver()124   ProfileLaunchObserver() { BrowserList::AddObserver(this); }
125   ProfileLaunchObserver(const ProfileLaunchObserver&) = delete;
126   ProfileLaunchObserver& operator=(const ProfileLaunchObserver&) = delete;
~ProfileLaunchObserver()127   ~ProfileLaunchObserver() override { BrowserList::RemoveObserver(this); }
128 
129   // BrowserListObserver:
OnBrowserAdded(Browser * browser)130   void OnBrowserAdded(Browser* browser) override {
131     opened_profiles_.insert(browser->profile());
132     MaybeActivateProfile();
133   }
134 
135   // ProfileObserver:
OnProfileWillBeDestroyed(Profile * profile)136   void OnProfileWillBeDestroyed(Profile* profile) override {
137     observed_profiles_.Remove(profile);
138     launched_profiles_.erase(profile);
139     opened_profiles_.erase(profile);
140     if (profile == profile_to_activate_)
141       profile_to_activate_ = nullptr;
142     // If this profile was the last launched one without an opened window,
143     // then we may be ready to activate |profile_to_activate_|.
144     MaybeActivateProfile();
145   }
146 
HasBeenLaunched(const Profile * profile) const147   bool HasBeenLaunched(const Profile* profile) const {
148     return launched_profiles_.find(profile) != launched_profiles_.end();
149   }
150 
AddLaunched(Profile * profile)151   void AddLaunched(Profile* profile) {
152     if (!observed_profiles_.IsObserving(profile))
153       observed_profiles_.Add(profile);
154     launched_profiles_.insert(profile);
155     if (chrome::FindBrowserWithProfile(profile)) {
156       // A browser may get opened before we get initialized (e.g., in tests),
157       // so we never see the OnBrowserAdded() for it.
158       opened_profiles_.insert(profile);
159     }
160   }
161 
Clear()162   void Clear() {
163     launched_profiles_.clear();
164     opened_profiles_.clear();
165   }
166 
activated_profile()167   bool activated_profile() { return activated_profile_; }
168 
set_profile_to_activate(Profile * profile)169   void set_profile_to_activate(Profile* profile) {
170     if (!observed_profiles_.IsObserving(profile))
171       observed_profiles_.Add(profile);
172     profile_to_activate_ = profile;
173     MaybeActivateProfile();
174   }
175 
176  private:
MaybeActivateProfile()177   void MaybeActivateProfile() {
178     if (!profile_to_activate_)
179       return;
180     // Check that browsers have been opened for all the launched profiles.
181     // Note that browsers opened for profiles that were not added as launched
182     // profiles are simply ignored.
183     auto i = launched_profiles_.begin();
184     for (; i != launched_profiles_.end(); ++i) {
185       if (opened_profiles_.find(*i) == opened_profiles_.end())
186         return;
187     }
188     // Asynchronous post to give a chance to the last window to completely
189     // open and activate before trying to activate |profile_to_activate_|.
190     content::GetUIThreadTaskRunner({})->PostTask(
191         FROM_HERE, base::BindOnce(&ProfileLaunchObserver::ActivateProfile,
192                                   base::Unretained(this)));
193     // Avoid posting more than once before ActivateProfile gets called.
194     observed_profiles_.RemoveAll();
195     BrowserList::RemoveObserver(this);
196   }
197 
ActivateProfile()198   void ActivateProfile() {
199     // We need to test again, in case the profile got deleted in the mean time.
200     if (profile_to_activate_) {
201       Browser* browser = chrome::FindBrowserWithProfile(profile_to_activate_);
202       // |profile| may never get launched, e.g., if it only had
203       // incognito Windows and one of them was used to exit Chrome.
204       // So it won't have a browser in that case.
205       if (browser)
206         browser->window()->Activate();
207       // No need try to activate this profile again.
208       profile_to_activate_ = nullptr;
209     }
210     // Assign true here, even if no browser was actually activated, so that
211     // the test can stop waiting, and fail gracefully when needed.
212     activated_profile_ = true;
213   }
214 
215   // These are the profiles that get launched by
216   // StartupBrowserCreator::LaunchBrowser.
217   std::set<const Profile*> launched_profiles_;
218   // These are the profiles for which at least one browser window has been
219   // opened. This is needed to know when it is safe to activate
220   // |profile_to_activate_|, otherwise, new browser windows being opened will
221   // be activated on top of it.
222   std::set<const Profile*> opened_profiles_;
223   // This is null until the profile to activate has been chosen. This value
224   // should only be set once all profiles have been launched, otherwise,
225   // activation may not happen after the launch of newer profiles.
226   Profile* profile_to_activate_ = nullptr;
227   // Set once we attempted to activate a profile. We only get one shot at this.
228   bool activated_profile_ = false;
229   ScopedObserver<Profile, ProfileObserver> observed_profiles_{this};
230 };
231 
232 base::LazyInstance<ProfileLaunchObserver>::DestructorAtExit
233     profile_launch_observer = LAZY_INSTANCE_INITIALIZER;
234 
235 // Dumps the current set of the browser process's histograms to |output_file|.
236 // The file is overwritten if it exists. This function should only be called in
237 // the blocking pool.
DumpBrowserHistograms(const base::FilePath & output_file)238 void DumpBrowserHistograms(const base::FilePath& output_file) {
239   std::string output_string(
240       base::StatisticsRecorder::ToJSON(base::JSON_VERBOSITY_LEVEL_FULL));
241 
242   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
243                                                 base::BlockingType::MAY_BLOCK);
244   base::WriteFile(output_file, output_string.data(),
245                   static_cast<int>(output_string.size()));
246 }
247 
248 // Returns whether |profile| can be opened during Chrome startup without
249 // explicit user action.
CanOpenProfileOnStartup(Profile * profile)250 bool CanOpenProfileOnStartup(Profile* profile) {
251 #if defined(OS_CHROMEOS)
252   // On ChromeOS, the user has already chosen and logged into the profile before
253   // Chrome starts up.
254   return true;
255 #else
256   // Profiles that require signin are not available.
257   ProfileAttributesEntry* entry = nullptr;
258   if (g_browser_process->profile_manager()
259           ->GetProfileAttributesStorage()
260           .GetProfileAttributesWithPath(profile->GetPath(), &entry) &&
261       entry->IsSigninRequired()) {
262     return false;
263   }
264 
265   // Guest or system profiles are not available unless a separate process
266   // already has a window open for the profile.
267   if (profile->IsEphemeralGuestProfile())
268     return chrome::GetBrowserCount(profile->GetOriginalProfile()) > 0;
269 
270   return (!profile->IsGuestSession() && !profile->IsSystemProfile()) ||
271          (chrome::GetBrowserCount(profile->GetPrimaryOTRProfile()) > 0);
272 #endif
273 }
274 
ShowUserManagerOnStartup()275 void ShowUserManagerOnStartup() {
276 #if !defined(OS_CHROMEOS)
277   UserManager::Show(base::FilePath(),
278                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
279 #endif  // !defined(OS_CHROMEOS)
280 }
281 
IsSilentLaunchEnabled(const base::CommandLine & command_line,const Profile * profile)282 bool IsSilentLaunchEnabled(const base::CommandLine& command_line,
283                            const Profile* profile) {
284   // Note: This check should have been done in ProcessCmdLineImpl()
285   // before calling this function. However chromeos/login/login_utils.cc
286   // calls this function directly (see comments there) so it has to be checked
287   // again.
288 
289   if (command_line.HasSwitch(switches::kSilentLaunch))
290     return true;
291 
292 #if defined(OS_CHROMEOS)
293   return profile->GetPrefs()->GetBoolean(
294       prefs::kStartupBrowserWindowLaunchSuppressed);
295 #endif  // defined(OS_CHROMEOS)
296 
297   return false;
298 }
299 
300 }  // namespace
301 
302 StartupBrowserCreator::StartupBrowserCreator() = default;
303 
304 StartupBrowserCreator::~StartupBrowserCreator() = default;
305 
306 // static
307 bool StartupBrowserCreator::was_restarted_read_ = false;
308 
309 // static
310 bool StartupBrowserCreator::in_synchronous_profile_launch_ = false;
311 
AddFirstRunTab(const GURL & url)312 void StartupBrowserCreator::AddFirstRunTab(const GURL& url) {
313   first_run_tabs_.push_back(url);
314 }
315 
Start(const base::CommandLine & cmd_line,const base::FilePath & cur_dir,Profile * last_used_profile,const Profiles & last_opened_profiles)316 bool StartupBrowserCreator::Start(const base::CommandLine& cmd_line,
317                                   const base::FilePath& cur_dir,
318                                   Profile* last_used_profile,
319                                   const Profiles& last_opened_profiles) {
320   TRACE_EVENT0("startup", "StartupBrowserCreator::Start");
321   SCOPED_UMA_HISTOGRAM_TIMER("Startup.StartupBrowserCreator_Start");
322   return ProcessCmdLineImpl(cmd_line, cur_dir, true, last_used_profile,
323                             last_opened_profiles);
324 }
325 
326 // static
InSynchronousProfileLaunch()327 bool StartupBrowserCreator::InSynchronousProfileLaunch() {
328   return in_synchronous_profile_launch_;
329 }
330 
LaunchBrowser(const base::CommandLine & command_line,Profile * profile,const base::FilePath & cur_dir,chrome::startup::IsProcessStartup process_startup,chrome::startup::IsFirstRun is_first_run,std::unique_ptr<LaunchModeRecorder> launch_mode_recorder)331 bool StartupBrowserCreator::LaunchBrowser(
332     const base::CommandLine& command_line,
333     Profile* profile,
334     const base::FilePath& cur_dir,
335     chrome::startup::IsProcessStartup process_startup,
336     chrome::startup::IsFirstRun is_first_run,
337     std::unique_ptr<LaunchModeRecorder> launch_mode_recorder) {
338   DCHECK(profile);
339 #if defined(OS_WIN)
340   DCHECK(!command_line.HasSwitch(credential_provider::kGcpwSigninSwitch));
341   DCHECK(!command_line.HasSwitch(switches::kNotificationLaunchId));
342 #endif  // defined(OS_WIN)
343   in_synchronous_profile_launch_ =
344       process_startup == chrome::startup::IS_PROCESS_STARTUP;
345 
346   // Continue with the incognito profile from here on if Incognito mode is
347   // forced.
348   if (IncognitoModePrefs::ShouldLaunchIncognito(command_line,
349                                                 profile->GetPrefs())) {
350     profile = profile->GetPrimaryOTRProfile();
351   } else if (command_line.HasSwitch(switches::kIncognito)) {
352     LOG(WARNING) << "Incognito mode disabled by policy, launching a normal "
353                  << "browser session.";
354   }
355 
356   if (profiles::IsGuestModeRequested(command_line,
357                                      g_browser_process->local_state(),
358                                      /* show_warning= */ true)) {
359     profile = g_browser_process->profile_manager()->GetProfile(
360         ProfileManager::GetGuestProfilePath());
361     if (!profile->IsEphemeralGuestProfile())
362       profile = profile->GetPrimaryOTRProfile();
363   }
364 
365   if (!IsSilentLaunchEnabled(command_line, profile)) {
366     StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
367     const std::vector<GURL> urls_to_launch =
368         GetURLsFromCommandLine(command_line, cur_dir, profile);
369     const bool launched =
370         lwp.Launch(profile, urls_to_launch, in_synchronous_profile_launch_,
371                    std::move(launch_mode_recorder));
372     in_synchronous_profile_launch_ = false;
373     if (!launched) {
374       LOG(ERROR) << "launch error";
375       return false;
376     }
377   } else {
378     in_synchronous_profile_launch_ = false;
379   }
380 
381   profile_launch_observer.Get().AddLaunched(profile);
382 
383   return true;
384 }
385 
386 // static
WasRestarted()387 bool StartupBrowserCreator::WasRestarted() {
388   // Stores the value of the preference kWasRestarted had when it was read.
389   static bool was_restarted = false;
390 
391   if (!was_restarted_read_) {
392     PrefService* pref_service = g_browser_process->local_state();
393     was_restarted = pref_service->GetBoolean(prefs::kWasRestarted);
394     pref_service->SetBoolean(prefs::kWasRestarted, false);
395     was_restarted_read_ = true;
396   }
397   return was_restarted;
398 }
399 
400 // static
GetSessionStartupPref(const base::CommandLine & command_line,const Profile * profile)401 SessionStartupPref StartupBrowserCreator::GetSessionStartupPref(
402     const base::CommandLine& command_line,
403     const Profile* profile) {
404   DCHECK(profile);
405   const PrefService* prefs = profile->GetPrefs();
406   SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
407 
408   // IsChromeFirstRun() looks for a sentinel file to determine whether the user
409   // is starting Chrome for the first time. On Chrome OS, the sentinel is stored
410   // in a location shared by all users and the check is meaningless. Query the
411   // UserManager instead to determine whether the user is new.
412 #if defined(OS_CHROMEOS)
413   const bool is_first_run =
414       user_manager::UserManager::Get()->IsCurrentUserNew();
415   // On ChromeOS restarts force the user to login again. The expectation is that
416   // after a login the user gets clean state. For this reason we ignore
417   // StartupBrowserCreator::WasRestarted(). However
418   // StartupBrowserCreator::WasRestarted has to be called in order to correctly
419   // update pref values.
420   const bool did_restart = false;
421   StartupBrowserCreator::WasRestarted();
422 #else
423   const bool is_first_run = first_run::IsChromeFirstRun();
424   const bool did_restart = StartupBrowserCreator::WasRestarted();
425 #endif
426 
427   // The pref has an OS-dependent default value. For the first run only, this
428   // default is overridden with SessionStartupPref::DEFAULT so that first run
429   // behavior (sync promo, welcome page) is consistently invoked.
430   // This applies only if the pref is still at its default and has not been
431   // set by the user, managed prefs or policy.
432   if (is_first_run && SessionStartupPref::TypeIsDefault(prefs))
433     pref.type = SessionStartupPref::DEFAULT;
434 
435   // The switches::kRestoreLastSession command line switch is used to restore
436   // sessions after a browser self restart (e.g. after a Chrome upgrade).
437   // However, new profiles can be created from a browser process that has this
438   // switch so do not set the session pref to SessionStartupPref::LAST for
439   // those as there is nothing to restore.
440   if ((command_line.HasSwitch(switches::kRestoreLastSession) || did_restart) &&
441       !profile->IsNewProfile()) {
442     pref.type = SessionStartupPref::LAST;
443   }
444 
445   // A browser starting for a profile being unlocked should always restore.
446   if (!profile->IsGuestSession() && !profile->IsEphemeralGuestProfile()) {
447     ProfileAttributesEntry* entry = nullptr;
448     bool has_entry =
449         g_browser_process->profile_manager()
450             ->GetProfileAttributesStorage()
451             .GetProfileAttributesWithPath(profile->GetPath(), &entry);
452 
453     if (has_entry && entry->IsSigninRequired())
454       pref.type = SessionStartupPref::LAST;
455   }
456 
457   if (pref.type == SessionStartupPref::LAST && profile->IsOffTheRecord()) {
458     // We don't store session information when incognito. If the user has
459     // chosen to restore last session and launched incognito, fallback to
460     // default launch behavior.
461     pref.type = SessionStartupPref::DEFAULT;
462   }
463 
464   return pref;
465 }
466 
467 // static
ClearLaunchedProfilesForTesting()468 void StartupBrowserCreator::ClearLaunchedProfilesForTesting() {
469   profile_launch_observer.Get().Clear();
470 }
471 
472 // static
RegisterLocalStatePrefs(PrefRegistrySimple * registry)473 void StartupBrowserCreator::RegisterLocalStatePrefs(
474     PrefRegistrySimple* registry) {
475 #if !defined(OS_CHROMEOS)
476   registry->RegisterBooleanPref(prefs::kPromotionalTabsEnabled, true);
477   registry->RegisterBooleanPref(prefs::kCommandLineFlagSecurityWarningsEnabled,
478                                 true);
479 #endif
480   registry->RegisterBooleanPref(prefs::kSuppressUnsupportedOSWarning, false);
481   registry->RegisterBooleanPref(prefs::kWasRestarted, false);
482 
483 #if defined(OS_WIN)
484   registry->RegisterStringPref(prefs::kShortcutMigrationVersion, std::string());
485 #endif
486 }
487 
488 // static
RegisterProfilePrefs(PrefRegistrySimple * registry)489 void StartupBrowserCreator::RegisterProfilePrefs(PrefRegistrySimple* registry) {
490   // Default to true so that existing users are not shown the Welcome page.
491   // ProfileManager handles setting this to false for new profiles upon
492   // creation.
493   registry->RegisterBooleanPref(prefs::kHasSeenWelcomePage, true);
494 #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
495   // This will be set for newly created profiles, and is used to indicate which
496   // users went through onboarding with the current experiment group.
497   registry->RegisterStringPref(prefs::kNaviOnboardGroup, "");
498 #endif  // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
499 }
500 
501 // static
GetURLsFromCommandLine(const base::CommandLine & command_line,const base::FilePath & cur_dir,Profile * profile)502 std::vector<GURL> StartupBrowserCreator::GetURLsFromCommandLine(
503     const base::CommandLine& command_line,
504     const base::FilePath& cur_dir,
505     Profile* profile) {
506   DCHECK(profile);
507 
508   std::vector<GURL> urls;
509 
510   const base::CommandLine::StringVector& params = command_line.GetArgs();
511   for (size_t i = 0; i < params.size(); ++i) {
512     base::FilePath param = base::FilePath(params[i]);
513     // Handle Vista way of searching - "? <search-term>"
514     if ((param.value().size() > 2) && (param.value()[0] == '?') &&
515         (param.value()[1] == ' ')) {
516       GURL url(GetDefaultSearchURLForSearchTerms(
517           TemplateURLServiceFactory::GetForProfile(profile),
518           param.LossyDisplayName().substr(2)));
519       if (url.is_valid()) {
520         urls.push_back(url);
521         continue;
522       }
523     }
524 
525     // Otherwise, fall through to treating it as a URL.
526 
527     // This will create a file URL or a regular URL.
528     // This call can (in rare circumstances) block the UI thread.
529     // Allow it until this bug is fixed.
530     //  http://code.google.com/p/chromium/issues/detail?id=60641
531     GURL url = GURL(param.MaybeAsASCII());
532 
533     // http://crbug.com/371030: Only use URLFixerUpper if we don't have a valid
534     // URL, otherwise we will look in the current directory for a file named
535     // 'about' if the browser was started with a about:foo argument.
536     // http://crbug.com/424991: Always use URLFixerUpper on file:// URLs,
537     // otherwise we wouldn't correctly handle '#' in a file name.
538     if (!url.is_valid() || url.SchemeIsFile()) {
539       base::ThreadRestrictions::ScopedAllowIO allow_io;
540       url = url_formatter::FixupRelativeFile(cur_dir, param);
541     }
542     // Exclude dangerous schemes.
543     if (!url.is_valid())
544       continue;
545 
546     const GURL settings_url = GURL(chrome::kChromeUISettingsURL);
547     bool url_points_to_an_approved_settings_page = false;
548 #if defined(OS_CHROMEOS)
549     // In ChromeOS, allow any settings page to be specified on the command line.
550     url_points_to_an_approved_settings_page =
551         url.GetOrigin() == settings_url.GetOrigin();
552 #else
553     // Exposed for external cleaners to offer a settings reset to the
554     // user. The allowed URLs must match exactly.
555     const GURL reset_settings_url =
556         settings_url.Resolve(chrome::kResetProfileSettingsSubPage);
557     url_points_to_an_approved_settings_page = url == reset_settings_url;
558 #if defined(OS_WIN)
559     // On Windows, also allow a hash for the Chrome Cleanup Tool.
560     const GURL reset_settings_url_with_cct_hash = reset_settings_url.Resolve(
561         std::string("#") +
562         settings::ResetSettingsHandler::kCctResetSettingsHash);
563     url_points_to_an_approved_settings_page =
564         url_points_to_an_approved_settings_page ||
565         url == reset_settings_url_with_cct_hash;
566 #endif  // defined(OS_WIN)
567 #endif  // defined(OS_CHROMEOS)
568 
569     ChildProcessSecurityPolicy* policy =
570         ChildProcessSecurityPolicy::GetInstance();
571     if (policy->IsWebSafeScheme(url.scheme()) ||
572         url.SchemeIs(url::kFileScheme) ||
573         url_points_to_an_approved_settings_page ||
574         (url.spec().compare(url::kAboutBlankURL) == 0)) {
575       urls.push_back(url);
576     }
577   }
578   return urls;
579 }
580 
ProcessCmdLineImpl(const base::CommandLine & command_line,const base::FilePath & cur_dir,bool process_startup,Profile * last_used_profile,const Profiles & last_opened_profiles)581 bool StartupBrowserCreator::ProcessCmdLineImpl(
582     const base::CommandLine& command_line,
583     const base::FilePath& cur_dir,
584     bool process_startup,
585     Profile* last_used_profile,
586     const Profiles& last_opened_profiles) {
587   DCHECK_CURRENTLY_ON(BrowserThread::UI);
588   TRACE_EVENT0("startup", "StartupBrowserCreator::ProcessCmdLineImpl");
589 
590   DCHECK(last_used_profile);
591   if (process_startup &&
592       command_line.HasSwitch(switches::kDisablePromptOnRepost)) {
593     content::NavigationController::DisablePromptOnRepost();
594   }
595 
596   bool silent_launch = false;
597   bool can_use_last_profile =
598       (CanOpenProfileOnStartup(last_used_profile) &&
599        !IncognitoModePrefs::ShouldLaunchIncognito(
600            command_line, last_used_profile->GetPrefs()));
601 
602 #if defined(OS_WIN) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
603   // If we are just displaying a print dialog we shouldn't open browser
604   // windows.
605   if (command_line.HasSwitch(switches::kCloudPrintFile) &&
606       can_use_last_profile &&
607       print_dialog_cloud::CreatePrintDialogFromCommandLine(last_used_profile,
608                                                            command_line)) {
609     silent_launch = true;
610   }
611 #endif  // defined(OS_WIN) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
612 
613   if (command_line.HasSwitch(switches::kValidateCrx)) {
614     if (!process_startup) {
615       LOG(ERROR) << "chrome is already running; you must close all running "
616                  << "instances before running with the --"
617                  << switches::kValidateCrx << " flag";
618       return false;
619     }
620     extensions::StartupHelper helper;
621     std::string message;
622     std::string error;
623     if (helper.ValidateCrx(command_line, &error))
624       message = std::string("ValidateCrx Success");
625     else
626       message = std::string("ValidateCrx Failure: ") + error;
627     printf("%s\n", message.c_str());
628     return false;
629   }
630 
631 #if defined(OS_CHROMEOS)
632 
633   // The browser will be launched after the user logs in.
634   if (command_line.HasSwitch(chromeos::switches::kLoginManager))
635     silent_launch = true;
636 
637   if (chrome::IsRunningInForcedAppMode()) {
638     user_manager::User* user =
639         chromeos::ProfileHelper::Get()->GetUserByProfile(last_used_profile);
640     if (user && user->GetType() == user_manager::USER_TYPE_KIOSK_APP) {
641       chromeos::LaunchAppOrDie(
642           last_used_profile,
643           chromeos::KioskAppId::ForChromeApp(
644               command_line.GetSwitchValueASCII(switches::kAppId)));
645     } else if (user &&
646                user->GetType() == user_manager::USER_TYPE_WEB_KIOSK_APP) {
647       chromeos::LaunchAppOrDie(
648           last_used_profile,
649           chromeos::KioskAppId::ForWebApp(user->GetAccountId()));
650     } else {
651       // If we are here, we are either in ARC kiosk session or the user is
652       // invalid. We should terminate the session in such cases.
653       chrome::AttemptUserExit();
654       return false;
655     }
656 
657     // Skip browser launch since app mode launches its app window.
658     silent_launch = true;
659   }
660 
661   // If we are a demo app session and we crashed, there is no safe recovery
662   // possible. We should instead cleanly exit and go back to the OOBE screen,
663   // where we will launch again after the timeout has expired.
664   if (chromeos::DemoAppLauncher::IsDemoAppSession(
665           cryptohome::Identification::FromString(
666               command_line.GetSwitchValueASCII(chromeos::switches::kLoginUser))
667               .GetAccountId())) {
668     chrome::AttemptUserExit();
669     return false;
670   }
671 #endif  // OS_CHROMEOS
672 
673 #if defined(TOOLKIT_VIEWS) && defined(USE_X11)
674   if (!features::IsUsingOzonePlatform()) {
675     // Ozone sets the device list upon platform initialisation.
676     ui::TouchFactory::SetTouchDeviceListFromCommandLine();
677   }
678 #endif
679 
680 #if defined(OS_MAC)
681   if (web_app::MaybeRebuildShortcut(command_line))
682     return true;
683 #endif
684 
685   if (!process_startup &&
686       command_line.HasSwitch(switches::kDumpBrowserHistograms)) {
687     // Only handle --dump-browser-histograms from a rendezvous. In this case, do
688     // not open a new browser window even if no output file was given.
689     base::FilePath output_file(
690         command_line.GetSwitchValuePath(switches::kDumpBrowserHistograms));
691     if (!output_file.empty()) {
692       base::ThreadPool::PostTask(
693           FROM_HERE,
694           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
695            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
696           base::BindOnce(&DumpBrowserHistograms, output_file));
697     }
698     silent_launch = true;
699   }
700 
701 #if !defined(OS_CHROMEOS)
702   if (base::FeatureList::IsEnabled(features::kOnConnectNative) &&
703       command_line.HasSwitch(switches::kNativeMessagingConnectHost) &&
704       command_line.HasSwitch(switches::kNativeMessagingConnectExtension)) {
705     extensions::LaunchNativeMessageHostFromNativeApp(
706         command_line.GetSwitchValueASCII(
707             switches::kNativeMessagingConnectExtension),
708         command_line.GetSwitchValueASCII(switches::kNativeMessagingConnectHost),
709         command_line.GetSwitchValueASCII(switches::kNativeMessagingConnectId),
710         last_used_profile);
711 
712     // Chrome's lifetime, if the specified extension and native messaging host
713     // are both valid and a connection is established, is prolonged by
714     // BackgroundModeManager. If |process_startup| is true, --no-startup-window
715     // must be set or a browser window must be created for BackgroundModeManager
716     // to start background mode. Without this, nothing will take the first
717     // keep-alive and the browser process will not terminate. To avoid this
718     // situation, don't set |silent_launch| in response to the native messaging
719     // connect switches; require the client to pass --no-startup-window if
720     // suppressing the creation of a window is desired.
721   }
722 #endif
723 
724   // If --no-startup-window is specified and Chrome is already running then do
725   // not open a new window.
726   if (!process_startup && command_line.HasSwitch(switches::kNoStartupWindow))
727     silent_launch = true;
728 
729   // If we don't want to launch a new browser window or tab we are done here.
730   if (silent_launch) {
731     if (process_startup)
732       startup_metric_utils::SetNonBrowserUIDisplayed();
733     return true;
734   }
735 
736   if (command_line.HasSwitch(extensions::switches::kLoadApps) &&
737       can_use_last_profile) {
738     if (!ProcessLoadApps(command_line, cur_dir, last_used_profile))
739       return false;
740 
741     // Return early here to avoid opening a browser window.
742     // The exception is when there are no browser windows, since we don't want
743     // chrome to shut down.
744     // TODO(jackhou): Do this properly once keep-alive is handled by the
745     // background page of apps. Tracked at http://crbug.com/175381
746     if (chrome::GetBrowserCount(last_used_profile) != 0)
747       return true;
748   }
749 
750   // Check for --load-and-launch-app.
751   if (command_line.HasSwitch(apps::kLoadAndLaunchApp) && can_use_last_profile) {
752     base::CommandLine::StringType path =
753         command_line.GetSwitchValueNative(apps::kLoadAndLaunchApp);
754 
755     if (!apps::AppLoadService::Get(last_used_profile)
756              ->LoadAndLaunch(base::FilePath(path), command_line, cur_dir)) {
757       return false;
758     }
759 
760     // Return early here since we don't want to open a browser window.
761     // The exception is when there are no browser windows, since we don't want
762     // chrome to shut down.
763     // TODO(jackhou): Do this properly once keep-alive is handled by the
764     // background page of apps. Tracked at http://crbug.com/175381
765     if (chrome::GetBrowserCount(last_used_profile) != 0)
766       return true;
767   }
768 
769 #if defined(OS_WIN)
770   // Log whether this process was a result of an action in the Windows Jumplist.
771   if (command_line.HasSwitch(switches::kWinJumplistAction)) {
772     jumplist::LogJumplistActionFromSwitchValue(
773         command_line.GetSwitchValueASCII(switches::kWinJumplistAction));
774     // Use a non-NULL pointer to indicate JumpList has been used. We re-use
775     // chrome::kJumpListIconDirname as the key to the data.
776     last_used_profile->SetUserData(
777         chrome::kJumpListIconDirname,
778         base::WrapUnique(new base::SupportsUserData::Data()));
779   }
780 
781   // If the command line has the kNotificationLaunchId switch, then this
782   // call is from notification_helper.exe to process toast activation.
783   // Delegate to the notification system; do not open a browser window here.
784   if (command_line.HasSwitch(switches::kNotificationLaunchId)) {
785     if (NotificationPlatformBridgeWin::HandleActivation(command_line)) {
786       LaunchModeRecorder().SetLaunchMode(LaunchMode::kWinPlatformNotification);
787       return true;
788     }
789     return false;
790   }
791 
792   // If being started for credential provider logon purpose, only show the
793   // signin page.
794   if (command_line.HasSwitch(credential_provider::kGcpwSigninSwitch)) {
795     // Use incognito profile since this is a credential provider logon.
796     Profile* profile = last_used_profile->GetPrimaryOTRProfile();
797     DCHECK(profile->IsIncognitoProfile());
798     // NOTE: All launch urls are ignored when running with --gcpw-signin since
799     // this mode only loads Google's sign in page.
800 
801     // If GCPW signin dialog fails, returning false here will allow Chrome to
802     // exit gracefully during the launch.
803     if (!StartGCPWSignin(command_line, profile))
804       return false;
805 
806     LaunchModeRecorder().SetLaunchMode(LaunchMode::kCredentialProviderSignIn);
807     return true;
808   }
809 #endif  // defined(OS_WIN)
810 
811   return LaunchBrowserForLastProfiles(command_line, cur_dir, process_startup,
812                                       last_used_profile, last_opened_profiles);
813 }
814 
LaunchBrowserForLastProfiles(const base::CommandLine & command_line,const base::FilePath & cur_dir,bool process_startup,Profile * last_used_profile,const Profiles & last_opened_profiles)815 bool StartupBrowserCreator::LaunchBrowserForLastProfiles(
816     const base::CommandLine& command_line,
817     const base::FilePath& cur_dir,
818     bool process_startup,
819     Profile* last_used_profile,
820     const Profiles& last_opened_profiles) {
821 #if !defined(OS_CHROMEOS)
822   const std::vector<GURL> urls_to_launch =
823       StartupBrowserCreator::GetURLsFromCommandLine(command_line, cur_dir,
824                                                     last_used_profile);
825   if (ProfilePicker::ShouldShowAtLaunch(command_line, urls_to_launch)) {
826     ProfilePicker::Show(
827         process_startup
828             ? ProfilePicker::EntryPoint::kOnStartup
829             : ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
830     return true;
831   }
832 #endif  // !defined(OS_CHROMEOS)
833 
834   chrome::startup::IsProcessStartup is_process_startup =
835       process_startup ? chrome::startup::IS_PROCESS_STARTUP
836                       : chrome::startup::IS_NOT_PROCESS_STARTUP;
837   chrome::startup::IsFirstRun is_first_run =
838       first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
839                                     : chrome::startup::IS_NOT_FIRST_RUN;
840 
841   // On Windows, when chrome is launched by notification activation where the
842   // kNotificationLaunchId switch is used, always use |last_used_profile| which
843   // contains the profile id extracted from the notification launch id.
844   bool was_windows_notification_launch = false;
845 #if defined(OS_WIN)
846   was_windows_notification_launch =
847       command_line.HasSwitch(switches::kNotificationLaunchId);
848 #endif  // defined(OS_WIN)
849 
850   // |last_opened_profiles| will be empty in the following circumstances:
851   // - This is the first launch. |last_used_profile| is the initial profile.
852   // - The user exited the browser by closing all windows for all profiles.
853   //   |last_used_profile| is the profile which owned the last open window.
854   // - Only incognito windows were open when the browser exited.
855   //   |last_used_profile| is the last used incognito profile. Restoring it will
856   //   create a browser window for the corresponding original profile.
857   // - All of the last opened profiles fail to initialize.
858   if (last_opened_profiles.empty() || was_windows_notification_launch) {
859     if (CanOpenProfileOnStartup(last_used_profile)) {
860       Profile* profile_to_open = last_used_profile->IsGuestSession()
861                                      ? last_used_profile->GetPrimaryOTRProfile()
862                                      : last_used_profile;
863       return LaunchBrowser(command_line, profile_to_open, cur_dir,
864                            is_process_startup, is_first_run,
865                            std::make_unique<LaunchModeRecorder>());
866     }
867 
868     // Show UserManager if |last_used_profile| can't be auto opened.
869     ShowUserManagerOnStartup();
870     return true;
871   }
872   return ProcessLastOpenedProfiles(command_line, cur_dir, is_process_startup,
873                                    is_first_run, last_used_profile,
874                                    last_opened_profiles);
875 }
876 
ProcessLastOpenedProfiles(const base::CommandLine & command_line,const base::FilePath & cur_dir,chrome::startup::IsProcessStartup is_process_startup,chrome::startup::IsFirstRun is_first_run,Profile * last_used_profile,const Profiles & last_opened_profiles)877 bool StartupBrowserCreator::ProcessLastOpenedProfiles(
878     const base::CommandLine& command_line,
879     const base::FilePath& cur_dir,
880     chrome::startup::IsProcessStartup is_process_startup,
881     chrome::startup::IsFirstRun is_first_run,
882     Profile* last_used_profile,
883     const Profiles& last_opened_profiles) {
884   base::CommandLine command_line_without_urls(command_line.GetProgram());
885   for (auto& switch_pair : command_line.GetSwitches()) {
886     command_line_without_urls.AppendSwitchNative(switch_pair.first,
887                                                  switch_pair.second);
888   }
889 
890   // Launch the profiles in the order they became active.
891   for (Profile* profile : last_opened_profiles) {
892     DCHECK(!profile->IsGuestSession() && !profile->IsEphemeralGuestProfile());
893 
894 #if !defined(OS_CHROMEOS)
895     // Skip any locked profile.
896     if (!CanOpenProfileOnStartup(profile))
897       continue;
898 
899     // Guest profiles should not be reopened on startup. This can happen if
900     // the last used profile was a Guest, but other profiles were also open
901     // when Chrome was closed. In this case, pick a different open profile
902     // to be the active one, since the Guest profile is never added to the
903     // list of open profiles.
904     if (last_used_profile->IsGuestSession() ||
905         last_used_profile->IsEphemeralGuestProfile()) {
906       last_used_profile = profile;
907     }
908 #endif
909 
910     // Don't launch additional profiles which would only open a new tab
911     // page. When restarting after an update, all profiles will reopen last
912     // open pages.
913     SessionStartupPref startup_pref =
914         GetSessionStartupPref(command_line, profile);
915     if (profile != last_used_profile &&
916         startup_pref.type == SessionStartupPref::DEFAULT &&
917         !HasPendingUncleanExit(profile)) {
918       continue;
919     }
920     // Only record a launch mode histogram for |last_used_profile|. Pass a
921     // null launch_mode_recorder for other profiles.
922     if (!LaunchBrowser((profile == last_used_profile)
923                            ? command_line
924                            : command_line_without_urls,
925                        profile, cur_dir, is_process_startup, is_first_run,
926                        profile == last_used_profile
927                            ? std::make_unique<LaunchModeRecorder>()
928                            : nullptr)) {
929       return false;
930     }
931     // We've launched at least one browser.
932     is_process_startup = chrome::startup::IS_NOT_PROCESS_STARTUP;
933   }
934 
935 // Set the |last_used_profile| to activate if a browser is launched for at
936 // least one profile. Otherwise, show UserManager.
937 // Note that this must be done after all profiles have
938 // been launched so the observer knows about all profiles to wait before
939 // activation this one.
940 #if !defined(OS_CHROMEOS)
941   if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP)
942     ShowUserManagerOnStartup();
943   else
944 #endif
945     profile_launch_observer.Get().set_profile_to_activate(last_used_profile);
946   return true;
947 }
948 
949 // static
ProcessLoadApps(const base::CommandLine & command_line,const base::FilePath & cur_dir,Profile * profile)950 bool StartupBrowserCreator::ProcessLoadApps(
951     const base::CommandLine& command_line,
952     const base::FilePath& cur_dir,
953     Profile* profile) {
954   base::CommandLine::StringType path_list =
955       command_line.GetSwitchValueNative(extensions::switches::kLoadApps);
956 
957   base::StringTokenizerT<base::CommandLine::StringType,
958                          base::CommandLine::StringType::const_iterator>
959       tokenizer(path_list, FILE_PATH_LITERAL(","));
960 
961   if (!tokenizer.GetNext())
962     return false;
963 
964   base::FilePath app_absolute_dir =
965       base::MakeAbsoluteFilePath(base::FilePath(tokenizer.token()));
966   if (!apps::AppLoadService::Get(profile)->LoadAndLaunch(
967           app_absolute_dir, command_line, cur_dir)) {
968     return false;
969   }
970 
971   while (tokenizer.GetNext()) {
972     app_absolute_dir =
973         base::MakeAbsoluteFilePath(base::FilePath(tokenizer.token()));
974 
975     if (!apps::AppLoadService::Get(profile)->Load(app_absolute_dir)) {
976       return false;
977     }
978   }
979 
980   return true;
981 }
982 
983 // static
ProcessCommandLineOnProfileCreated(const base::CommandLine & command_line,const base::FilePath & cur_dir,Profile * profile,Profile::CreateStatus status)984 void StartupBrowserCreator::ProcessCommandLineOnProfileCreated(
985     const base::CommandLine& command_line,
986     const base::FilePath& cur_dir,
987     Profile* profile,
988     Profile::CreateStatus status) {
989   if (status != Profile::CREATE_STATUS_INITIALIZED)
990     return;
991   StartupBrowserCreator startup_browser_creator;
992   startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir, false,
993                                              profile, Profiles());
994 }
995 
996 // static
ProcessCommandLineAlreadyRunning(const base::CommandLine & command_line,const base::FilePath & cur_dir,const base::FilePath & profile_path)997 void StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
998     const base::CommandLine& command_line,
999     const base::FilePath& cur_dir,
1000     const base::FilePath& profile_path) {
1001   ProfileManager* profile_manager = g_browser_process->profile_manager();
1002   Profile* profile = profile_manager->GetProfileByPath(profile_path);
1003 
1004   // The profile isn't loaded yet and so needs to be loaded asynchronously.
1005   if (!profile) {
1006     profile_manager->CreateProfileAsync(
1007         profile_path,
1008         base::BindRepeating(&ProcessCommandLineOnProfileCreated, command_line,
1009                             cur_dir),
1010         base::string16(), std::string());
1011     return;
1012   }
1013   StartupBrowserCreator startup_browser_creator;
1014   Profiles last_opened_profiles;
1015 #if !defined(OS_CHROMEOS)
1016   // On ChromeOS multiple profiles doesn't apply.
1017   // If no browser windows are open, i.e. the browser is being kept alive in
1018   // background mode or for other processing, restore |last_opened_profiles|.
1019   if (chrome::GetTotalBrowserCount() == 0)
1020     last_opened_profiles = profile_manager->GetLastOpenedProfiles();
1021 #endif  // defined(OS_CHROMEOS)
1022   startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir,
1023                                              /*process_startup=*/false, profile,
1024                                              last_opened_profiles);
1025 }
1026 
1027 // static
OpenStartupPages(Browser * browser,bool process_startup)1028 void StartupBrowserCreator::OpenStartupPages(Browser* browser,
1029                                              bool process_startup) {
1030   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
1031   chrome::startup::IsFirstRun is_first_run =
1032       first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
1033                                     : chrome::startup::IS_NOT_FIRST_RUN;
1034   StartupBrowserCreatorImpl startup_browser_creator_impl(
1035       base::FilePath(), command_line, is_first_run);
1036   SessionStartupPref session_startup_pref =
1037       StartupBrowserCreator::GetSessionStartupPref(command_line,
1038                                                    browser->profile());
1039   startup_browser_creator_impl.OpenURLsInBrowser(browser, process_startup,
1040                                                  session_startup_pref.urls);
1041 }
1042 
1043 // static
ActivatedProfile()1044 bool StartupBrowserCreator::ActivatedProfile() {
1045   return profile_launch_observer.Get().activated_profile();
1046 }
1047 
HasPendingUncleanExit(Profile * profile)1048 bool HasPendingUncleanExit(Profile* profile) {
1049   return profile->GetLastSessionExitType() == Profile::EXIT_CRASHED &&
1050          !profile_launch_observer.Get().HasBeenLaunched(profile);
1051 }
1052 
GetStartupProfilePath(const base::FilePath & user_data_dir,const base::CommandLine & command_line)1053 base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir,
1054                                      const base::CommandLine& command_line) {
1055 // If the browser is launched due to activation on Windows native notification,
1056 // the profile id encoded in the notification launch id should be chosen over
1057 // all others.
1058 #if defined(OS_WIN)
1059   std::string profile_id =
1060       NotificationLaunchId::GetNotificationLaunchProfileId(command_line);
1061   if (!profile_id.empty()) {
1062     return user_data_dir.Append(base::FilePath(base::UTF8ToUTF16(profile_id)));
1063   }
1064 #endif  // defined(OS_WIN)
1065 
1066   // If opening in Guest mode is requested, load the default profile so that
1067   // last opened profile would not trigger a user management dialog.
1068   if (profiles::IsGuestModeRequested(command_line,
1069                                      g_browser_process->local_state(),
1070                                      /* show_warning= */ false)) {
1071     return profiles::GetDefaultProfileDir(user_data_dir);
1072   }
1073 
1074   if (command_line.HasSwitch(switches::kProfileDirectory)) {
1075     return user_data_dir.Append(
1076         command_line.GetSwitchValuePath(switches::kProfileDirectory));
1077   }
1078 
1079   return g_browser_process->profile_manager()->GetLastUsedProfileDir(
1080       user_data_dir);
1081 }
1082 
1083 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
GetStartupProfile(const base::FilePath & user_data_dir,const base::CommandLine & command_line)1084 Profile* GetStartupProfile(const base::FilePath& user_data_dir,
1085                            const base::CommandLine& command_line) {
1086   ProfileManager* profile_manager = g_browser_process->profile_manager();
1087 
1088   base::FilePath profile_path =
1089       GetStartupProfilePath(user_data_dir, command_line);
1090   Profile* profile = profile_manager->GetProfile(profile_path);
1091 
1092   // If there is no entry in profile attributes storage, the profile is deleted,
1093   // and we should show the user manager. Also, when using
1094   // --new-profile-management, if the profile is locked we should show the user
1095   // manager as well. When neither of these is true, we can safely start up with
1096   // |profile|.
1097   auto* storage = &profile_manager->GetProfileAttributesStorage();
1098   ProfileAttributesEntry* entry;
1099   bool has_entry = storage->GetProfileAttributesWithPath(profile_path, &entry);
1100   if (has_entry && (!entry->IsSigninRequired() || !profile)) {
1101     return profile;
1102   }
1103 
1104   // We want to show the user manager. To indicate this, return the guest
1105   // profile. However, we can only do this if the system profile (where the user
1106   // manager lives) also exists (or is creatable).
1107   return profile_manager->GetProfile(ProfileManager::GetSystemProfilePath())
1108              ? profile_manager->GetProfile(
1109                    ProfileManager::GetGuestProfilePath())
1110              : nullptr;
1111 }
1112 
GetFallbackStartupProfile()1113 Profile* GetFallbackStartupProfile() {
1114   ProfileManager* profile_manager = g_browser_process->profile_manager();
1115   // The only known reason for profiles to fail initialization is being unable
1116   // to create the profile directory, and this has already happened in
1117   // GetStartupProfilePath() before calling this function. In this case,
1118   // creation of new profiles is expected to fail. So only existing profiles are
1119   // attempted for fallback.
1120 
1121   // If the last used profile could not be initialized, see if any of other last
1122   // opened profiles can be initialized successfully.
1123   auto* storage = &profile_manager->GetProfileAttributesStorage();
1124   for (Profile* profile : ProfileManager::GetLastOpenedProfiles()) {
1125     // Return any profile that is not locked.
1126     ProfileAttributesEntry* entry;
1127     bool has_entry =
1128         storage->GetProfileAttributesWithPath(profile->GetPath(), &entry);
1129     if (!has_entry || !entry->IsSigninRequired())
1130       return profile;
1131   }
1132 
1133   // Couldn't initialize any last opened profiles. Try to show the user manager,
1134   // which requires successful initialization of the guest and system profiles.
1135   Profile* guest_profile =
1136       profile_manager->GetProfile(ProfileManager::GetGuestProfilePath());
1137   Profile* system_profile =
1138       profile_manager->GetProfile(ProfileManager::GetSystemProfilePath());
1139   if (guest_profile && system_profile)
1140     return guest_profile;
1141 
1142   // Couldn't show the user manager either. Try to open any profile that is not
1143   // locked.
1144   for (ProfileAttributesEntry* entry : storage->GetAllProfilesAttributes()) {
1145     if (!entry->IsSigninRequired()) {
1146       Profile* profile = profile_manager->GetProfile(entry->GetPath());
1147       if (profile)
1148         return profile;
1149     }
1150   }
1151 
1152   return nullptr;
1153 }
1154 #endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
1155