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