Home | History | Annotate | Download | only in renderer
      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