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 58 namespace content { 59 namespace { 60 // This function provides some ways to test crash and assertion handling 61 // behavior of the renderer. 62 static 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. 77 class 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 103 int 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