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