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