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 <algorithm>   // For max().
8#include <set>
9
10#include "apps/app_load_service.h"
11#include "apps/switches.h"
12#include "ash/shell.h"
13#include "base/bind.h"
14#include "base/bind_helpers.h"
15#include "base/command_line.h"
16#include "base/compiler_specific.h"
17#include "base/environment.h"
18#include "base/file_util.h"
19#include "base/files/file_path.h"
20#include "base/lazy_instance.h"
21#include "base/logging.h"
22#include "base/memory/scoped_ptr.h"
23#include "base/metrics/histogram.h"
24#include "base/metrics/statistics_recorder.h"
25#include "base/path_service.h"
26#include "base/prefs/pref_service.h"
27#include "base/strings/string_number_conversions.h"
28#include "base/strings/string_split.h"
29#include "base/strings/utf_string_conversions.h"
30#include "base/threading/thread_restrictions.h"
31#include "chrome/browser/app_mode/app_mode_utils.h"
32#include "chrome/browser/auto_launch_trial.h"
33#include "chrome/browser/automation/automation_provider.h"
34#include "chrome/browser/automation/automation_provider_list.h"
35#include "chrome/browser/automation/testing_automation_provider.h"
36#include "chrome/browser/browser_process.h"
37#include "chrome/browser/chrome_notification_types.h"
38#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
39#include "chrome/browser/extensions/startup_helper.h"
40#include "chrome/browser/extensions/unpacked_installer.h"
41#include "chrome/browser/first_run/first_run.h"
42#include "chrome/browser/google/google_util.h"
43#include "chrome/browser/notifications/desktop_notification_service.h"
44#include "chrome/browser/prefs/incognito_mode_prefs.h"
45#include "chrome/browser/prefs/session_startup_pref.h"
46#include "chrome/browser/profiles/profile.h"
47#include "chrome/browser/profiles/profile_manager.h"
48#include "chrome/browser/profiles/profiles_state.h"
49#include "chrome/browser/search_engines/util.h"
50#include "chrome/browser/ui/browser.h"
51#include "chrome/browser/ui/browser_dialogs.h"
52#include "chrome/browser/ui/browser_finder.h"
53#include "chrome/browser/ui/browser_window.h"
54#include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
55#include "chrome/common/chrome_constants.h"
56#include "chrome/common/chrome_paths.h"
57#include "chrome/common/chrome_result_codes.h"
58#include "chrome/common/chrome_switches.h"
59#include "chrome/common/chrome_version_info.h"
60#include "chrome/common/net/url_fixer_upper.h"
61#include "chrome/common/pref_names.h"
62#include "chrome/common/url_constants.h"
63#include "chrome/installer/util/browser_distribution.h"
64#include "content/public/browser/browser_thread.h"
65#include "content/public/browser/child_process_security_policy.h"
66#include "content/public/browser/navigation_controller.h"
67#include "grit/locale_settings.h"
68#include "net/base/net_util.h"
69#include "ui/base/l10n/l10n_util.h"
70#include "ui/base/resource/resource_bundle.h"
71
72#if defined(OS_CHROMEOS)
73#include "chrome/browser/chromeos/app_mode/app_launch_utils.h"
74#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
75#include "chrome/browser/chromeos/login/user_manager.h"
76#include "chrome/browser/chromeos/profiles/profile_helper.h"
77#include "chromeos/chromeos_switches.h"
78#endif
79
80#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
81#include "ui/events/x/touch_factory_x11.h"
82#endif
83
84#if defined(OS_WIN)
85#include "chrome/browser/automation/chrome_frame_automation_provider_win.h"
86#include "chrome/browser/ui/startup/startup_browser_creator_win.h"
87#endif
88
89#if defined(ENABLE_FULL_PRINTING)
90#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
91#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
92#include "chrome/browser/printing/print_dialog_cloud.h"
93#endif
94
95using content::BrowserThread;
96using content::ChildProcessSecurityPolicy;
97
98namespace {
99
100// Keeps track on which profiles have been launched.
101class ProfileLaunchObserver : public content::NotificationObserver {
102 public:
103  ProfileLaunchObserver()
104      : profile_to_activate_(NULL),
105        activated_profile_(false) {
106    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
107                   content::NotificationService::AllSources());
108    registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
109                   content::NotificationService::AllSources());
110  }
111  virtual ~ProfileLaunchObserver() {}
112
113  virtual void Observe(int type,
114                       const content::NotificationSource& source,
115                       const content::NotificationDetails& details) OVERRIDE {
116    switch (type) {
117      case chrome::NOTIFICATION_PROFILE_DESTROYED: {
118        Profile* profile = content::Source<Profile>(source).ptr();
119        launched_profiles_.erase(profile);
120        opened_profiles_.erase(profile);
121        if (profile == profile_to_activate_)
122          profile_to_activate_ = NULL;
123        // If this profile was the last launched one without an opened window,
124        // then we may be ready to activate |profile_to_activate_|.
125        MaybeActivateProfile();
126        break;
127      }
128      case chrome::NOTIFICATION_BROWSER_WINDOW_READY: {
129        Browser* browser = content::Source<Browser>(source).ptr();
130        DCHECK(browser);
131        opened_profiles_.insert(browser->profile());
132        MaybeActivateProfile();
133        break;
134      }
135      default:
136        NOTREACHED();
137    }
138  }
139
140  bool HasBeenLaunched(const Profile* profile) const {
141    return launched_profiles_.find(profile) != launched_profiles_.end();
142  }
143
144  void AddLaunched(Profile* profile) {
145    launched_profiles_.insert(profile);
146    // Since the startup code only executes for browsers launched in
147    // desktop mode, i.e., HOST_DESKTOP_TYPE_NATIVE. Ash should never get here.
148    if (chrome::FindBrowserWithProfile(profile,
149                                       chrome::HOST_DESKTOP_TYPE_NATIVE)) {
150      // A browser may get opened before we get initialized (e.g., in tests),
151      // so we never see the NOTIFICATION_BROWSER_WINDOW_READY for it.
152      opened_profiles_.insert(profile);
153    }
154  }
155
156  void Clear() {
157    launched_profiles_.clear();
158    opened_profiles_.clear();
159  }
160
161  bool activated_profile() { return activated_profile_; }
162
163  void set_profile_to_activate(Profile* profile) {
164    profile_to_activate_ = profile;
165    MaybeActivateProfile();
166  }
167
168 private:
169  void MaybeActivateProfile() {
170    if (!profile_to_activate_)
171      return;
172    // Check that browsers have been opened for all the launched profiles.
173    // Note that browsers opened for profiles that were not added as launched
174    // profiles are simply ignored.
175    std::set<const Profile*>::const_iterator i = launched_profiles_.begin();
176    for (; i != launched_profiles_.end(); ++i) {
177      if (opened_profiles_.find(*i) == opened_profiles_.end())
178        return;
179    }
180    // Asynchronous post to give a chance to the last window to completely
181    // open and activate before trying to activate |profile_to_activate_|.
182    BrowserThread::PostTask(
183        BrowserThread::UI, FROM_HERE,
184        base::Bind(&ProfileLaunchObserver::ActivateProfile,
185                   base::Unretained(this)));
186    // Avoid posting more than once before ActivateProfile gets called.
187    registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
188                      content::NotificationService::AllSources());
189    registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
190                      content::NotificationService::AllSources());
191  }
192
193  void ActivateProfile() {
194    // We need to test again, in case the profile got deleted in the mean time.
195    if (profile_to_activate_) {
196      Browser* browser = chrome::FindBrowserWithProfile(
197          profile_to_activate_, chrome::HOST_DESKTOP_TYPE_NATIVE);
198      // |profile| may never get launched, e.g., if it only had
199      // incognito Windows and one of them was used to exit Chrome.
200      // So it won't have a browser in that case.
201      if (browser)
202        browser->window()->Activate();
203      // No need try to activate this profile again.
204      profile_to_activate_ = NULL;
205    }
206    // Assign true here, even if no browser was actually activated, so that
207    // the test can stop waiting, and fail gracefully when needed.
208    activated_profile_ = true;
209  }
210
211  // These are the profiles that get launched by
212  // StartupBrowserCreator::LaunchBrowser.
213  std::set<const Profile*> launched_profiles_;
214  // These are the profiles for which at least one browser window has been
215  // opened. This is needed to know when it is safe to activate
216  // |profile_to_activate_|, otherwise, new browser windows being opened will
217  // be activated on top of it.
218  std::set<const Profile*> opened_profiles_;
219  content::NotificationRegistrar registrar_;
220  // This is NULL until the profile to activate has been chosen. This value,
221  // should only be set once all profiles have been launched, otherwise,
222  // activation may not happen after the launch of newer profiles.
223  Profile* profile_to_activate_;
224  // Set once we attempted to activate a profile. We only get one shot at this.
225  bool activated_profile_;
226
227  DISALLOW_COPY_AND_ASSIGN(ProfileLaunchObserver);
228};
229
230base::LazyInstance<ProfileLaunchObserver> profile_launch_observer =
231    LAZY_INSTANCE_INITIALIZER;
232
233// Dumps the current set of the browser process's histograms to |output_file|.
234// The file is overwritten if it exists. This function should only be called in
235// the blocking pool.
236void DumpBrowserHistograms(const base::FilePath& output_file) {
237  base::ThreadRestrictions::AssertIOAllowed();
238
239  std::string output_string(base::StatisticsRecorder::ToJSON(std::string()));
240  file_util::WriteFile(output_file, output_string.data(),
241                       static_cast<int>(output_string.size()));
242}
243
244}  // namespace
245
246StartupBrowserCreator::StartupBrowserCreator()
247    : is_default_browser_dialog_suppressed_(false),
248      show_main_browser_window_(true) {
249}
250
251StartupBrowserCreator::~StartupBrowserCreator() {}
252
253// static
254bool StartupBrowserCreator::was_restarted_read_ = false;
255
256// static
257bool StartupBrowserCreator::in_synchronous_profile_launch_ = false;
258
259void StartupBrowserCreator::AddFirstRunTab(const GURL& url) {
260  first_run_tabs_.push_back(url);
261}
262
263// static
264bool StartupBrowserCreator::InSynchronousProfileLaunch() {
265  return in_synchronous_profile_launch_;
266}
267
268bool StartupBrowserCreator::LaunchBrowser(
269    const CommandLine& command_line,
270    Profile* profile,
271    const base::FilePath& cur_dir,
272    chrome::startup::IsProcessStartup process_startup,
273    chrome::startup::IsFirstRun is_first_run,
274    int* return_code) {
275
276  in_synchronous_profile_launch_ =
277      process_startup == chrome::startup::IS_PROCESS_STARTUP;
278  DCHECK(profile);
279
280  // Continue with the incognito profile from here on if Incognito mode
281  // is forced.
282  if (IncognitoModePrefs::ShouldLaunchIncognito(command_line,
283                                                profile->GetPrefs())) {
284    profile = profile->GetOffTheRecordProfile();
285  } else if (command_line.HasSwitch(switches::kIncognito)) {
286    LOG(WARNING) << "Incognito mode disabled by policy, launching a normal "
287                 << "browser session.";
288  }
289
290  // Note: This check should have been done in ProcessCmdLineImpl()
291  // before calling this function. However chromeos/login/login_utils.cc
292  // calls this function directly (see comments there) so it has to be checked
293  // again.
294  const bool silent_launch = command_line.HasSwitch(switches::kSilentLaunch);
295
296  if (!silent_launch) {
297    StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
298    const std::vector<GURL> urls_to_launch =
299        GetURLsFromCommandLine(command_line, cur_dir, profile);
300    chrome::HostDesktopType host_desktop_type =
301        chrome::HOST_DESKTOP_TYPE_NATIVE;
302
303#if defined(OS_WIN) && defined(USE_ASH)
304    // We want to maintain only one type of instance for now, either ASH
305    // or desktop.
306    // TODO(shrikant): Remove this code once we decide on running both desktop
307    // and ASH instances side by side.
308    if (ash::Shell::HasInstance())
309      host_desktop_type = chrome::HOST_DESKTOP_TYPE_ASH;
310#endif
311
312    const bool launched = lwp.Launch(profile, urls_to_launch,
313                               in_synchronous_profile_launch_,
314                               host_desktop_type);
315    in_synchronous_profile_launch_ = false;
316    if (!launched) {
317      LOG(ERROR) << "launch error";
318      if (return_code)
319        *return_code = chrome::RESULT_CODE_INVALID_CMDLINE_URL;
320      return false;
321    }
322  } else {
323    in_synchronous_profile_launch_ = false;
324  }
325
326  profile_launch_observer.Get().AddLaunched(profile);
327
328#if defined(OS_CHROMEOS)
329  g_browser_process->platform_part()->profile_helper()->ProfileStartup(
330      profile,
331      process_startup);
332#endif
333  return true;
334}
335
336// static
337bool StartupBrowserCreator::WasRestarted() {
338  // Stores the value of the preference kWasRestarted had when it was read.
339  static bool was_restarted = false;
340
341  if (!was_restarted_read_) {
342    PrefService* pref_service = g_browser_process->local_state();
343    was_restarted = pref_service->GetBoolean(prefs::kWasRestarted);
344    pref_service->SetBoolean(prefs::kWasRestarted, false);
345    was_restarted_read_ = true;
346  }
347  return was_restarted;
348}
349
350// static
351SessionStartupPref StartupBrowserCreator::GetSessionStartupPref(
352    const CommandLine& command_line,
353    Profile* profile) {
354  DCHECK(profile);
355  PrefService* prefs = profile->GetPrefs();
356  SessionStartupPref pref = SessionStartupPref::GetStartupPref(prefs);
357
358  // IsChromeFirstRun() looks for a sentinel file to determine whether the user
359  // is starting Chrome for the first time. On Chrome OS, the sentinel is stored
360  // in a location shared by all users and the check is meaningless. Query the
361  // UserManager instead to determine whether the user is new.
362#if defined(OS_CHROMEOS)
363  const bool is_first_run = chromeos::UserManager::Get()->IsCurrentUserNew();
364#else
365  const bool is_first_run = first_run::IsChromeFirstRun();
366#endif
367
368  // The pref has an OS-dependent default value. For the first run only, this
369  // default is overridden with SessionStartupPref::DEFAULT so that first run
370  // behavior (sync promo, welcome page) is consistently invoked.
371  // This applies only if the pref is still at its default and has not been
372  // set by the user, managed prefs or policy.
373  if (is_first_run && SessionStartupPref::TypeIsDefault(prefs))
374    pref.type = SessionStartupPref::DEFAULT;
375
376  // The switches::kRestoreLastSession command line switch is used to restore
377  // sessions after a browser self restart (e.g. after a Chrome upgrade).
378  // However, new profiles can be created from a browser process that has this
379  // switch so do not set the session pref to SessionStartupPref::LAST for
380  // those as there is nothing to restore.
381  if ((command_line.HasSwitch(switches::kRestoreLastSession) ||
382       StartupBrowserCreator::WasRestarted()) &&
383      !profile->IsNewProfile()) {
384    pref.type = SessionStartupPref::LAST;
385  }
386  if (pref.type == SessionStartupPref::LAST &&
387      IncognitoModePrefs::ShouldLaunchIncognito(command_line, prefs)) {
388    // We don't store session information when incognito. If the user has
389    // chosen to restore last session and launched incognito, fallback to
390    // default launch behavior.
391    pref.type = SessionStartupPref::DEFAULT;
392  }
393
394  return pref;
395}
396
397// static
398void StartupBrowserCreator::ClearLaunchedProfilesForTesting() {
399  profile_launch_observer.Get().Clear();
400}
401
402// static
403std::vector<GURL> StartupBrowserCreator::GetURLsFromCommandLine(
404    const CommandLine& command_line,
405    const base::FilePath& cur_dir,
406    Profile* profile) {
407  std::vector<GURL> urls;
408
409  const CommandLine::StringVector& params = command_line.GetArgs();
410  for (size_t i = 0; i < params.size(); ++i) {
411    base::FilePath param = base::FilePath(params[i]);
412    // Handle Vista way of searching - "? <search-term>"
413    if ((param.value().size() > 2) && (param.value()[0] == '?') &&
414        (param.value()[1] == ' ')) {
415      GURL url(GetDefaultSearchURLForSearchTerms(
416          profile, param.LossyDisplayName().substr(2)));
417      if (url.is_valid()) {
418        urls.push_back(url);
419        continue;
420      }
421    }
422
423    // Otherwise, fall through to treating it as a URL.
424
425    // This will create a file URL or a regular URL.
426    // This call can (in rare circumstances) block the UI thread.
427    // Allow it until this bug is fixed.
428    //  http://code.google.com/p/chromium/issues/detail?id=60641
429    GURL url;
430    {
431      base::ThreadRestrictions::ScopedAllowIO allow_io;
432      url = URLFixerUpper::FixupRelativeFile(cur_dir, param);
433    }
434    // Exclude dangerous schemes.
435    if (url.is_valid()) {
436      ChildProcessSecurityPolicy* policy =
437          ChildProcessSecurityPolicy::GetInstance();
438      if (policy->IsWebSafeScheme(url.scheme()) ||
439          url.SchemeIs(chrome::kFileScheme) ||
440#if defined(OS_CHROMEOS)
441          // In ChromeOS, allow a settings page to be specified on the
442          // command line. See ExistingUserController::OnLoginSuccess.
443          (url.spec().find(chrome::kChromeUISettingsURL) == 0) ||
444#endif
445          (url.spec().compare(content::kAboutBlankURL) == 0)) {
446        urls.push_back(url);
447      }
448    }
449  }
450#if defined(OS_WIN)
451  if (urls.empty()) {
452    // If we are in Windows 8 metro mode and were launched as a result of the
453    // search charm or via a url navigation in metro, then fetch the
454    // corresponding url.
455    GURL url(chrome::GetURLToOpen(profile));
456    if (url.is_valid())
457      urls.push_back(url);
458  }
459#endif  // OS_WIN
460  return urls;
461}
462
463// static
464bool StartupBrowserCreator::ProcessCmdLineImpl(
465    const CommandLine& command_line,
466    const base::FilePath& cur_dir,
467    bool process_startup,
468    Profile* last_used_profile,
469    const Profiles& last_opened_profiles,
470    int* return_code,
471    StartupBrowserCreator* browser_creator) {
472  DCHECK(last_used_profile);
473  if (process_startup) {
474    if (command_line.HasSwitch(switches::kDisablePromptOnRepost))
475      content::NavigationController::DisablePromptOnRepost();
476  }
477
478  bool silent_launch = false;
479
480#if defined(ENABLE_AUTOMATION)
481  // Look for the testing channel ID ONLY during process startup
482  if (process_startup &&
483      command_line.HasSwitch(switches::kTestingChannelID)) {
484    std::string testing_channel_id = command_line.GetSwitchValueASCII(
485        switches::kTestingChannelID);
486    // TODO(sanjeevr) Check if we need to make this a singleton for
487    // compatibility with the old testing code
488    // If there are any extra parameters, we expect each one to generate a
489    // new tab; if there are none then we get one homepage tab.
490    int expected_tab_count = 1;
491    if (command_line.HasSwitch(switches::kNoStartupWindow) &&
492        !command_line.HasSwitch(switches::kAutoLaunchAtStartup)) {
493      expected_tab_count = 0;
494#if defined(OS_CHROMEOS)
495    // kLoginManager will cause Chrome to start up with the ChromeOS login
496    // screen instead of a browser window, so it won't load any tabs.
497    } else if (command_line.HasSwitch(chromeos::switches::kLoginManager)) {
498      expected_tab_count = 0;
499#endif
500    } else if (command_line.HasSwitch(switches::kRestoreLastSession)) {
501      std::string restore_session_value(
502          command_line.GetSwitchValueASCII(switches::kRestoreLastSession));
503      base::StringToInt(restore_session_value, &expected_tab_count);
504    } else {
505      std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
506          command_line, cur_dir, last_used_profile);
507      expected_tab_count =
508          std::max(1, static_cast<int>(urls_to_open.size()));
509    }
510    if (!CreateAutomationProvider<TestingAutomationProvider>(
511        testing_channel_id,
512        last_used_profile,
513        static_cast<size_t>(expected_tab_count)))
514      return false;
515  }
516
517  if (command_line.HasSwitch(switches::kSilentLaunch)) {
518    std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
519        command_line, cur_dir, last_used_profile);
520    size_t expected_tabs =
521        std::max(static_cast<int>(urls_to_open.size()), 0);
522    if (expected_tabs == 0)
523      silent_launch = true;
524  }
525
526  if (command_line.HasSwitch(switches::kAutomationClientChannelID)) {
527    std::string automation_channel_id = command_line.GetSwitchValueASCII(
528        switches::kAutomationClientChannelID);
529    // If there are any extra parameters, we expect each one to generate a
530    // new tab; if there are none then we have no tabs
531    std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
532        command_line, cur_dir, last_used_profile);
533    size_t expected_tabs =
534        std::max(static_cast<int>(urls_to_open.size()), 0);
535    if (expected_tabs == 0)
536      silent_launch = true;
537
538    if (command_line.HasSwitch(switches::kChromeFrame)) {
539#if defined(OS_WIN)
540      if (!CreateAutomationProvider<ChromeFrameAutomationProvider>(
541          automation_channel_id, last_used_profile, expected_tabs))
542        return false;
543#endif
544    } else {
545      if (!CreateAutomationProvider<AutomationProvider>(
546          automation_channel_id, last_used_profile, expected_tabs))
547        return false;
548    }
549  }
550#endif  // defined(ENABLE_AUTOMATION)
551
552#if defined(ENABLE_FULL_PRINTING)
553  // If we are just displaying a print dialog we shouldn't open browser
554  // windows.
555  if (command_line.HasSwitch(switches::kCloudPrintFile) &&
556      print_dialog_cloud::CreatePrintDialogFromCommandLine(last_used_profile,
557                                                           command_line)) {
558    silent_launch = true;
559  }
560
561  // If we are checking the proxy enabled policy, don't open any windows.
562  if (command_line.HasSwitch(switches::kCheckCloudPrintConnectorPolicy)) {
563    silent_launch = true;
564    if (CloudPrintProxyServiceFactory::GetForProfile(last_used_profile)->
565        EnforceCloudPrintConnectorPolicyAndQuit())
566      // Success, nothing more needs to be done, so return false to stop
567      // launching and quit.
568      return false;
569  }
570#endif  // defined(ENABLE_FULL_PRINTING)
571
572  if (command_line.HasSwitch(switches::kExplicitlyAllowedPorts)) {
573    std::string allowed_ports =
574        command_line.GetSwitchValueASCII(switches::kExplicitlyAllowedPorts);
575    net::SetExplicitlyAllowedPorts(allowed_ports);
576  }
577
578  if (command_line.HasSwitch(switches::kInstallFromWebstore)) {
579    extensions::StartupHelper helper;
580    helper.InstallFromWebstore(command_line, last_used_profile);
581    // Nothing more needs to be done, so return false to stop launching and
582    // quit.
583    return false;
584  }
585
586  if (command_line.HasSwitch(switches::kValidateCrx)) {
587    if (!process_startup) {
588      LOG(ERROR) << "chrome is already running; you must close all running "
589                 << "instances before running with the --"
590                 << switches::kValidateCrx << " flag";
591      return false;
592    }
593    extensions::StartupHelper helper;
594    std::string message;
595    std::string error;
596    if (helper.ValidateCrx(command_line, &error))
597      message = std::string("ValidateCrx Success");
598    else
599      message = std::string("ValidateCrx Failure: ") + error;
600    printf("%s\n", message.c_str());
601    return false;
602  }
603
604  if (command_line.HasSwitch(switches::kLimitedInstallFromWebstore)) {
605    extensions::StartupHelper helper;
606    helper.LimitedInstallFromWebstore(command_line, last_used_profile,
607                                      base::Bind(&base::DoNothing));
608  }
609
610#if defined(OS_CHROMEOS)
611  // The browser will be launched after the user logs in.
612  if (command_line.HasSwitch(chromeos::switches::kLoginManager) ||
613      command_line.HasSwitch(chromeos::switches::kLoginPassword)) {
614    silent_launch = true;
615  }
616
617  if (chrome::IsRunningInAppMode() &&
618      command_line.HasSwitch(switches::kAppId)) {
619    chromeos::LaunchAppOrDie(
620        last_used_profile,
621        command_line.GetSwitchValueASCII(switches::kAppId));
622
623    // Skip browser launch since app mode launches its app window.
624    silent_launch = true;
625  }
626#endif
627
628#if defined(TOOLKIT_VIEWS) && defined(USE_X11)
629  ui::TouchFactory::SetTouchDeviceListFromCommandLine();
630#endif
631
632  if (!process_startup &&
633      command_line.HasSwitch(switches::kDumpBrowserHistograms)) {
634    // Only handle --dump-browser-histograms from a rendezvous. In this case, do
635    // not open a new browser window even if no output file was given.
636    base::FilePath output_file(
637        command_line.GetSwitchValuePath(switches::kDumpBrowserHistograms));
638    if (!output_file.empty()) {
639      BrowserThread::PostBlockingPoolTask(
640          FROM_HERE,
641          base::Bind(&DumpBrowserHistograms, output_file));
642    }
643    silent_launch = true;
644  }
645
646  // If we don't want to launch a new browser window or tab (in the case
647  // of an automation request), we are done here.
648  if (silent_launch)
649    return true;
650
651  // Check for --load-and-launch-app.
652  if (command_line.HasSwitch(apps::kLoadAndLaunchApp) &&
653      !IncognitoModePrefs::ShouldLaunchIncognito(
654          command_line, last_used_profile->GetPrefs())) {
655    CommandLine::StringType path = command_line.GetSwitchValueNative(
656        apps::kLoadAndLaunchApp);
657
658    if (!apps::AppLoadService::Get(last_used_profile)->LoadAndLaunch(
659            base::FilePath(path), command_line, cur_dir)) {
660      return false;
661    }
662
663    // Return early here since we don't want to open a browser window.
664    // The exception is when there are no browser windows, since we don't want
665    // chrome to shut down.
666    // TODO(jackhou): Do this properly once keep-alive is handled by the
667    // background page of apps. Tracked at http://crbug.com/175381
668    if (chrome::GetTotalBrowserCountForProfile(last_used_profile) != 0)
669      return true;
670  }
671
672  chrome::startup::IsProcessStartup is_process_startup = process_startup ?
673      chrome::startup::IS_PROCESS_STARTUP :
674      chrome::startup::IS_NOT_PROCESS_STARTUP;
675  chrome::startup::IsFirstRun is_first_run = first_run::IsChromeFirstRun() ?
676      chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
677  // |last_opened_profiles| will be empty in the following circumstances:
678  // - This is the first launch. |last_used_profile| is the initial profile.
679  // - The user exited the browser by closing all windows for all
680  // profiles. |last_used_profile| is the profile which owned the last open
681  // window.
682  // - Only incognito windows were open when the browser exited.
683  // |last_used_profile| is the last used incognito profile. Restoring it will
684  // create a browser window for the corresponding original profile.
685  if (last_opened_profiles.empty()) {
686    // If the last used profile was a guest, show the user manager instead.
687    if (profiles::IsNewProfileManagementEnabled() &&
688        last_used_profile->IsGuestSession()) {
689      chrome::ShowUserManager(base::FilePath());
690      return true;
691    }
692    if (!browser_creator->LaunchBrowser(command_line, last_used_profile,
693                                        cur_dir, is_process_startup,
694                                        is_first_run, return_code)) {
695      return false;
696    }
697  } else {
698    // Launch the last used profile with the full command line, and the other
699    // opened profiles without the URLs to launch.
700    CommandLine command_line_without_urls(command_line.GetProgram());
701    const CommandLine::SwitchMap& switches = command_line.GetSwitches();
702    for (CommandLine::SwitchMap::const_iterator switch_it = switches.begin();
703         switch_it != switches.end(); ++switch_it) {
704      command_line_without_urls.AppendSwitchNative(switch_it->first,
705                                                   switch_it->second);
706    }
707    // Launch the profiles in the order they became active.
708    for (Profiles::const_iterator it = last_opened_profiles.begin();
709         it != last_opened_profiles.end(); ++it) {
710      // Don't launch additional profiles which would only open a new tab
711      // page. When restarting after an update, all profiles will reopen last
712      // open pages.
713      SessionStartupPref startup_pref =
714          GetSessionStartupPref(command_line, *it);
715      if (*it != last_used_profile &&
716          startup_pref.type == SessionStartupPref::DEFAULT &&
717          !HasPendingUncleanExit(*it))
718        continue;
719
720      // Don't re-open a browser window for the guest profile.
721      if (profiles::IsNewProfileManagementEnabled() &&
722          (*it)->IsGuestSession())
723        continue;
724
725      if (!browser_creator->LaunchBrowser((*it == last_used_profile) ?
726          command_line : command_line_without_urls, *it, cur_dir,
727          is_process_startup, is_first_run, return_code))
728        return false;
729      // We've launched at least one browser.
730      is_process_startup = chrome::startup::IS_NOT_PROCESS_STARTUP;
731    }
732    // This must be done after all profiles have been launched so the observer
733    // knows about all profiles to wait for before activating this one.
734
735    // If the last used profile was the guest one, we didn't open it so
736    // we don't need to activate it either.
737    if (!profiles::IsNewProfileManagementEnabled() &&
738        !last_used_profile->IsGuestSession())
739      profile_launch_observer.Get().set_profile_to_activate(last_used_profile);
740  }
741  return true;
742}
743
744template <class AutomationProviderClass>
745bool StartupBrowserCreator::CreateAutomationProvider(
746    const std::string& channel_id,
747    Profile* profile,
748    size_t expected_tabs) {
749#if defined(ENABLE_AUTOMATION)
750  scoped_refptr<AutomationProviderClass> automation =
751      new AutomationProviderClass(profile);
752  if (!automation->InitializeChannel(channel_id))
753    return false;
754  automation->SetExpectedTabCount(expected_tabs);
755
756  AutomationProviderList* list = g_browser_process->GetAutomationProviderList();
757  DCHECK(list);
758  list->AddProvider(automation.get());
759#endif  // defined(ENABLE_AUTOMATION)
760
761  return true;
762}
763
764// static
765void StartupBrowserCreator::ProcessCommandLineOnProfileCreated(
766    const CommandLine& command_line,
767    const base::FilePath& cur_dir,
768    Profile* profile,
769    Profile::CreateStatus status) {
770  if (status == Profile::CREATE_STATUS_INITIALIZED)
771    ProcessCmdLineImpl(command_line, cur_dir, false, profile, Profiles(), NULL,
772                       NULL);
773}
774
775// static
776void StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
777    const CommandLine& command_line,
778    const base::FilePath& cur_dir,
779    const base::FilePath& profile_path) {
780  ProfileManager* profile_manager = g_browser_process->profile_manager();
781  Profile* profile = profile_manager->GetProfileByPath(profile_path);
782
783  // The profile isn't loaded yet and so needs to be loaded asynchronously.
784  if (!profile) {
785    profile_manager->CreateProfileAsync(profile_path,
786        base::Bind(&StartupBrowserCreator::ProcessCommandLineOnProfileCreated,
787                   command_line, cur_dir), base::string16(), base::string16(),
788                   std::string());
789    return;
790  }
791
792  ProcessCmdLineImpl(command_line, cur_dir, false, profile, Profiles(), NULL,
793                     NULL);
794}
795
796// static
797bool StartupBrowserCreator::ActivatedProfile() {
798  return profile_launch_observer.Get().activated_profile();
799}
800
801bool HasPendingUncleanExit(Profile* profile) {
802  return profile->GetLastSessionExitType() == Profile::EXIT_CRASHED &&
803      !profile_launch_observer.Get().HasBeenLaunched(profile);
804}
805