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