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