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