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