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