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