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 "base/base_switches.h"
6#include "base/command_line.h"
7#include "base/debug/debugger.h"
8#include "base/debug/stack_trace.h"
9#include "base/debug/trace_event.h"
10#include "base/i18n/rtl.h"
11#include "base/memory/ref_counted.h"
12#include "base/message_loop/message_loop.h"
13#include "base/metrics/field_trial.h"
14#include "base/metrics/histogram.h"
15#include "base/metrics/statistics_recorder.h"
16#include "base/metrics/stats_counters.h"
17#include "base/path_service.h"
18#include "base/pending_task.h"
19#include "base/strings/string_util.h"
20#include "base/sys_info.h"
21#include "base/threading/platform_thread.h"
22#include "base/time/time.h"
23#include "base/timer/hi_res_timer_manager.h"
24#include "content/child/child_process.h"
25#include "content/common/content_constants_internal.h"
26#include "content/public/common/content_switches.h"
27#include "content/public/common/main_function_params.h"
28#include "content/public/renderer/content_renderer_client.h"
29#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
30#include "content/renderer/render_process_impl.h"
31#include "content/renderer/render_thread_impl.h"
32#include "content/renderer/renderer_main_platform_delegate.h"
33#include "ui/base/ui_base_switches.h"
34
35#if defined(OS_ANDROID)
36#include "third_party/skia/include/core/SkGraphics.h"
37#endif  // OS_ANDROID
38
39#if defined(OS_MACOSX)
40#include <Carbon/Carbon.h>
41#include <signal.h>
42#include <unistd.h>
43
44#include "base/mac/mac_util.h"
45#include "base/mac/scoped_nsautorelease_pool.h"
46#include "base/message_loop/message_pump_mac.h"
47#include "third_party/WebKit/public/web/WebView.h"
48#endif  // OS_MACOSX
49
50#if defined(ENABLE_PLUGINS)
51#include "content/renderer/pepper/pepper_plugin_registry.h"
52#endif
53
54#if defined(ENABLE_WEBRTC)
55#include "third_party/libjingle/overrides/init_webrtc.h"
56#endif
57
58namespace content {
59namespace {
60// This function provides some ways to test crash and assertion handling
61// behavior of the renderer.
62static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
63  if (command_line.HasSwitch(switches::kWaitForDebugger))
64    base::debug::WaitForDebugger(60, true);
65
66  if (command_line.HasSwitch(switches::kRendererStartupDialog))
67    ChildProcess::WaitForDebugger("Renderer");
68
69  // This parameter causes an assertion.
70  if (command_line.HasSwitch(switches::kRendererAssertTest)) {
71    DCHECK(false);
72  }
73}
74
75// This is a simplified version of the browser Jankometer, which measures
76// the processing time of tasks on the render thread.
77class RendererMessageLoopObserver : public base::MessageLoop::TaskObserver {
78 public:
79  RendererMessageLoopObserver()
80      : process_times_(base::Histogram::FactoryGet(
81            "Chrome.ProcMsgL RenderThread",
82            1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag)) {}
83  virtual ~RendererMessageLoopObserver() {}
84
85  virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
86    begin_process_message_ = base::TimeTicks::Now();
87  }
88
89  virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
90    if (!begin_process_message_.is_null())
91      process_times_->AddTime(base::TimeTicks::Now() - begin_process_message_);
92  }
93
94 private:
95  base::TimeTicks begin_process_message_;
96  base::HistogramBase* const process_times_;
97  DISALLOW_COPY_AND_ASSIGN(RendererMessageLoopObserver);
98};
99
100}  // namespace
101
102// mainline routine for running as the Renderer process
103int RendererMain(const MainFunctionParams& parameters) {
104  TRACE_EVENT_BEGIN_ETW("RendererMain", 0, "");
105  base::debug::TraceLog::GetInstance()->SetProcessName("Renderer");
106  base::debug::TraceLog::GetInstance()->SetProcessSortIndex(
107      kTraceEventRendererProcessSortIndex);
108
109  const CommandLine& parsed_command_line = parameters.command_line;
110
111#if defined(OS_MACOSX)
112  base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool;
113#endif  // OS_MACOSX
114
115#if defined(OS_CHROMEOS)
116  // As Zygote process starts up earlier than browser process gets its own
117  // locale (at login time for Chrome OS), we have to set the ICU default
118  // locale for renderer process here.
119  // ICU locale will be used for fallback font selection etc.
120  if (parsed_command_line.HasSwitch(switches::kLang)) {
121    const std::string locale =
122        parsed_command_line.GetSwitchValueASCII(switches::kLang);
123    base::i18n::SetICUDefaultLocale(locale);
124  }
125#endif
126
127#if defined(OS_ANDROID)
128  const int kMB = 1024 * 1024;
129  size_t font_cache_limit =
130      base::SysInfo::IsLowEndDevice() ? kMB : 8 * kMB;
131  SkGraphics::SetFontCacheLimit(font_cache_limit);
132#endif
133
134  // This function allows pausing execution using the --renderer-startup-dialog
135  // flag allowing us to attach a debugger.
136  // Do not move this function down since that would mean we can't easily debug
137  // whatever occurs before it.
138  HandleRendererErrorTestParameters(parsed_command_line);
139
140  RendererMainPlatformDelegate platform(parameters);
141
142
143  base::StatsCounterTimer stats_counter_timer("Content.RendererInit");
144  base::StatsScope<base::StatsCounterTimer> startup_timer(stats_counter_timer);
145
146  RendererMessageLoopObserver task_observer;
147#if defined(OS_MACOSX)
148  // As long as scrollbars on Mac are painted with Cocoa, the message pump
149  // needs to be backed by a Foundation-level loop to process NSTimers. See
150  // http://crbug.com/306348#c24 for details.
151  scoped_ptr<base::MessagePump> pump(new base::MessagePumpNSRunLoop());
152  base::MessageLoop main_message_loop(pump.Pass());
153#else
154  // The main message loop of the renderer services doesn't have IO or UI tasks.
155  base::MessageLoop main_message_loop;
156#endif
157  main_message_loop.AddTaskObserver(&task_observer);
158
159  base::PlatformThread::SetName("CrRendererMain");
160
161  bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
162
163  // Initialize histogram statistics gathering system.
164  base::StatisticsRecorder::Initialize();
165
166  // Initialize statistical testing infrastructure.  We set the entropy provider
167  // to NULL to disallow the renderer process from creating its own one-time
168  // randomized trials; they should be created in the browser process.
169  base::FieldTrialList field_trial_list(NULL);
170  // Ensure any field trials in browser are reflected into renderer.
171  if (parsed_command_line.HasSwitch(switches::kForceFieldTrials)) {
172    // Field trials are created in an "activated" state to ensure they get
173    // reported in crash reports.
174    bool result = base::FieldTrialList::CreateTrialsFromString(
175        parsed_command_line.GetSwitchValueASCII(switches::kForceFieldTrials),
176        base::FieldTrialList::ACTIVATE_TRIALS,
177        std::set<std::string>());
178    DCHECK(result);
179  }
180
181  // PlatformInitialize uses FieldTrials, so this must happen later.
182  platform.PlatformInitialize();
183
184#if defined(ENABLE_PLUGINS)
185  // Load pepper plugins before engaging the sandbox.
186  PepperPluginRegistry::GetInstance();
187#endif
188#if defined(ENABLE_WEBRTC)
189  // Initialize WebRTC before engaging the sandbox.
190  // NOTE: On linux, this call could already have been made from
191  // zygote_main_linux.cc.  However, calling multiple times from the same thread
192  // is OK.
193  InitializeWebRtcModule();
194#endif
195
196  {
197#if defined(OS_WIN) || defined(OS_MACOSX)
198    // TODO(markus): Check if it is OK to unconditionally move this
199    // instruction down.
200    RenderProcessImpl render_process;
201    new RenderThreadImpl();
202#endif
203    bool run_loop = true;
204    if (!no_sandbox) {
205      run_loop = platform.EnableSandbox();
206    } else {
207      LOG(ERROR) << "Running without renderer sandbox";
208#ifndef NDEBUG
209      // For convenience, we print the stack traces for crashes.  When sandbox
210      // is enabled, the in-process stack dumping is enabled as part of the
211      // EnableSandbox() call.
212      base::debug::EnableInProcessStackDumping();
213#endif
214    }
215#if defined(OS_POSIX) && !defined(OS_MACOSX)
216    RenderProcessImpl render_process;
217    new RenderThreadImpl();
218#endif
219
220    base::HighResolutionTimerManager hi_res_timer_manager;
221
222    startup_timer.Stop();  // End of Startup Time Measurement.
223
224    if (run_loop) {
225#if defined(OS_MACOSX)
226      if (pool)
227        pool->Recycle();
228#endif
229      TRACE_EVENT_BEGIN_ETW("RendererMain.START_MSG_LOOP", 0, 0);
230      base::MessageLoop::current()->Run();
231      TRACE_EVENT_END_ETW("RendererMain.START_MSG_LOOP", 0, 0);
232    }
233  }
234  platform.PlatformUninitialize();
235  TRACE_EVENT_END_ETW("RendererMain", 0, "");
236  return 0;
237}
238
239}  // namespace content
240