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