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