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