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