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