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 "content/public/app/content_main_runner.h" 6 7 #include <stdlib.h> 8 9 #include "base/allocator/allocator_extension.h" 10 #include "base/at_exit.h" 11 #include "base/command_line.h" 12 #include "base/debug/debugger.h" 13 #include "base/debug/trace_event.h" 14 #include "base/files/file_path.h" 15 #include "base/i18n/icu_util.h" 16 #include "base/lazy_instance.h" 17 #include "base/logging.h" 18 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_vector.h" 20 #include "base/metrics/stats_table.h" 21 #include "base/path_service.h" 22 #include "base/process/launch.h" 23 #include "base/process/memory.h" 24 #include "base/process/process_handle.h" 25 #include "base/profiler/alternate_timer.h" 26 #include "base/strings/string_number_conversions.h" 27 #include "base/strings/string_util.h" 28 #include "base/strings/stringprintf.h" 29 #include "content/browser/browser_main.h" 30 #include "content/common/set_process_title.h" 31 #include "content/common/url_schemes.h" 32 #include "content/gpu/in_process_gpu_thread.h" 33 #include "content/public/app/content_main.h" 34 #include "content/public/app/content_main_delegate.h" 35 #include "content/public/app/startup_helper_win.h" 36 #include "content/public/browser/content_browser_client.h" 37 #include "content/public/common/content_client.h" 38 #include "content/public/common/content_constants.h" 39 #include "content/public/common/content_paths.h" 40 #include "content/public/common/content_switches.h" 41 #include "content/public/common/main_function_params.h" 42 #include "content/public/common/sandbox_init.h" 43 #include "content/renderer/in_process_renderer_thread.h" 44 #include "content/utility/in_process_utility_thread.h" 45 #include "crypto/nss_util.h" 46 #include "ipc/ipc_descriptors.h" 47 #include "ipc/ipc_switches.h" 48 #include "media/base/media.h" 49 #include "sandbox/win/src/sandbox_types.h" 50 #include "ui/base/ui_base_paths.h" 51 #include "ui/base/ui_base_switches.h" 52 53 #if defined(OS_ANDROID) 54 #include "content/public/common/content_descriptors.h" 55 #endif 56 57 #if defined(USE_TCMALLOC) 58 #include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h" 59 #if defined(TYPE_PROFILING) 60 #include "base/allocator/type_profiler.h" 61 #include "base/allocator/type_profiler_tcmalloc.h" 62 #endif 63 #endif 64 65 #if !defined(OS_IOS) 66 #include "content/app/mojo/mojo_init.h" 67 #include "content/browser/gpu/gpu_process_host.h" 68 #include "content/browser/renderer_host/render_process_host_impl.h" 69 #include "content/browser/utility_process_host_impl.h" 70 #include "content/public/plugin/content_plugin_client.h" 71 #include "content/public/renderer/content_renderer_client.h" 72 #include "content/public/utility/content_utility_client.h" 73 #endif 74 75 #if defined(OS_WIN) 76 #include <malloc.h> 77 #include <cstring> 78 79 #include "base/strings/string_number_conversions.h" 80 #include "ui/base/win/atl_module.h" 81 #include "ui/base/win/dpi_setup.h" 82 #include "ui/gfx/win/dpi.h" 83 #elif defined(OS_MACOSX) 84 #include "base/mac/scoped_nsautorelease_pool.h" 85 #if !defined(OS_IOS) 86 #include "base/power_monitor/power_monitor_device_source.h" 87 #include "content/browser/mach_broker_mac.h" 88 #include "content/common/sandbox_init_mac.h" 89 #endif // !OS_IOS 90 #endif // OS_WIN 91 92 #if defined(OS_POSIX) 93 #include <signal.h> 94 95 #include "base/posix/global_descriptors.h" 96 #include "content/public/common/content_descriptors.h" 97 98 #if !defined(OS_MACOSX) 99 #include "content/public/common/zygote_fork_delegate_linux.h" 100 #endif 101 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 102 #include "content/zygote/zygote_main.h" 103 #endif 104 105 #endif // OS_POSIX 106 107 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) 108 extern "C" { 109 int tc_set_new_mode(int mode); 110 } 111 #endif 112 113 namespace content { 114 extern int GpuMain(const content::MainFunctionParams&); 115 #if defined(ENABLE_PLUGINS) 116 #if !defined(OS_LINUX) 117 extern int PluginMain(const content::MainFunctionParams&); 118 #endif 119 extern int PpapiPluginMain(const MainFunctionParams&); 120 extern int PpapiBrokerMain(const MainFunctionParams&); 121 #endif 122 extern int RendererMain(const content::MainFunctionParams&); 123 extern int UtilityMain(const MainFunctionParams&); 124 } // namespace content 125 126 namespace content { 127 128 #if !defined(CHROME_MULTIPLE_DLL_CHILD) 129 base::LazyInstance<ContentBrowserClient> 130 g_empty_content_browser_client = LAZY_INSTANCE_INITIALIZER; 131 #endif // !CHROME_MULTIPLE_DLL_CHILD 132 133 #if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER) 134 base::LazyInstance<ContentPluginClient> 135 g_empty_content_plugin_client = LAZY_INSTANCE_INITIALIZER; 136 base::LazyInstance<ContentRendererClient> 137 g_empty_content_renderer_client = LAZY_INSTANCE_INITIALIZER; 138 base::LazyInstance<ContentUtilityClient> 139 g_empty_content_utility_client = LAZY_INSTANCE_INITIALIZER; 140 #endif // !OS_IOS && !CHROME_MULTIPLE_DLL_BROWSER 141 142 #if defined(OS_WIN) 143 144 #endif // defined(OS_WIN) 145 146 #if defined(OS_POSIX) && !defined(OS_IOS) 147 148 // Setup signal-handling state: resanitize most signals, ignore SIGPIPE. 149 void SetupSignalHandlers() { 150 // Sanitise our signal handling state. Signals that were ignored by our 151 // parent will also be ignored by us. We also inherit our parent's sigmask. 152 sigset_t empty_signal_set; 153 CHECK(0 == sigemptyset(&empty_signal_set)); 154 CHECK(0 == sigprocmask(SIG_SETMASK, &empty_signal_set, NULL)); 155 156 struct sigaction sigact; 157 memset(&sigact, 0, sizeof(sigact)); 158 sigact.sa_handler = SIG_DFL; 159 static const int signals_to_reset[] = 160 {SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, 161 SIGALRM, SIGTERM, SIGCHLD, SIGBUS, SIGTRAP}; // SIGPIPE is set below. 162 for (unsigned i = 0; i < arraysize(signals_to_reset); i++) { 163 CHECK(0 == sigaction(signals_to_reset[i], &sigact, NULL)); 164 } 165 166 // Always ignore SIGPIPE. We check the return value of write(). 167 CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR); 168 } 169 170 #endif // OS_POSIX && !OS_IOS 171 172 void CommonSubprocessInit(const std::string& process_type) { 173 #if defined(OS_WIN) 174 // HACK: Let Windows know that we have started. This is needed to suppress 175 // the IDC_APPSTARTING cursor from being displayed for a prolonged period 176 // while a subprocess is starting. 177 PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0); 178 MSG msg; 179 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); 180 #endif 181 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 182 // Various things break when you're using a locale where the decimal 183 // separator isn't a period. See e.g. bugs 22782 and 39964. For 184 // all processes except the browser process (where we call system 185 // APIs that may rely on the correct locale for formatting numbers 186 // when presenting them to the user), reset the locale for numeric 187 // formatting. 188 // Note that this is not correct for plugin processes -- they can 189 // surface UI -- but it's likely they get this wrong too so why not. 190 setlocale(LC_NUMERIC, "C"); 191 #endif 192 } 193 194 // Only needed on Windows for creating stats tables. 195 #if defined(OS_WIN) 196 static base::ProcessId GetBrowserPid(const base::CommandLine& command_line) { 197 base::ProcessId browser_pid = base::GetCurrentProcId(); 198 if (command_line.HasSwitch(switches::kProcessChannelID)) { 199 std::string channel_name = 200 command_line.GetSwitchValueASCII(switches::kProcessChannelID); 201 202 int browser_pid_int; 203 base::StringToInt(channel_name, &browser_pid_int); 204 browser_pid = static_cast<base::ProcessId>(browser_pid_int); 205 DCHECK_NE(browser_pid_int, 0); 206 } 207 return browser_pid; 208 } 209 #endif 210 211 static void InitializeStatsTable(const base::CommandLine& command_line) { 212 // Initialize the Stats Counters table. With this initialized, 213 // the StatsViewer can be utilized to read counters outside of 214 // Chrome. These lines can be commented out to effectively turn 215 // counters 'off'. The table is created and exists for the life 216 // of the process. It is not cleaned up. 217 if (command_line.HasSwitch(switches::kEnableStatsTable)) { 218 // NOTIMPLEMENTED: we probably need to shut this down correctly to avoid 219 // leaking shared memory regions on posix platforms. 220 #if defined(OS_POSIX) 221 // Stats table is in the global file descriptors table on Posix. 222 base::GlobalDescriptors* global_descriptors = 223 base::GlobalDescriptors::GetInstance(); 224 base::FileDescriptor table_ident; 225 if (global_descriptors->MaybeGet(kStatsTableSharedMemFd) != -1) { 226 // Open the shared memory file descriptor passed by the browser process. 227 table_ident = base::FileDescriptor( 228 global_descriptors->Get(kStatsTableSharedMemFd), false); 229 } 230 #elif defined(OS_WIN) 231 // Stats table is in a named segment on Windows. Use the PID to make this 232 // unique on the system. 233 std::string table_ident = 234 base::StringPrintf("%s-%u", kStatsFilename, 235 static_cast<unsigned int>(GetBrowserPid(command_line))); 236 #endif 237 base::StatsTable* stats_table = 238 new base::StatsTable(table_ident, kStatsMaxThreads, kStatsMaxCounters); 239 base::StatsTable::set_current(stats_table); 240 } 241 } 242 243 class ContentClientInitializer { 244 public: 245 static void Set(const std::string& process_type, 246 ContentMainDelegate* delegate) { 247 ContentClient* content_client = GetContentClient(); 248 #if !defined(CHROME_MULTIPLE_DLL_CHILD) 249 if (process_type.empty()) { 250 if (delegate) 251 content_client->browser_ = delegate->CreateContentBrowserClient(); 252 if (!content_client->browser_) 253 content_client->browser_ = &g_empty_content_browser_client.Get(); 254 } 255 #endif // !CHROME_MULTIPLE_DLL_CHILD 256 257 #if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER) 258 if (process_type == switches::kPluginProcess || 259 process_type == switches::kPpapiPluginProcess) { 260 if (delegate) 261 content_client->plugin_ = delegate->CreateContentPluginClient(); 262 if (!content_client->plugin_) 263 content_client->plugin_ = &g_empty_content_plugin_client.Get(); 264 // Single process not supported in split dll mode. 265 } else if (process_type == switches::kRendererProcess || 266 base::CommandLine::ForCurrentProcess()->HasSwitch( 267 switches::kSingleProcess)) { 268 if (delegate) 269 content_client->renderer_ = delegate->CreateContentRendererClient(); 270 if (!content_client->renderer_) 271 content_client->renderer_ = &g_empty_content_renderer_client.Get(); 272 } 273 274 if (process_type == switches::kUtilityProcess || 275 base::CommandLine::ForCurrentProcess()->HasSwitch( 276 switches::kSingleProcess)) { 277 if (delegate) 278 content_client->utility_ = delegate->CreateContentUtilityClient(); 279 // TODO(scottmg): http://crbug.com/237249 Should be in _child. 280 if (!content_client->utility_) 281 content_client->utility_ = &g_empty_content_utility_client.Get(); 282 } 283 #endif // !OS_IOS && !CHROME_MULTIPLE_DLL_BROWSER 284 } 285 }; 286 287 // We dispatch to a process-type-specific FooMain() based on a command-line 288 // flag. This struct is used to build a table of (flag, main function) pairs. 289 struct MainFunction { 290 const char* name; 291 int (*function)(const MainFunctionParams&); 292 }; 293 294 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 295 // On platforms that use the zygote, we have a special subset of 296 // subprocesses that are launched via the zygote. This function 297 // fills in some process-launching bits around ZygoteMain(). 298 // Returns the exit code of the subprocess. 299 int RunZygote(const MainFunctionParams& main_function_params, 300 ContentMainDelegate* delegate) { 301 static const MainFunction kMainFunctions[] = { 302 { switches::kRendererProcess, RendererMain }, 303 #if defined(ENABLE_PLUGINS) 304 { switches::kPpapiPluginProcess, PpapiPluginMain }, 305 #endif 306 { switches::kUtilityProcess, UtilityMain }, 307 }; 308 309 ScopedVector<ZygoteForkDelegate> zygote_fork_delegates; 310 if (delegate) { 311 delegate->ZygoteStarting(&zygote_fork_delegates); 312 // Each Renderer we spawn will re-attempt initialization of the media 313 // libraries, at which point failure will be detected and handled, so 314 // we do not need to cope with initialization failures here. 315 base::FilePath media_path; 316 if (PathService::Get(DIR_MEDIA_LIBS, &media_path)) 317 media::InitializeMediaLibrary(media_path); 318 } 319 320 // This function call can return multiple times, once per fork(). 321 if (!ZygoteMain(main_function_params, zygote_fork_delegates.Pass())) 322 return 1; 323 324 if (delegate) delegate->ZygoteForked(); 325 326 // Zygote::HandleForkRequest may have reallocated the command 327 // line so update it here with the new version. 328 const base::CommandLine& command_line = 329 *base::CommandLine::ForCurrentProcess(); 330 std::string process_type = 331 command_line.GetSwitchValueASCII(switches::kProcessType); 332 ContentClientInitializer::Set(process_type, delegate); 333 334 // The StatsTable must be initialized in each process; we already 335 // initialized for the browser process, now we need to initialize 336 // within the new processes as well. 337 InitializeStatsTable(command_line); 338 339 MainFunctionParams main_params(command_line); 340 main_params.zygote_child = true; 341 342 for (size_t i = 0; i < arraysize(kMainFunctions); ++i) { 343 if (process_type == kMainFunctions[i].name) 344 return kMainFunctions[i].function(main_params); 345 } 346 347 if (delegate) 348 return delegate->RunProcess(process_type, main_params); 349 350 NOTREACHED() << "Unknown zygote process type: " << process_type; 351 return 1; 352 } 353 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 354 355 #if !defined(OS_IOS) 356 static void RegisterMainThreadFactories() { 357 #if !defined(CHROME_MULTIPLE_DLL_BROWSER) && !defined(CHROME_MULTIPLE_DLL_CHILD) 358 UtilityProcessHostImpl::RegisterUtilityMainThreadFactory( 359 CreateInProcessUtilityThread); 360 RenderProcessHostImpl::RegisterRendererMainThreadFactory( 361 CreateInProcessRendererThread); 362 GpuProcessHost::RegisterGpuMainThreadFactory( 363 CreateInProcessGpuThread); 364 #else 365 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); 366 if (command_line.HasSwitch(switches::kSingleProcess)) { 367 LOG(FATAL) << 368 "--single-process is not supported in chrome multiple dll browser."; 369 } 370 if (command_line.HasSwitch(switches::kInProcessGPU)) { 371 LOG(FATAL) << 372 "--in-process-gpu is not supported in chrome multiple dll browser."; 373 } 374 #endif // !CHROME_MULTIPLE_DLL_BROWSER && !CHROME_MULTIPLE_DLL_CHILD 375 } 376 377 // Run the FooMain() for a given process type. 378 // If |process_type| is empty, runs BrowserMain(). 379 // Returns the exit code for this process. 380 int RunNamedProcessTypeMain( 381 const std::string& process_type, 382 const MainFunctionParams& main_function_params, 383 ContentMainDelegate* delegate) { 384 static const MainFunction kMainFunctions[] = { 385 #if !defined(CHROME_MULTIPLE_DLL_CHILD) 386 { "", BrowserMain }, 387 #endif 388 #if !defined(CHROME_MULTIPLE_DLL_BROWSER) 389 #if defined(ENABLE_PLUGINS) 390 #if !defined(OS_LINUX) 391 { switches::kPluginProcess, PluginMain }, 392 #endif 393 { switches::kPpapiPluginProcess, PpapiPluginMain }, 394 { switches::kPpapiBrokerProcess, PpapiBrokerMain }, 395 #endif // ENABLE_PLUGINS 396 { switches::kUtilityProcess, UtilityMain }, 397 { switches::kRendererProcess, RendererMain }, 398 { switches::kGpuProcess, GpuMain }, 399 #endif // !CHROME_MULTIPLE_DLL_BROWSER 400 }; 401 402 RegisterMainThreadFactories(); 403 404 for (size_t i = 0; i < arraysize(kMainFunctions); ++i) { 405 if (process_type == kMainFunctions[i].name) { 406 if (delegate) { 407 int exit_code = delegate->RunProcess(process_type, 408 main_function_params); 409 #if defined(OS_ANDROID) 410 // In Android's browser process, the negative exit code doesn't mean the 411 // default behavior should be used as the UI message loop is managed by 412 // the Java and the browser process's default behavior is always 413 // overridden. 414 if (process_type.empty()) 415 return exit_code; 416 #endif 417 if (exit_code >= 0) 418 return exit_code; 419 } 420 return kMainFunctions[i].function(main_function_params); 421 } 422 } 423 424 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 425 // Zygote startup is special -- see RunZygote comments above 426 // for why we don't use ZygoteMain directly. 427 if (process_type == switches::kZygoteProcess) 428 return RunZygote(main_function_params, delegate); 429 #endif 430 431 // If it's a process we don't know about, the embedder should know. 432 if (delegate) 433 return delegate->RunProcess(process_type, main_function_params); 434 435 NOTREACHED() << "Unknown process type: " << process_type; 436 return 1; 437 } 438 #endif // !OS_IOS 439 440 class ContentMainRunnerImpl : public ContentMainRunner { 441 public: 442 ContentMainRunnerImpl() 443 : is_initialized_(false), 444 is_shutdown_(false), 445 completed_basic_startup_(false), 446 delegate_(NULL), 447 ui_task_(NULL) { 448 #if defined(OS_WIN) 449 memset(&sandbox_info_, 0, sizeof(sandbox_info_)); 450 #endif 451 } 452 453 virtual ~ContentMainRunnerImpl() { 454 if (is_initialized_ && !is_shutdown_) 455 Shutdown(); 456 } 457 458 #if defined(USE_TCMALLOC) 459 static bool GetAllocatorWasteSizeThunk(size_t* size) { 460 size_t heap_size, allocated_bytes, unmapped_bytes; 461 MallocExtension* ext = MallocExtension::instance(); 462 if (ext->GetNumericProperty("generic.heap_size", &heap_size) && 463 ext->GetNumericProperty("generic.current_allocated_bytes", 464 &allocated_bytes) && 465 ext->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", 466 &unmapped_bytes)) { 467 *size = heap_size - allocated_bytes - unmapped_bytes; 468 return true; 469 } 470 DCHECK(false); 471 return false; 472 } 473 474 static void GetStatsThunk(char* buffer, int buffer_length) { 475 MallocExtension::instance()->GetStats(buffer, buffer_length); 476 } 477 478 static void ReleaseFreeMemoryThunk() { 479 MallocExtension::instance()->ReleaseFreeMemory(); 480 } 481 #endif 482 483 virtual int Initialize(const ContentMainParams& params) OVERRIDE { 484 ui_task_ = params.ui_task; 485 486 #if defined(OS_WIN) 487 RegisterInvalidParamHandler(); 488 ui::win::CreateATLModuleIfNeeded(); 489 490 sandbox_info_ = *params.sandbox_info; 491 #else // !OS_WIN 492 493 #if defined(OS_ANDROID) 494 // See note at the initialization of ExitManager, below; basically, 495 // only Android builds have the ctor/dtor handlers set up to use 496 // TRACE_EVENT right away. 497 TRACE_EVENT0("startup", "ContentMainRunnerImpl::Initialize"); 498 #endif // OS_ANDROID 499 500 // NOTE(willchan): One might ask why these TCMalloc-related calls are done 501 // here rather than in process_util_linux.cc with the definition of 502 // EnableTerminationOnOutOfMemory(). That's because base shouldn't have a 503 // dependency on TCMalloc. Really, we ought to have our allocator shim code 504 // implement this EnableTerminationOnOutOfMemory() function. Whateverz. 505 // This works for now. 506 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) 507 508 #if defined(TYPE_PROFILING) 509 base::type_profiler::InterceptFunctions::SetFunctions( 510 base::type_profiler::NewInterceptForTCMalloc, 511 base::type_profiler::DeleteInterceptForTCMalloc); 512 #endif 513 514 // For tcmalloc, we need to tell it to behave like new. 515 tc_set_new_mode(1); 516 517 // On windows, we've already set these thunks up in _heap_init() 518 base::allocator::SetGetAllocatorWasteSizeFunction( 519 GetAllocatorWasteSizeThunk); 520 base::allocator::SetGetStatsFunction(GetStatsThunk); 521 base::allocator::SetReleaseFreeMemoryFunction(ReleaseFreeMemoryThunk); 522 523 // Provide optional hook for monitoring allocation quantities on a 524 // per-thread basis. Only set the hook if the environment indicates this 525 // needs to be enabled. 526 const char* profiling = getenv(tracked_objects::kAlternateProfilerTime); 527 if (profiling && 528 (atoi(profiling) == tracked_objects::TIME_SOURCE_TYPE_TCMALLOC)) { 529 tracked_objects::SetAlternateTimeSource( 530 MallocExtension::GetBytesAllocatedOnCurrentThread, 531 tracked_objects::TIME_SOURCE_TYPE_TCMALLOC); 532 } 533 #endif // !OS_MACOSX && USE_TCMALLOC 534 535 // On Android, 536 // - setlocale() is not supported. 537 // - We do not override the signal handlers so that we can get 538 // stack trace when crashing. 539 // - The ipc_fd is passed through the Java service. 540 // Thus, these are all disabled. 541 #if !defined(OS_ANDROID) && !defined(OS_IOS) 542 // Set C library locale to make sure CommandLine can parse argument values 543 // in correct encoding. 544 setlocale(LC_ALL, ""); 545 546 SetupSignalHandlers(); 547 548 base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance(); 549 g_fds->Set(kPrimaryIPCChannel, 550 kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor); 551 #endif // !OS_ANDROID && !OS_IOS 552 553 #if defined(OS_LINUX) || defined(OS_OPENBSD) 554 g_fds->Set(kCrashDumpSignal, 555 kCrashDumpSignal + base::GlobalDescriptors::kBaseDescriptor); 556 #endif 557 558 #endif // !OS_WIN 559 560 is_initialized_ = true; 561 delegate_ = params.delegate; 562 563 // The exit manager is in charge of calling the dtors of singleton objects. 564 // On Android, AtExitManager is set up when library is loaded. 565 // On iOS, it's set up in main(), which can't call directly through to here. 566 // A consequence of this is that you can't use the ctor/dtor-based 567 // TRACE_EVENT methods on Linux or iOS builds till after we set this up. 568 #if !defined(OS_ANDROID) && !defined(OS_IOS) 569 if (!ui_task_) { 570 // When running browser tests, don't create a second AtExitManager as that 571 // interfers with shutdown when objects created before ContentMain is 572 // called are destructed when it returns. 573 exit_manager_.reset(new base::AtExitManager); 574 } 575 #endif // !OS_ANDROID && !OS_IOS 576 577 #if defined(OS_MACOSX) 578 // We need this pool for all the objects created before we get to the 579 // event loop, but we don't want to leave them hanging around until the 580 // app quits. Each "main" needs to flush this pool right before it goes into 581 // its main event loop to get rid of the cruft. 582 autorelease_pool_.reset(new base::mac::ScopedNSAutoreleasePool()); 583 #endif 584 585 // On Android, the command line is initialized when library is loaded and 586 // we have already started our TRACE_EVENT0. 587 #if !defined(OS_ANDROID) 588 // argc/argv are ignored on Windows and Android; see command_line.h for 589 // details. 590 int argc = 0; 591 const char** argv = NULL; 592 593 #if !defined(OS_WIN) 594 argc = params.argc; 595 argv = params.argv; 596 #endif 597 598 base::CommandLine::Init(argc, argv); 599 600 if (!delegate_ || delegate_->ShouldEnableTerminationOnHeapCorruption()) 601 base::EnableTerminationOnHeapCorruption(); 602 base::EnableTerminationOnOutOfMemory(); 603 604 #if !defined(OS_IOS) 605 SetProcessTitleFromCommandLine(argv); 606 #endif 607 #endif // !OS_ANDROID 608 609 int exit_code = 0; 610 if (delegate_ && delegate_->BasicStartupComplete(&exit_code)) 611 return exit_code; 612 613 completed_basic_startup_ = true; 614 615 const base::CommandLine& command_line = 616 *base::CommandLine::ForCurrentProcess(); 617 std::string process_type = 618 command_line.GetSwitchValueASCII(switches::kProcessType); 619 620 #if !defined(OS_IOS) 621 // Initialize mojo here so that services can be registered. 622 InitializeMojo(); 623 #endif 624 625 #if defined(OS_WIN) 626 bool init_device_scale_factor = true; 627 if (command_line.HasSwitch(switches::kDeviceScaleFactor)) { 628 std::string scale_factor_string = command_line.GetSwitchValueASCII( 629 switches::kDeviceScaleFactor); 630 double scale_factor = 0; 631 if (base::StringToDouble(scale_factor_string, &scale_factor)) { 632 init_device_scale_factor = false; 633 gfx::InitDeviceScaleFactor(scale_factor); 634 } 635 } 636 if (init_device_scale_factor) 637 ui::win::InitDeviceScaleFactor(); 638 #endif 639 640 if (!GetContentClient()) 641 SetContentClient(&empty_content_client_); 642 ContentClientInitializer::Set(process_type, delegate_); 643 644 #if defined(OS_WIN) 645 // Route stdio to parent console (if any) or create one. 646 if (command_line.HasSwitch(switches::kEnableLogging)) 647 base::RouteStdioToConsole(); 648 #endif 649 650 // Enable startup tracing asap to avoid early TRACE_EVENT calls being 651 // ignored. 652 if (command_line.HasSwitch(switches::kTraceStartup)) { 653 base::debug::CategoryFilter category_filter( 654 command_line.GetSwitchValueASCII(switches::kTraceStartup)); 655 base::debug::TraceLog::GetInstance()->SetEnabled( 656 category_filter, 657 base::debug::TraceLog::RECORDING_MODE, 658 base::debug::TraceOptions( 659 base::debug::RECORD_UNTIL_FULL)); 660 } 661 #if !defined(OS_ANDROID) 662 // Android tracing started at the beginning of the method. 663 // Other OSes have to wait till we get here in order for all the memory 664 // management setup to be completed. 665 TRACE_EVENT0("startup", "ContentMainRunnerImpl::Initialize"); 666 #endif // !OS_ANDROID 667 668 #if defined(OS_MACOSX) && !defined(OS_IOS) 669 // We need to allocate the IO Ports before the Sandbox is initialized or 670 // the first instance of PowerMonitor is created. 671 // It's important not to allocate the ports for processes which don't 672 // register with the power monitor - see crbug.com/88867. 673 if (process_type.empty() || 674 (delegate_ && 675 delegate_->ProcessRegistersWithSystemProcess(process_type))) { 676 base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); 677 } 678 679 if (!process_type.empty() && 680 (!delegate_ || delegate_->ShouldSendMachPort(process_type))) { 681 MachBroker::ChildSendTaskPortToParent(); 682 } 683 #elif defined(OS_WIN) 684 SetupCRT(command_line); 685 #endif 686 687 #if defined(OS_POSIX) 688 if (!process_type.empty()) { 689 // When you hit Ctrl-C in a terminal running the browser 690 // process, a SIGINT is delivered to the entire process group. 691 // When debugging the browser process via gdb, gdb catches the 692 // SIGINT for the browser process (and dumps you back to the gdb 693 // console) but doesn't for the child processes, killing them. 694 // The fix is to have child processes ignore SIGINT; they'll die 695 // on their own when the browser process goes away. 696 // 697 // Note that we *can't* rely on BeingDebugged to catch this case because 698 // we are the child process, which is not being debugged. 699 // TODO(evanm): move this to some shared subprocess-init function. 700 if (!base::debug::BeingDebugged()) 701 signal(SIGINT, SIG_IGN); 702 } 703 #endif 704 705 #if defined(USE_NSS) 706 crypto::EarlySetupForNSSInit(); 707 #endif 708 709 ui::RegisterPathProvider(); 710 RegisterPathProvider(); 711 RegisterContentSchemes(true); 712 713 #if defined(OS_ANDROID) 714 int icudata_fd = base::GlobalDescriptors::GetInstance()->MaybeGet( 715 kAndroidICUDataDescriptor); 716 if (icudata_fd != -1) 717 CHECK(base::i18n::InitializeICUWithFileDescriptor(icudata_fd)); 718 else 719 CHECK(base::i18n::InitializeICU()); 720 #else 721 CHECK(base::i18n::InitializeICU()); 722 #endif 723 724 InitializeStatsTable(command_line); 725 726 if (delegate_) 727 delegate_->PreSandboxStartup(); 728 729 if (!process_type.empty()) 730 CommonSubprocessInit(process_type); 731 732 #if defined(OS_WIN) 733 CHECK(InitializeSandbox(params.sandbox_info)); 734 #elif defined(OS_MACOSX) && !defined(OS_IOS) 735 if (process_type == switches::kRendererProcess || 736 process_type == switches::kPpapiPluginProcess || 737 (delegate_ && delegate_->DelaySandboxInitialization(process_type))) { 738 // On OS X the renderer sandbox needs to be initialized later in the 739 // startup sequence in RendererMainPlatformDelegate::EnableSandbox(). 740 } else { 741 CHECK(InitializeSandbox()); 742 } 743 #endif 744 745 if (delegate_) 746 delegate_->SandboxInitialized(process_type); 747 748 // Return -1 to indicate no early termination. 749 return -1; 750 } 751 752 virtual int Run() OVERRIDE { 753 DCHECK(is_initialized_); 754 DCHECK(!is_shutdown_); 755 const base::CommandLine& command_line = 756 *base::CommandLine::ForCurrentProcess(); 757 std::string process_type = 758 command_line.GetSwitchValueASCII(switches::kProcessType); 759 760 MainFunctionParams main_params(command_line); 761 main_params.ui_task = ui_task_; 762 #if defined(OS_WIN) 763 main_params.sandbox_info = &sandbox_info_; 764 #elif defined(OS_MACOSX) 765 main_params.autorelease_pool = autorelease_pool_.get(); 766 #endif 767 768 #if !defined(OS_IOS) 769 return RunNamedProcessTypeMain(process_type, main_params, delegate_); 770 #else 771 return 1; 772 #endif 773 } 774 775 virtual void Shutdown() OVERRIDE { 776 DCHECK(is_initialized_); 777 DCHECK(!is_shutdown_); 778 779 if (completed_basic_startup_ && delegate_) { 780 const base::CommandLine& command_line = 781 *base::CommandLine::ForCurrentProcess(); 782 std::string process_type = 783 command_line.GetSwitchValueASCII(switches::kProcessType); 784 785 delegate_->ProcessExiting(process_type); 786 } 787 788 #if defined(OS_WIN) 789 #ifdef _CRTDBG_MAP_ALLOC 790 _CrtDumpMemoryLeaks(); 791 #endif // _CRTDBG_MAP_ALLOC 792 #endif // OS_WIN 793 794 #if defined(OS_MACOSX) 795 autorelease_pool_.reset(NULL); 796 #endif 797 798 exit_manager_.reset(NULL); 799 800 delegate_ = NULL; 801 is_shutdown_ = true; 802 } 803 804 private: 805 // True if the runner has been initialized. 806 bool is_initialized_; 807 808 // True if the runner has been shut down. 809 bool is_shutdown_; 810 811 // True if basic startup was completed. 812 bool completed_basic_startup_; 813 814 // Used if the embedder doesn't set one. 815 ContentClient empty_content_client_; 816 817 // The delegate will outlive this object. 818 ContentMainDelegate* delegate_; 819 820 scoped_ptr<base::AtExitManager> exit_manager_; 821 #if defined(OS_WIN) 822 sandbox::SandboxInterfaceInfo sandbox_info_; 823 #elif defined(OS_MACOSX) 824 scoped_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool_; 825 #endif 826 827 base::Closure* ui_task_; 828 829 DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl); 830 }; 831 832 // static 833 ContentMainRunner* ContentMainRunner::Create() { 834 return new ContentMainRunnerImpl(); 835 } 836 837 } // namespace content 838