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 #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