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 "content/renderer/render_thread_impl.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 #include <map>
     10 #include <vector>
     11 
     12 #include "base/allocator/allocator_extension.h"
     13 #include "base/command_line.h"
     14 #include "base/debug/trace_event.h"
     15 #include "base/lazy_instance.h"
     16 #include "base/logging.h"
     17 #include "base/memory/discardable_memory.h"
     18 #include "base/memory/shared_memory.h"
     19 #include "base/metrics/field_trial.h"
     20 #include "base/metrics/histogram.h"
     21 #include "base/metrics/stats_table.h"
     22 #include "base/path_service.h"
     23 #include "base/strings/string16.h"
     24 #include "base/strings/string_tokenizer.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "base/threading/thread_local.h"
     27 #include "base/threading/thread_restrictions.h"
     28 #include "base/values.h"
     29 #include "content/child/appcache/appcache_dispatcher.h"
     30 #include "content/child/appcache/appcache_frontend_impl.h"
     31 #include "content/child/child_histogram_message_filter.h"
     32 #include "content/child/db_message_filter.h"
     33 #include "content/child/indexed_db/indexed_db_dispatcher.h"
     34 #include "content/child/indexed_db/indexed_db_message_filter.h"
     35 #include "content/child/npapi/npobject_util.h"
     36 #include "content/child/plugin_messages.h"
     37 #include "content/child/resource_dispatcher.h"
     38 #include "content/child/runtime_features.h"
     39 #include "content/child/thread_safe_sender.h"
     40 #include "content/child/web_database_observer_impl.h"
     41 #include "content/common/child_process_messages.h"
     42 #include "content/common/content_constants_internal.h"
     43 #include "content/common/database_messages.h"
     44 #include "content/common/dom_storage/dom_storage_messages.h"
     45 #include "content/common/gpu/client/context_provider_command_buffer.h"
     46 #include "content/common/gpu/client/gpu_channel_host.h"
     47 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
     48 #include "content/common/gpu/gpu_messages.h"
     49 #include "content/common/gpu/gpu_process_launch_causes.h"
     50 #include "content/common/resource_messages.h"
     51 #include "content/common/view_messages.h"
     52 #include "content/public/common/content_constants.h"
     53 #include "content/public/common/content_paths.h"
     54 #include "content/public/common/content_switches.h"
     55 #include "content/public/common/renderer_preferences.h"
     56 #include "content/public/common/url_constants.h"
     57 #include "content/public/renderer/content_renderer_client.h"
     58 #include "content/public/renderer/render_process_observer.h"
     59 #include "content/public/renderer/render_view_visitor.h"
     60 #include "content/renderer/devtools/devtools_agent_filter.h"
     61 #include "content/renderer/dom_storage/dom_storage_dispatcher.h"
     62 #include "content/renderer/dom_storage/webstoragearea_impl.h"
     63 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
     64 #include "content/renderer/gamepad_shared_memory_reader.h"
     65 #include "content/renderer/gpu/compositor_output_surface.h"
     66 #include "content/renderer/gpu/gpu_benchmarking_extension.h"
     67 #include "content/renderer/input/input_event_filter.h"
     68 #include "content/renderer/input/input_handler_manager.h"
     69 #include "content/renderer/media/audio_input_message_filter.h"
     70 #include "content/renderer/media/audio_message_filter.h"
     71 #include "content/renderer/media/audio_renderer_mixer_manager.h"
     72 #include "content/renderer/media/media_stream_center.h"
     73 #include "content/renderer/media/media_stream_dependency_factory.h"
     74 #include "content/renderer/media/midi_message_filter.h"
     75 #include "content/renderer/media/peer_connection_tracker.h"
     76 #include "content/renderer/media/video_capture_impl_manager.h"
     77 #include "content/renderer/media/video_capture_message_filter.h"
     78 #include "content/renderer/media/webrtc_identity_service.h"
     79 #include "content/renderer/memory_benchmarking_extension.h"
     80 #include "content/renderer/p2p/socket_dispatcher.h"
     81 #include "content/renderer/render_process_impl.h"
     82 #include "content/renderer/render_view_impl.h"
     83 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
     84 #include "content/renderer/service_worker/embedded_worker_dispatcher.h"
     85 #include "content/renderer/skia_benchmarking_extension.h"
     86 #include "grit/content_resources.h"
     87 #include "ipc/ipc_channel_handle.h"
     88 #include "ipc/ipc_forwarding_message_filter.h"
     89 #include "ipc/ipc_platform_file.h"
     90 #include "media/base/audio_hardware_config.h"
     91 #include "media/base/media.h"
     92 #include "media/filters/gpu_video_accelerator_factories.h"
     93 #include "net/base/net_errors.h"
     94 #include "net/base/net_util.h"
     95 #include "third_party/skia/include/core/SkGraphics.h"
     96 #include "third_party/WebKit/public/platform/WebString.h"
     97 #include "third_party/WebKit/public/web/WebColorName.h"
     98 #include "third_party/WebKit/public/web/WebDatabase.h"
     99 #include "third_party/WebKit/public/web/WebDocument.h"
    100 #include "third_party/WebKit/public/web/WebFrame.h"
    101 #include "third_party/WebKit/public/web/WebImageCache.h"
    102 #include "third_party/WebKit/public/web/WebKit.h"
    103 #include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
    104 #include "third_party/WebKit/public/web/WebPopupMenu.h"
    105 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
    106 #include "third_party/WebKit/public/web/WebScriptController.h"
    107 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
    108 #include "third_party/WebKit/public/web/WebView.h"
    109 #include "ui/base/layout.h"
    110 #include "ui/base/ui_base_switches.h"
    111 #include "v8/include/v8.h"
    112 #include "webkit/child/worker_task_runner.h"
    113 #include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h"
    114 
    115 #if defined(OS_WIN)
    116 #include <windows.h>
    117 #include <objbase.h>
    118 #include "base/win/scoped_com_initializer.h"
    119 #else
    120 // TODO(port)
    121 #include "base/memory/scoped_handle.h"
    122 #include "content/child/npapi/np_channel_base.h"
    123 #endif
    124 
    125 #if defined(OS_MACOSX)
    126 #include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h"
    127 #endif
    128 
    129 #if defined(OS_POSIX)
    130 #include "ipc/ipc_channel_posix.h"
    131 #endif
    132 
    133 #if defined(OS_ANDROID)
    134 #include <cpu-features.h>
    135 #include "content/renderer/android/synchronous_compositor_factory.h"
    136 #include "content/renderer/media/android/renderer_demuxer_android.h"
    137 #endif
    138 
    139 #if defined(ENABLE_PLUGINS)
    140 #include "content/renderer/npapi/plugin_channel_host.h"
    141 #endif
    142 
    143 using base::ThreadRestrictions;
    144 using blink::WebDocument;
    145 using blink::WebFrame;
    146 using blink::WebNetworkStateNotifier;
    147 using blink::WebRuntimeFeatures;
    148 using blink::WebScriptController;
    149 using blink::WebSecurityPolicy;
    150 using blink::WebString;
    151 using blink::WebView;
    152 
    153 namespace content {
    154 
    155 namespace {
    156 
    157 const int64 kInitialIdleHandlerDelayMs = 1000;
    158 const int64 kShortIdleHandlerDelayMs = 1000;
    159 const int64 kLongIdleHandlerDelayMs = 30*1000;
    160 const int kIdleCPUUsageThresholdInPercents = 3;
    161 
    162 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
    163 // incorrectly from the wrong thread.
    164 base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> >
    165     lazy_tls = LAZY_INSTANCE_INITIALIZER;
    166 
    167 class RenderViewZoomer : public RenderViewVisitor {
    168  public:
    169   RenderViewZoomer(const std::string& scheme,
    170                    const std::string& host,
    171                    double zoom_level) : scheme_(scheme),
    172                                         host_(host),
    173                                         zoom_level_(zoom_level) {
    174   }
    175 
    176   virtual bool Visit(RenderView* render_view) OVERRIDE {
    177     WebView* webview = render_view->GetWebView();
    178     WebDocument document = webview->mainFrame()->document();
    179 
    180     // Don't set zoom level for full-page plugin since they don't use the same
    181     // zoom settings.
    182     if (document.isPluginDocument())
    183       return true;
    184     GURL url(document.url());
    185     // Empty scheme works as wildcard that matches any scheme,
    186     if ((net::GetHostOrSpecFromURL(url) == host_) &&
    187         (scheme_.empty() || scheme_ == url.scheme())) {
    188       webview->setZoomLevel(zoom_level_);
    189     }
    190     return true;
    191   }
    192 
    193  private:
    194   const std::string scheme_;
    195   const std::string host_;
    196   const double zoom_level_;
    197 
    198   DISALLOW_COPY_AND_ASSIGN(RenderViewZoomer);
    199 };
    200 
    201 std::string HostToCustomHistogramSuffix(const std::string& host) {
    202   if (host == "mail.google.com")
    203     return ".gmail";
    204   if (host == "docs.google.com" || host == "drive.google.com")
    205     return ".docs";
    206   if (host == "plus.google.com")
    207     return ".plus";
    208   return std::string();
    209 }
    210 
    211 void* CreateHistogram(
    212     const char *name, int min, int max, size_t buckets) {
    213   if (min <= 0)
    214     min = 1;
    215   std::string histogram_name;
    216   RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
    217   if (render_thread_impl) {  // Can be null in tests.
    218     histogram_name = render_thread_impl->
    219         histogram_customizer()->ConvertToCustomHistogramName(name);
    220   } else {
    221     histogram_name = std::string(name);
    222   }
    223   base::HistogramBase* histogram = base::Histogram::FactoryGet(
    224       histogram_name, min, max, buckets,
    225       base::Histogram::kUmaTargetedHistogramFlag);
    226   return histogram;
    227 }
    228 
    229 void AddHistogramSample(void* hist, int sample) {
    230   base::Histogram* histogram = static_cast<base::Histogram*>(hist);
    231   histogram->Add(sample);
    232 }
    233 
    234 scoped_ptr<base::SharedMemory> AllocateSharedMemoryFunction(size_t size) {
    235   return RenderThreadImpl::Get()->HostAllocateSharedMemoryBuffer(size);
    236 }
    237 
    238 void EnableWebCoreLogChannels(const std::string& channels) {
    239   if (channels.empty())
    240     return;
    241   base::StringTokenizer t(channels, ", ");
    242   while (t.GetNext())
    243     blink::enableLogChannel(t.token().c_str());
    244 }
    245 
    246 }  // namespace
    247 
    248 RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() {
    249   custom_histograms_.insert("V8.MemoryExternalFragmentationTotal");
    250   custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted");
    251   custom_histograms_.insert("V8.MemoryHeapSampleTotalUsed");
    252 }
    253 
    254 RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {}
    255 
    256 void RenderThreadImpl::HistogramCustomizer::RenderViewNavigatedToHost(
    257     const std::string& host, size_t view_count) {
    258   if (CommandLine::ForCurrentProcess()->HasSwitch(
    259       switches::kDisableHistogramCustomizer)) {
    260     return;
    261   }
    262   // Check if all RenderViews are displaying a page from the same host. If there
    263   // is only one RenderView, the common host is this view's host. If there are
    264   // many, check if this one shares the common host of the other
    265   // RenderViews. It's ok to not detect some cases where the RenderViews share a
    266   // common host. This information is only used for producing custom histograms.
    267   if (view_count == 1)
    268     SetCommonHost(host);
    269   else if (host != common_host_)
    270     SetCommonHost(std::string());
    271 }
    272 
    273 std::string RenderThreadImpl::HistogramCustomizer::ConvertToCustomHistogramName(
    274     const char* histogram_name) const {
    275   std::string name(histogram_name);
    276   if (!common_host_histogram_suffix_.empty() &&
    277       custom_histograms_.find(name) != custom_histograms_.end())
    278     name += common_host_histogram_suffix_;
    279   return name;
    280 }
    281 
    282 void RenderThreadImpl::HistogramCustomizer::SetCommonHost(
    283     const std::string& host) {
    284   if (host != common_host_) {
    285     common_host_ = host;
    286     common_host_histogram_suffix_ = HostToCustomHistogramSuffix(host);
    287     v8::V8::SetCreateHistogramFunction(CreateHistogram);
    288   }
    289 }
    290 
    291 RenderThreadImpl* RenderThreadImpl::current() {
    292   return lazy_tls.Pointer()->Get();
    293 }
    294 
    295 // When we run plugins in process, we actually run them on the render thread,
    296 // which means that we need to make the render thread pump UI events.
    297 RenderThreadImpl::RenderThreadImpl() {
    298   Init();
    299 }
    300 
    301 RenderThreadImpl::RenderThreadImpl(const std::string& channel_name)
    302     : ChildThread(channel_name) {
    303   Init();
    304 }
    305 
    306 void RenderThreadImpl::Init() {
    307   TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, "");
    308 
    309   base::debug::TraceLog::GetInstance()->SetThreadSortIndex(
    310       base::PlatformThread::CurrentId(),
    311       kTraceEventRendererMainThreadSortIndex);
    312 
    313   v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
    314   v8::V8::SetCreateHistogramFunction(CreateHistogram);
    315   v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
    316 
    317 #if defined(OS_MACOSX) || defined(OS_ANDROID)
    318   // On Mac and Android, the select popups are rendered by the browser.
    319   blink::WebView::setUseExternalPopupMenus(true);
    320 #endif
    321 
    322   lazy_tls.Pointer()->Set(this);
    323 
    324 #if defined(OS_WIN)
    325   // If you are running plugins in this thread you need COM active but in
    326   // the normal case you don't.
    327   if (RenderProcessImpl::InProcessPlugins())
    328     initialize_com_.reset(new base::win::ScopedCOMInitializer());
    329 #endif
    330 
    331   // Register this object as the main thread.
    332   ChildProcess::current()->set_main_thread(this);
    333 
    334   // In single process the single process is all there is.
    335   suspend_webkit_shared_timer_ = true;
    336   notify_webkit_of_modal_loop_ = true;
    337   widget_count_ = 0;
    338   hidden_widget_count_ = 0;
    339   idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs;
    340   idle_notifications_to_skip_ = 0;
    341   layout_test_mode_ = false;
    342   shutdown_event_ = NULL;
    343 
    344   appcache_dispatcher_.reset(
    345       new AppCacheDispatcher(Get(), new AppCacheFrontendImpl()));
    346   dom_storage_dispatcher_.reset(new DomStorageDispatcher());
    347   main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
    348       thread_safe_sender()));
    349   embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher());
    350 
    351   media_stream_center_ = NULL;
    352 
    353   db_message_filter_ = new DBMessageFilter();
    354   AddFilter(db_message_filter_.get());
    355 
    356 #if defined(ENABLE_WEBRTC)
    357   peer_connection_tracker_.reset(new PeerConnectionTracker());
    358   AddObserver(peer_connection_tracker_.get());
    359 
    360   p2p_socket_dispatcher_ =
    361       new P2PSocketDispatcher(GetIOMessageLoopProxy().get());
    362   AddFilter(p2p_socket_dispatcher_.get());
    363 
    364   webrtc_identity_service_.reset(new WebRTCIdentityService());
    365 #endif  // defined(ENABLE_WEBRTC)
    366   vc_manager_ = new VideoCaptureImplManager();
    367   AddFilter(vc_manager_->video_capture_message_filter());
    368 
    369   audio_input_message_filter_ =
    370       new AudioInputMessageFilter(GetIOMessageLoopProxy());
    371   AddFilter(audio_input_message_filter_.get());
    372 
    373   audio_message_filter_ = new AudioMessageFilter(GetIOMessageLoopProxy());
    374   AddFilter(audio_message_filter_.get());
    375 
    376   midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy());
    377   AddFilter(midi_message_filter_.get());
    378 
    379   AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter());
    380 
    381   GetContentClient()->renderer()->RenderThreadStarted();
    382 
    383   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    384   if (command_line.HasSwitch(switches::kEnableGpuBenchmarking))
    385       RegisterExtension(GpuBenchmarkingExtension::Get());
    386 
    387 #if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
    388   if (command_line.HasSwitch(switches::kEnableMemoryBenchmarking))
    389     RegisterExtension(MemoryBenchmarkingExtension::Get());
    390 #endif  // USE_TCMALLOC
    391 
    392   if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking)) {
    393     LOG(WARNING) << "Enabling unsafe Skia benchmarking extension.";
    394     RegisterExtension(SkiaBenchmarkingExtension::Get());
    395   }
    396 
    397   // Note that under Linux, the media library will normally already have
    398   // been initialized by the Zygote before this instance became a Renderer.
    399   base::FilePath media_path;
    400   PathService::Get(DIR_MEDIA_LIBS, &media_path);
    401   if (!media_path.empty())
    402     media::InitializeMediaLibrary(media_path);
    403 
    404   memory_pressure_listener_.reset(new base::MemoryPressureListener(
    405       base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this))));
    406 
    407   renderer_process_id_ = base::kNullProcessId;
    408 
    409   // AllocateGpuMemoryBuffer must be used exclusively on one thread but
    410   // it doesn't have to be the same thread RenderThreadImpl is created on.
    411   allocate_gpu_memory_buffer_thread_checker_.DetachFromThread();
    412 
    413   TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, "");
    414 }
    415 
    416 RenderThreadImpl::~RenderThreadImpl() {
    417 }
    418 
    419 void RenderThreadImpl::Shutdown() {
    420   FOR_EACH_OBSERVER(
    421       RenderProcessObserver, observers_, OnRenderProcessShutdown());
    422 
    423   ChildThread::Shutdown();
    424 
    425   // Wait for all databases to be closed.
    426   if (webkit_platform_support_) {
    427     webkit_platform_support_->web_database_observer_impl()->
    428         WaitForAllDatabasesToClose();
    429   }
    430 
    431   // Shutdown in reverse of the initialization order.
    432   if (devtools_agent_message_filter_.get()) {
    433     RemoveFilter(devtools_agent_message_filter_.get());
    434     devtools_agent_message_filter_ = NULL;
    435   }
    436 
    437   RemoveFilter(audio_input_message_filter_.get());
    438   audio_input_message_filter_ = NULL;
    439 
    440   RemoveFilter(audio_message_filter_.get());
    441   audio_message_filter_ = NULL;
    442 
    443   RemoveFilter(vc_manager_->video_capture_message_filter());
    444 
    445   RemoveFilter(db_message_filter_.get());
    446   db_message_filter_ = NULL;
    447 
    448   // Shutdown the file thread if it's running.
    449   if (file_thread_)
    450     file_thread_->Stop();
    451 
    452   if (compositor_output_surface_filter_.get()) {
    453     RemoveFilter(compositor_output_surface_filter_.get());
    454     compositor_output_surface_filter_ = NULL;
    455   }
    456 
    457   compositor_thread_.reset();
    458   input_handler_manager_.reset();
    459   if (input_event_filter_.get()) {
    460     RemoveFilter(input_event_filter_.get());
    461     input_event_filter_ = NULL;
    462   }
    463 
    464   // Ramp down IDB before we ramp down WebKit (and V8), since IDB classes might
    465   // hold pointers to V8 objects (e.g., via pending requests).
    466   main_thread_indexed_db_dispatcher_.reset();
    467 
    468   if (webkit_platform_support_)
    469     blink::shutdown();
    470 
    471   lazy_tls.Pointer()->Set(NULL);
    472 
    473   // TODO(port)
    474 #if defined(OS_WIN)
    475   // Clean up plugin channels before this thread goes away.
    476   NPChannelBase::CleanupChannels();
    477 #endif
    478 
    479   // Leak shared contexts on other threads, as we can not get to the correct
    480   // thread to destroy them.
    481   if (offscreen_compositor_contexts_.get())
    482     offscreen_compositor_contexts_->set_leak_on_destroy();
    483 }
    484 
    485 bool RenderThreadImpl::Send(IPC::Message* msg) {
    486   // Certain synchronous messages cannot always be processed synchronously by
    487   // the browser, e.g., putting up UI and waiting for the user. This could cause
    488   // a complete hang of Chrome if a windowed plug-in is trying to communicate
    489   // with the renderer thread since the browser's UI thread could be stuck
    490   // (within a Windows API call) trying to synchronously communicate with the
    491   // plug-in.  The remedy is to pump messages on this thread while the browser
    492   // is processing this request. This creates an opportunity for re-entrancy
    493   // into WebKit, so we need to take care to disable callbacks, timers, and
    494   // pending network loads that could trigger such callbacks.
    495   bool pumping_events = false;
    496   if (msg->is_sync()) {
    497     if (msg->is_caller_pumping_messages()) {
    498       pumping_events = true;
    499     }
    500   }
    501 
    502   bool suspend_webkit_shared_timer = true;  // default value
    503   std::swap(suspend_webkit_shared_timer, suspend_webkit_shared_timer_);
    504 
    505   bool notify_webkit_of_modal_loop = true;  // default value
    506   std::swap(notify_webkit_of_modal_loop, notify_webkit_of_modal_loop_);
    507 
    508 #if defined(ENABLE_PLUGINS)
    509   int render_view_id = MSG_ROUTING_NONE;
    510 #endif
    511 
    512   if (pumping_events) {
    513     if (suspend_webkit_shared_timer)
    514       webkit_platform_support_->SuspendSharedTimer();
    515 
    516     if (notify_webkit_of_modal_loop)
    517       WebView::willEnterModalLoop();
    518 #if defined(ENABLE_PLUGINS)
    519     RenderViewImpl* render_view =
    520         RenderViewImpl::FromRoutingID(msg->routing_id());
    521     if (render_view) {
    522       render_view_id = msg->routing_id();
    523       PluginChannelHost::Broadcast(
    524           new PluginMsg_SignalModalDialogEvent(render_view_id));
    525     }
    526 #endif
    527   }
    528 
    529   bool rv = ChildThread::Send(msg);
    530 
    531   if (pumping_events) {
    532 #if defined(ENABLE_PLUGINS)
    533     if (render_view_id != MSG_ROUTING_NONE) {
    534       PluginChannelHost::Broadcast(
    535           new PluginMsg_ResetModalDialogEvent(render_view_id));
    536     }
    537 #endif
    538 
    539     if (notify_webkit_of_modal_loop)
    540       WebView::didExitModalLoop();
    541 
    542     if (suspend_webkit_shared_timer)
    543       webkit_platform_support_->ResumeSharedTimer();
    544   }
    545 
    546   return rv;
    547 }
    548 
    549 base::MessageLoop* RenderThreadImpl::GetMessageLoop() {
    550   return message_loop();
    551 }
    552 
    553 IPC::SyncChannel* RenderThreadImpl::GetChannel() {
    554   return channel();
    555 }
    556 
    557 std::string RenderThreadImpl::GetLocale() {
    558   // The browser process should have passed the locale to the renderer via the
    559   // --lang command line flag.
    560   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
    561   const std::string& lang =
    562       parsed_command_line.GetSwitchValueASCII(switches::kLang);
    563   DCHECK(!lang.empty());
    564   return lang;
    565 }
    566 
    567 IPC::SyncMessageFilter* RenderThreadImpl::GetSyncMessageFilter() {
    568   return sync_message_filter();
    569 }
    570 
    571 scoped_refptr<base::MessageLoopProxy>
    572     RenderThreadImpl::GetIOMessageLoopProxy() {
    573   return ChildProcess::current()->io_message_loop_proxy();
    574 }
    575 
    576 void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) {
    577   widget_count_++;
    578   return ChildThread::AddRoute(routing_id, listener);
    579 }
    580 
    581 void RenderThreadImpl::RemoveRoute(int32 routing_id) {
    582   widget_count_--;
    583   return ChildThread::RemoveRoute(routing_id);
    584 }
    585 
    586 int RenderThreadImpl::GenerateRoutingID() {
    587   int routing_id = MSG_ROUTING_NONE;
    588   Send(new ViewHostMsg_GenerateRoutingID(&routing_id));
    589   return routing_id;
    590 }
    591 
    592 void RenderThreadImpl::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
    593   channel()->AddFilter(filter);
    594 }
    595 
    596 void RenderThreadImpl::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
    597   channel()->RemoveFilter(filter);
    598 }
    599 
    600 void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) {
    601   observers_.AddObserver(observer);
    602 }
    603 
    604 void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) {
    605   observers_.RemoveObserver(observer);
    606 }
    607 
    608 void RenderThreadImpl::SetResourceDispatcherDelegate(
    609     ResourceDispatcherDelegate* delegate) {
    610   resource_dispatcher()->set_delegate(delegate);
    611 }
    612 
    613 void RenderThreadImpl::WidgetHidden() {
    614   DCHECK_LT(hidden_widget_count_, widget_count_);
    615   hidden_widget_count_++;
    616 
    617   if (widget_count_ && hidden_widget_count_ == widget_count_) {
    618 #if !defined(SYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE)
    619     // TODO(vollick): Remove this this heavy-handed approach once we're polling
    620     // the real system memory pressure.
    621     base::MemoryPressureListener::NotifyMemoryPressure(
    622         base::MemoryPressureListener::MEMORY_PRESSURE_MODERATE);
    623 #endif
    624     if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
    625       ScheduleIdleHandler(kInitialIdleHandlerDelayMs);
    626   }
    627 }
    628 
    629 void RenderThreadImpl::WidgetRestored() {
    630   DCHECK_GT(hidden_widget_count_, 0);
    631   hidden_widget_count_--;
    632 
    633   if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) {
    634     return;
    635   }
    636 
    637   ScheduleIdleHandler(kLongIdleHandlerDelayMs);
    638 }
    639 
    640 void RenderThreadImpl::EnsureWebKitInitialized() {
    641   if (webkit_platform_support_)
    642     return;
    643 
    644   webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
    645   blink::initialize(webkit_platform_support_.get());
    646 
    647   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    648 
    649   bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing);
    650   if (enable) {
    651 #if defined(OS_ANDROID)
    652     if (SynchronousCompositorFactory* factory =
    653         SynchronousCompositorFactory::GetInstance())
    654       compositor_message_loop_proxy_ =
    655           factory->GetCompositorMessageLoop();
    656 #endif
    657     if (!compositor_message_loop_proxy_.get()) {
    658       compositor_thread_.reset(new base::Thread("Compositor"));
    659       compositor_thread_->Start();
    660 #if defined(OS_ANDROID)
    661       compositor_thread_->SetPriority(base::kThreadPriority_Display);
    662 #endif
    663       compositor_message_loop_proxy_ =
    664           compositor_thread_->message_loop_proxy();
    665       compositor_message_loop_proxy_->PostTask(
    666           FROM_HERE,
    667           base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed),
    668                      false));
    669     }
    670 
    671     InputHandlerManagerClient* input_handler_manager_client = NULL;
    672 #if defined(OS_ANDROID)
    673     if (SynchronousCompositorFactory* factory =
    674         SynchronousCompositorFactory::GetInstance()) {
    675       input_handler_manager_client = factory->GetInputHandlerManagerClient();
    676     }
    677 #endif
    678     if (!input_handler_manager_client) {
    679       input_event_filter_ =
    680           new InputEventFilter(this, compositor_message_loop_proxy_);
    681       AddFilter(input_event_filter_.get());
    682       input_handler_manager_client = input_event_filter_.get();
    683     }
    684     input_handler_manager_.reset(
    685         new InputHandlerManager(compositor_message_loop_proxy_,
    686                                 input_handler_manager_client));
    687   }
    688 
    689   scoped_refptr<base::MessageLoopProxy> output_surface_loop;
    690   if (enable)
    691     output_surface_loop = compositor_message_loop_proxy_;
    692   else
    693     output_surface_loop = base::MessageLoopProxy::current();
    694 
    695   compositor_output_surface_filter_ =
    696       CompositorOutputSurface::CreateFilter(output_surface_loop.get());
    697   AddFilter(compositor_output_surface_filter_.get());
    698 
    699   WebScriptController::enableV8SingleThreadMode();
    700 
    701   RenderThreadImpl::RegisterSchemes();
    702 
    703   EnableWebCoreLogChannels(
    704       command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels));
    705 
    706   SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
    707 
    708   if (!media::IsMediaLibraryInitialized()) {
    709     WebRuntimeFeatures::enableMediaPlayer(false);
    710     WebRuntimeFeatures::enableWebAudio(false);
    711   }
    712 
    713   FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
    714 
    715   devtools_agent_message_filter_ = new DevToolsAgentFilter();
    716   AddFilter(devtools_agent_message_filter_.get());
    717 
    718   if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
    719     ScheduleIdleHandler(kLongIdleHandlerDelayMs);
    720 
    721   webkit::SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
    722 }
    723 
    724 void RenderThreadImpl::RegisterSchemes() {
    725   // swappedout: pages should not be accessible, and should also
    726   // be treated as empty documents that can commit synchronously.
    727   WebString swappedout_scheme(ASCIIToUTF16(kSwappedOutScheme));
    728   WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(swappedout_scheme);
    729   WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme);
    730 }
    731 
    732 void RenderThreadImpl::RecordAction(const UserMetricsAction& action) {
    733   Send(new ViewHostMsg_UserMetricsRecordAction(action.str_));
    734 }
    735 
    736 void RenderThreadImpl::RecordComputedAction(const std::string& action) {
    737   Send(new ViewHostMsg_UserMetricsRecordAction(action));
    738 }
    739 
    740 scoped_ptr<base::SharedMemory>
    741     RenderThreadImpl::HostAllocateSharedMemoryBuffer(size_t size) {
    742   if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
    743     return scoped_ptr<base::SharedMemory>();
    744 
    745   base::SharedMemoryHandle handle;
    746   bool success;
    747   IPC::Message* message =
    748       new ChildProcessHostMsg_SyncAllocateSharedMemory(size, &handle);
    749 
    750   // Allow calling this from the compositor thread.
    751   if (base::MessageLoop::current() == message_loop())
    752     success = ChildThread::Send(message);
    753   else
    754     success = sync_message_filter()->Send(message);
    755 
    756   if (!success)
    757     return scoped_ptr<base::SharedMemory>();
    758 
    759   if (!base::SharedMemory::IsHandleValid(handle))
    760     return scoped_ptr<base::SharedMemory>();
    761 
    762   return scoped_ptr<base::SharedMemory>(new base::SharedMemory(handle, false));
    763 }
    764 
    765 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
    766   WebScriptController::registerExtension(extension);
    767 }
    768 
    769 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) {
    770   idle_notification_delay_in_ms_ = initial_delay_ms;
    771   idle_timer_.Stop();
    772   idle_timer_.Start(FROM_HERE,
    773       base::TimeDelta::FromMilliseconds(initial_delay_ms),
    774       this, &RenderThreadImpl::IdleHandler);
    775 }
    776 
    777 void RenderThreadImpl::IdleHandler() {
    778   bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) &&
    779                                GetContentClient()->renderer()->
    780                                    RunIdleHandlerWhenWidgetsHidden();
    781   if (run_in_foreground_tab) {
    782     IdleHandlerInForegroundTab();
    783     return;
    784   }
    785 
    786   base::allocator::ReleaseFreeMemory();
    787 
    788   v8::V8::IdleNotification();
    789 
    790   // Schedule next invocation.
    791   // Dampen the delay using the algorithm (if delay is in seconds):
    792   //    delay = delay + 1 / (delay + 2)
    793   // Using floor(delay) has a dampening effect such as:
    794   //    1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
    795   // If the delay is in milliseconds, the above formula is equivalent to:
    796   //    delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
    797   // which is equivalent to
    798   //    delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
    799   // Note that idle_notification_delay_in_ms_ would be reset to
    800   // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden.
    801   ScheduleIdleHandler(idle_notification_delay_in_ms_ +
    802                       1000000 / (idle_notification_delay_in_ms_ + 2000));
    803 
    804   FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
    805 }
    806 
    807 void RenderThreadImpl::IdleHandlerInForegroundTab() {
    808   // Increase the delay in the same way as in IdleHandler,
    809   // but make it periodic by reseting it once it is too big.
    810   int64 new_delay_ms = idle_notification_delay_in_ms_ +
    811                        1000000 / (idle_notification_delay_in_ms_ + 2000);
    812   if (new_delay_ms >= kLongIdleHandlerDelayMs)
    813     new_delay_ms = kShortIdleHandlerDelayMs;
    814 
    815   if (idle_notifications_to_skip_ > 0) {
    816     idle_notifications_to_skip_--;
    817   } else  {
    818     int cpu_usage = 0;
    819     Send(new ViewHostMsg_GetCPUUsage(&cpu_usage));
    820     // Idle notification hint roughly specifies the expected duration of the
    821     // idle pause. We set it proportional to the idle timer delay.
    822     int idle_hint = static_cast<int>(new_delay_ms / 10);
    823     if (cpu_usage < kIdleCPUUsageThresholdInPercents) {
    824       base::allocator::ReleaseFreeMemory();
    825       if (v8::V8::IdleNotification(idle_hint)) {
    826         // V8 finished collecting garbage.
    827         new_delay_ms = kLongIdleHandlerDelayMs;
    828       }
    829     }
    830   }
    831   ScheduleIdleHandler(new_delay_ms);
    832 }
    833 
    834 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
    835   return idle_notification_delay_in_ms_;
    836 }
    837 
    838 void RenderThreadImpl::SetIdleNotificationDelayInMs(
    839     int64 idle_notification_delay_in_ms) {
    840   idle_notification_delay_in_ms_ = idle_notification_delay_in_ms;
    841 }
    842 
    843 void RenderThreadImpl::ToggleWebKitSharedTimer(bool suspend) {
    844   if (suspend_webkit_shared_timer_) {
    845     EnsureWebKitInitialized();
    846     if (suspend) {
    847       webkit_platform_support_->SuspendSharedTimer();
    848     } else {
    849       webkit_platform_support_->ResumeSharedTimer();
    850     }
    851   }
    852 }
    853 
    854 void RenderThreadImpl::UpdateHistograms(int sequence_number) {
    855   child_histogram_message_filter()->SendHistograms(sequence_number);
    856 }
    857 
    858 int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) {
    859   return webkit_glue::WorkerTaskRunner::Instance()->PostTaskToAllThreads(
    860       closure);
    861 }
    862 
    863 bool RenderThreadImpl::ResolveProxy(const GURL& url, std::string* proxy_list) {
    864   bool result = false;
    865   Send(new ViewHostMsg_ResolveProxy(url, &result, proxy_list));
    866   return result;
    867 }
    868 
    869 void RenderThreadImpl::PostponeIdleNotification() {
    870   idle_notifications_to_skip_ = 2;
    871 }
    872 
    873 scoped_refptr<RendererGpuVideoAcceleratorFactories>
    874 RenderThreadImpl::GetGpuFactories() {
    875   DCHECK(IsMainThread());
    876 
    877   scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
    878   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
    879   scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories;
    880   if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
    881     if (!gpu_va_context_provider_ ||
    882         gpu_va_context_provider_->DestroyedOnMainThread()) {
    883       if (!gpu_channel_host) {
    884         gpu_channel_host = EstablishGpuChannelSync(
    885             CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
    886       }
    887       gpu_va_context_provider_ = ContextProviderCommandBuffer::Create(
    888           make_scoped_ptr(
    889               WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
    890                   gpu_channel_host.get(),
    891                   blink::WebGraphicsContext3D::Attributes(),
    892                   GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"),
    893                   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())),
    894           "GPU-VideoAccelerator-Offscreen");
    895     }
    896   }
    897   if (gpu_channel_host) {
    898     gpu_factories = new RendererGpuVideoAcceleratorFactories(
    899         gpu_channel_host.get(), gpu_va_context_provider_);
    900   }
    901   return gpu_factories;
    902 }
    903 
    904 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
    905 RenderThreadImpl::CreateOffscreenContext3d() {
    906   blink::WebGraphicsContext3D::Attributes attributes;
    907   attributes.shareResources = true;
    908   attributes.depth = false;
    909   attributes.stencil = false;
    910   attributes.antialias = false;
    911   attributes.noAutomaticFlushes = true;
    912 
    913   scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
    914       CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
    915   return make_scoped_ptr(
    916       WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
    917           gpu_channel_host.get(),
    918           attributes,
    919           GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"),
    920           WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits()));
    921 }
    922 
    923 scoped_refptr<cc::ContextProvider>
    924 RenderThreadImpl::OffscreenCompositorContextProvider() {
    925   DCHECK(IsMainThread());
    926 
    927 #if defined(OS_ANDROID)
    928   if (SynchronousCompositorFactory* factory =
    929       SynchronousCompositorFactory::GetInstance()) {
    930     if (compositor_message_loop_proxy_)
    931       return factory->GetOffscreenContextProviderForCompositorThread();
    932     return factory->GetOffscreenContextProviderForMainThread();
    933   }
    934 #endif
    935 
    936   if (!offscreen_compositor_contexts_.get() ||
    937       offscreen_compositor_contexts_->DestroyedOnMainThread()) {
    938     offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create(
    939         CreateOffscreenContext3d(),
    940         "Compositor-Offscreen");
    941   }
    942   return offscreen_compositor_contexts_;
    943 }
    944 
    945 scoped_refptr<cc::ContextProvider>
    946 RenderThreadImpl::SharedMainThreadContextProvider() {
    947   DCHECK(IsMainThread());
    948 #if defined(OS_ANDROID)
    949   if (SynchronousCompositorFactory* factory =
    950       SynchronousCompositorFactory::GetInstance())
    951     return factory->GetOffscreenContextProviderForMainThread();
    952 #endif
    953 
    954   if (!shared_main_thread_contexts_ ||
    955       shared_main_thread_contexts_->DestroyedOnMainThread()) {
    956     if (compositor_message_loop_proxy_) {
    957       // In threaded compositing mode, we have to create a new ContextProvider
    958       // to bind to the main thread since the compositor's is bound to the
    959       // compositor thread.
    960       shared_main_thread_contexts_ =
    961           ContextProviderCommandBuffer::Create(CreateOffscreenContext3d(),
    962                                                "Offscreen-MainThread");
    963     } else {
    964       // In single threaded mode, we can use the same context provider.
    965       shared_main_thread_contexts_ =
    966           static_cast<ContextProviderCommandBuffer*>(
    967                 OffscreenCompositorContextProvider().get());
    968     }
    969   }
    970   if (shared_main_thread_contexts_ &&
    971       !shared_main_thread_contexts_->BindToCurrentThread())
    972     shared_main_thread_contexts_ = NULL;
    973   return shared_main_thread_contexts_;
    974 }
    975 
    976 AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
    977   if (!audio_renderer_mixer_manager_) {
    978     audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager(
    979         GetAudioHardwareConfig()));
    980   }
    981 
    982   return audio_renderer_mixer_manager_.get();
    983 }
    984 
    985 media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() {
    986   if (!audio_hardware_config_) {
    987     media::AudioParameters input_params;
    988     media::AudioParameters output_params;
    989     Send(new ViewHostMsg_GetAudioHardwareConfig(
    990         &input_params, &output_params));
    991 
    992     audio_hardware_config_.reset(new media::AudioHardwareConfig(
    993         input_params, output_params));
    994     audio_message_filter_->SetAudioHardwareConfig(audio_hardware_config_.get());
    995   }
    996 
    997   return audio_hardware_config_.get();
    998 }
    999 
   1000 #if defined(OS_WIN)
   1001 void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
   1002                                               const base::string16& str) {
   1003   Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str));
   1004 }
   1005 
   1006 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) {
   1007   Send(new ChildProcessHostMsg_PreCacheFont(log_font));
   1008 }
   1009 
   1010 void RenderThreadImpl::ReleaseCachedFonts() {
   1011   Send(new ChildProcessHostMsg_ReleaseCachedFonts());
   1012 }
   1013 
   1014 #endif  // OS_WIN
   1015 
   1016 bool RenderThreadImpl::IsMainThread() {
   1017   return !!current();
   1018 }
   1019 
   1020 base::MessageLoop* RenderThreadImpl::GetMainLoop() {
   1021   return message_loop();
   1022 }
   1023 
   1024 scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() {
   1025   return io_message_loop_proxy_;
   1026 }
   1027 
   1028 base::WaitableEvent* RenderThreadImpl::GetShutDownEvent() {
   1029   return shutdown_event_;
   1030 }
   1031 
   1032 scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory(
   1033     size_t size) {
   1034   return scoped_ptr<base::SharedMemory>(
   1035       HostAllocateSharedMemoryBuffer(size));
   1036 }
   1037 
   1038 int32 RenderThreadImpl::CreateViewCommandBuffer(
   1039       int32 surface_id, const GPUCreateCommandBufferConfig& init_params) {
   1040   TRACE_EVENT1("gpu",
   1041                "RenderThreadImpl::CreateViewCommandBuffer",
   1042                "surface_id",
   1043                surface_id);
   1044 
   1045   int32 route_id = MSG_ROUTING_NONE;
   1046   IPC::Message* message = new GpuHostMsg_CreateViewCommandBuffer(
   1047       surface_id,
   1048       init_params,
   1049       &route_id);
   1050 
   1051   // Allow calling this from the compositor thread.
   1052   thread_safe_sender()->Send(message);
   1053 
   1054   return route_id;
   1055 }
   1056 
   1057 void RenderThreadImpl::CreateImage(
   1058     gfx::PluginWindowHandle window,
   1059     int32 image_id,
   1060     const CreateImageCallback& callback) {
   1061   NOTREACHED();
   1062 }
   1063 
   1064 void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) {
   1065   NOTREACHED();
   1066 }
   1067 
   1068 scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer(
   1069     size_t width,
   1070     size_t height,
   1071     unsigned internalformat) {
   1072   DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread());
   1073 
   1074   if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
   1075     return scoped_ptr<gfx::GpuMemoryBuffer>();
   1076 
   1077   gfx::GpuMemoryBufferHandle handle;
   1078   bool success;
   1079   IPC::Message* message =
   1080       new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(width,
   1081                                                           height,
   1082                                                           internalformat,
   1083                                                           &handle);
   1084 
   1085   // Allow calling this from the compositor thread.
   1086   if (base::MessageLoop::current() == message_loop())
   1087     success = ChildThread::Send(message);
   1088   else
   1089     success = sync_message_filter()->Send(message);
   1090 
   1091   if (!success)
   1092     return scoped_ptr<gfx::GpuMemoryBuffer>();
   1093 
   1094   return GpuMemoryBufferImpl::Create(
   1095       handle,
   1096       gfx::Size(width, height),
   1097       internalformat).PassAs<gfx::GpuMemoryBuffer>();
   1098 }
   1099 
   1100 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
   1101   suspend_webkit_shared_timer_ = false;
   1102 }
   1103 
   1104 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
   1105   notify_webkit_of_modal_loop_ = false;
   1106 }
   1107 
   1108 void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme,
   1109                                                    const std::string& host,
   1110                                                    double zoom_level) {
   1111   RenderViewZoomer zoomer(scheme, host, zoom_level);
   1112   RenderView::ForEach(&zoomer);
   1113 }
   1114 
   1115 bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
   1116   ObserverListBase<RenderProcessObserver>::Iterator it(observers_);
   1117   RenderProcessObserver* observer;
   1118   while ((observer = it.GetNext()) != NULL) {
   1119     if (observer->OnControlMessageReceived(msg))
   1120       return true;
   1121   }
   1122 
   1123   // Some messages are handled by delegates.
   1124   if (appcache_dispatcher_->OnMessageReceived(msg) ||
   1125       dom_storage_dispatcher_->OnMessageReceived(msg) ||
   1126       embedded_worker_dispatcher_->OnMessageReceived(msg)) {
   1127     return true;
   1128   }
   1129 
   1130   bool handled = true;
   1131   IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg)
   1132     IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL,
   1133                         OnSetZoomLevelForCurrentURL)
   1134     // TODO(port): removed from render_messages_internal.h;
   1135     // is there a new non-windows message I should add here?
   1136     IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
   1137     IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
   1138     IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged)
   1139     IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData)
   1140     IPC_MESSAGE_HANDLER(ViewMsg_SetRendererProcessID, OnSetRendererProcessID)
   1141 #if defined(OS_ANDROID)
   1142     IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended,
   1143                         OnSetWebKitSharedTimersSuspended)
   1144 #endif
   1145 #if defined(OS_MACOSX)
   1146     IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
   1147 #endif
   1148     IPC_MESSAGE_UNHANDLED(handled = false)
   1149   IPC_END_MESSAGE_MAP()
   1150   return handled;
   1151 }
   1152 
   1153 void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
   1154   EnsureWebKitInitialized();
   1155   // When bringing in render_view, also bring in webkit's glue and jsbindings.
   1156   RenderViewImpl::Create(
   1157       params.opener_route_id,
   1158       params.renderer_preferences,
   1159       params.web_preferences,
   1160       params.view_id,
   1161       params.main_frame_routing_id,
   1162       params.surface_id,
   1163       params.session_storage_namespace_id,
   1164       params.frame_name,
   1165       false,
   1166       params.swapped_out,
   1167       params.hidden,
   1168       params.next_page_id,
   1169       params.screen_info,
   1170       params.accessibility_mode,
   1171       params.allow_partial_swap);
   1172 }
   1173 
   1174 GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
   1175     CauseForGpuLaunch cause_for_gpu_launch) {
   1176   TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync");
   1177 
   1178   if (gpu_channel_.get()) {
   1179     // Do nothing if we already have a GPU channel or are already
   1180     // establishing one.
   1181     if (!gpu_channel_->IsLost())
   1182       return gpu_channel_.get();
   1183 
   1184     // Recreate the channel if it has been lost.
   1185     gpu_channel_ = NULL;
   1186   }
   1187 
   1188   // Ask the browser for the channel name.
   1189   int client_id = 0;
   1190   IPC::ChannelHandle channel_handle;
   1191   gpu::GPUInfo gpu_info;
   1192   if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch,
   1193                                                &client_id,
   1194                                                &channel_handle,
   1195                                                &gpu_info)) ||
   1196 #if defined(OS_POSIX)
   1197       channel_handle.socket.fd == -1 ||
   1198 #endif
   1199       channel_handle.name.empty()) {
   1200     // Otherwise cancel the connection.
   1201     return NULL;
   1202   }
   1203 
   1204   GetContentClient()->SetGpuInfo(gpu_info);
   1205 
   1206   // Cache some variables that are needed on the compositor thread for our
   1207   // implementation of GpuChannelHostFactory.
   1208   io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy();
   1209   shutdown_event_ = ChildProcess::current()->GetShutDownEvent();
   1210 
   1211   gpu_channel_ = GpuChannelHost::Create(
   1212       this, 0, gpu_info, channel_handle);
   1213   return gpu_channel_.get();
   1214 }
   1215 
   1216 blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
   1217     blink::WebMediaStreamCenterClient* client) {
   1218 #if defined(OS_ANDROID)
   1219   if (CommandLine::ForCurrentProcess()->HasSwitch(
   1220       switches::kDisableWebRTC))
   1221     return NULL;
   1222 #endif
   1223 
   1224 #if defined(ENABLE_WEBRTC)
   1225   if (!media_stream_center_) {
   1226     media_stream_center_ = GetContentClient()->renderer()
   1227         ->OverrideCreateWebMediaStreamCenter(client);
   1228     if (!media_stream_center_) {
   1229       scoped_ptr<MediaStreamCenter> media_stream_center(
   1230           new MediaStreamCenter(client, GetMediaStreamDependencyFactory()));
   1231       AddObserver(media_stream_center.get());
   1232       media_stream_center_ = media_stream_center.release();
   1233     }
   1234   }
   1235 #endif
   1236   return media_stream_center_;
   1237 }
   1238 
   1239 MediaStreamDependencyFactory*
   1240 RenderThreadImpl::GetMediaStreamDependencyFactory() {
   1241 #if defined(ENABLE_WEBRTC)
   1242   if (!media_stream_factory_) {
   1243     media_stream_factory_.reset(new MediaStreamDependencyFactory(
   1244         vc_manager_.get(), p2p_socket_dispatcher_.get()));
   1245   }
   1246 #endif
   1247   return media_stream_factory_.get();
   1248 }
   1249 
   1250 GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
   1251   if (!gpu_channel_.get())
   1252     return NULL;
   1253 
   1254   if (gpu_channel_->IsLost())
   1255     return NULL;
   1256 
   1257   return gpu_channel_.get();
   1258 }
   1259 
   1260 void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
   1261   EnsureWebKitInitialized();
   1262   // The call below will cause a GetPlugins call with refresh=true, but at this
   1263   // point we already know that the browser has refreshed its list, so disable
   1264   // refresh temporarily to prevent each renderer process causing the list to be
   1265   // regenerated.
   1266   webkit_platform_support_->set_plugin_refresh_allowed(false);
   1267   blink::resetPluginCache(reload_pages);
   1268   webkit_platform_support_->set_plugin_refresh_allowed(true);
   1269 
   1270   FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
   1271 }
   1272 
   1273 void RenderThreadImpl::OnNetworkStateChanged(bool online) {
   1274   EnsureWebKitInitialized();
   1275   WebNetworkStateNotifier::setOnLine(online);
   1276 }
   1277 
   1278 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
   1279   GetContentClient()->SetActiveURL(data);
   1280   CHECK(false);
   1281 }
   1282 
   1283 void RenderThreadImpl::OnSetRendererProcessID(base::ProcessId process_id) {
   1284   renderer_process_id_ = process_id;
   1285 }
   1286 
   1287 #if defined(OS_ANDROID)
   1288 void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
   1289   ToggleWebKitSharedTimer(suspend);
   1290 }
   1291 #endif
   1292 
   1293 #if defined(OS_MACOSX)
   1294 void RenderThreadImpl::OnUpdateScrollbarTheme(float initial_button_delay,
   1295                                               float autoscroll_button_delay,
   1296                                               bool jump_on_track_click,
   1297                                               bool redraw) {
   1298   blink::WebScrollbarTheme::updateScrollbars(initial_button_delay,
   1299                                              autoscroll_button_delay,
   1300                                              jump_on_track_click,
   1301                                              redraw);
   1302 }
   1303 #endif
   1304 
   1305 void RenderThreadImpl::OnMemoryPressure(
   1306     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
   1307   base::allocator::ReleaseFreeMemory();
   1308 
   1309   if (memory_pressure_level ==
   1310       base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL) {
   1311     // Trigger full v8 garbage collection on critical memory notification.
   1312     v8::V8::LowMemoryNotification();
   1313     // Clear the image cache.
   1314     blink::WebImageCache::clear();
   1315     // Purge Skia font cache, by setting it to 0 and then again to the previous
   1316     // limit.
   1317     size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0);
   1318     SkGraphics::SetFontCacheLimit(font_cache_limit);
   1319   } else {
   1320     // Otherwise trigger a couple of v8 GCs using IdleNotification.
   1321     if (!v8::V8::IdleNotification())
   1322       v8::V8::IdleNotification();
   1323   }
   1324 }
   1325 
   1326 scoped_refptr<base::MessageLoopProxy>
   1327 RenderThreadImpl::GetFileThreadMessageLoopProxy() {
   1328   DCHECK(message_loop() == base::MessageLoop::current());
   1329   if (!file_thread_) {
   1330     file_thread_.reset(new base::Thread("Renderer::FILE"));
   1331     file_thread_->Start();
   1332   }
   1333   return file_thread_->message_loop_proxy();
   1334 }
   1335 
   1336 scoped_refptr<base::MessageLoopProxy>
   1337 RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
   1338   DCHECK(message_loop() == base::MessageLoop::current());
   1339   if (!media_thread_) {
   1340     media_thread_.reset(new base::Thread("Media"));
   1341     media_thread_->Start();
   1342 
   1343 #if defined(OS_ANDROID)
   1344     renderer_demuxer_ = new RendererDemuxerAndroid();
   1345     AddFilter(renderer_demuxer_.get());
   1346 #endif
   1347   }
   1348   return media_thread_->message_loop_proxy();
   1349 }
   1350 
   1351 void RenderThreadImpl::SetFlingCurveParameters(
   1352     const std::vector<float>& new_touchpad,
   1353     const std::vector<float>& new_touchscreen) {
   1354   webkit_platform_support_->SetFlingCurveParameters(new_touchpad,
   1355                                                     new_touchscreen);
   1356 
   1357 }
   1358 
   1359 void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
   1360   if (!gamepad_shared_memory_reader_)
   1361     gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader);
   1362   gamepad_shared_memory_reader_->SampleGamepads(*data);
   1363 }
   1364 
   1365 base::ProcessId RenderThreadImpl::renderer_process_id() const {
   1366   return renderer_process_id_;
   1367 }
   1368 
   1369 }  // namespace content
   1370