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