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