Home | History | Annotate | Download | only in app
      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