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