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