render_thread_impl.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/render_thread_impl.h"
6
7#include <algorithm>
8#include <limits>
9#include <map>
10#include <vector>
11
12#include "base/allocator/allocator_extension.h"
13#include "base/command_line.h"
14#include "base/debug/trace_event.h"
15#include "base/lazy_instance.h"
16#include "base/logging.h"
17#include "base/memory/discardable_memory.h"
18#include "base/memory/shared_memory.h"
19#include "base/metrics/field_trial.h"
20#include "base/metrics/histogram.h"
21#include "base/metrics/stats_table.h"
22#include "base/path_service.h"
23#include "base/strings/string16.h"
24#include "base/strings/string_number_conversions.h"
25#include "base/strings/string_tokenizer.h"
26#include "base/strings/utf_string_conversions.h"
27#include "base/threading/thread_local.h"
28#include "base/threading/thread_restrictions.h"
29#include "base/values.h"
30#include "cc/base/switches.h"
31#include "cc/resources/raster_worker_pool.h"
32#include "content/child/appcache/appcache_dispatcher.h"
33#include "content/child/appcache/appcache_frontend_impl.h"
34#include "content/child/child_histogram_message_filter.h"
35#include "content/child/content_child_helpers.h"
36#include "content/child/db_message_filter.h"
37#include "content/child/indexed_db/indexed_db_dispatcher.h"
38#include "content/child/indexed_db/indexed_db_message_filter.h"
39#include "content/child/npapi/npobject_util.h"
40#include "content/child/plugin_messages.h"
41#include "content/child/resource_dispatcher.h"
42#include "content/child/runtime_features.h"
43#include "content/child/thread_safe_sender.h"
44#include "content/child/web_database_observer_impl.h"
45#include "content/child/worker_task_runner.h"
46#include "content/common/child_process_messages.h"
47#include "content/common/content_constants_internal.h"
48#include "content/common/database_messages.h"
49#include "content/common/dom_storage/dom_storage_messages.h"
50#include "content/common/frame_messages.h"
51#include "content/common/gpu/client/context_provider_command_buffer.h"
52#include "content/common/gpu/client/gpu_channel_host.h"
53#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
54#include "content/common/gpu/gpu_messages.h"
55#include "content/common/gpu/gpu_process_launch_causes.h"
56#include "content/common/render_frame_setup.mojom.h"
57#include "content/common/resource_messages.h"
58#include "content/common/view_messages.h"
59#include "content/common/worker_messages.h"
60#include "content/public/common/content_constants.h"
61#include "content/public/common/content_paths.h"
62#include "content/public/common/content_switches.h"
63#include "content/public/common/renderer_preferences.h"
64#include "content/public/common/url_constants.h"
65#include "content/public/renderer/content_renderer_client.h"
66#include "content/public/renderer/render_process_observer.h"
67#include "content/public/renderer/render_view_visitor.h"
68#include "content/renderer/compositor_bindings/web_external_bitmap_impl.h"
69#include "content/renderer/compositor_bindings/web_layer_impl.h"
70#include "content/renderer/devtools/devtools_agent_filter.h"
71#include "content/renderer/dom_storage/dom_storage_dispatcher.h"
72#include "content/renderer/dom_storage/webstoragearea_impl.h"
73#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
74#include "content/renderer/gamepad_shared_memory_reader.h"
75#include "content/renderer/gpu/compositor_output_surface.h"
76#include "content/renderer/gpu/gpu_benchmarking_extension.h"
77#include "content/renderer/input/input_event_filter.h"
78#include "content/renderer/input/input_handler_manager.h"
79#include "content/renderer/media/aec_dump_message_filter.h"
80#include "content/renderer/media/audio_input_message_filter.h"
81#include "content/renderer/media/audio_message_filter.h"
82#include "content/renderer/media/audio_renderer_mixer_manager.h"
83#include "content/renderer/media/media_stream_center.h"
84#include "content/renderer/media/midi_message_filter.h"
85#include "content/renderer/media/peer_connection_tracker.h"
86#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
87#include "content/renderer/media/rtc_peer_connection_handler.h"
88#include "content/renderer/media/video_capture_impl_manager.h"
89#include "content/renderer/media/video_capture_message_filter.h"
90#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
91#include "content/renderer/media/webrtc_identity_service.h"
92#include "content/renderer/net_info_helper.h"
93#include "content/renderer/p2p/socket_dispatcher.h"
94#include "content/renderer/render_frame_proxy.h"
95#include "content/renderer/render_process_impl.h"
96#include "content/renderer/render_view_impl.h"
97#include "content/renderer/renderer_webkitplatformsupport_impl.h"
98#include "content/renderer/service_worker/embedded_worker_context_message_filter.h"
99#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
100#include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
101#include "grit/content_resources.h"
102#include "ipc/ipc_channel_handle.h"
103#include "ipc/ipc_forwarding_message_filter.h"
104#include "ipc/ipc_platform_file.h"
105#include "media/base/audio_hardware_config.h"
106#include "media/base/media.h"
107#include "media/filters/gpu_video_accelerator_factories.h"
108#include "mojo/common/common_type_converters.h"
109#include "net/base/net_errors.h"
110#include "net/base/net_util.h"
111#include "skia/ext/event_tracer_impl.h"
112#include "third_party/WebKit/public/platform/WebString.h"
113#include "third_party/WebKit/public/web/WebColorName.h"
114#include "third_party/WebKit/public/web/WebDatabase.h"
115#include "third_party/WebKit/public/web/WebDocument.h"
116#include "third_party/WebKit/public/web/WebFrame.h"
117#include "third_party/WebKit/public/web/WebImageCache.h"
118#include "third_party/WebKit/public/web/WebKit.h"
119#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
120#include "third_party/WebKit/public/web/WebPopupMenu.h"
121#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
122#include "third_party/WebKit/public/web/WebScriptController.h"
123#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
124#include "third_party/WebKit/public/web/WebView.h"
125#include "third_party/skia/include/core/SkGraphics.h"
126#include "ui/base/layout.h"
127#include "ui/base/ui_base_switches.h"
128#include "v8/include/v8.h"
129
130#if defined(OS_ANDROID)
131#include <cpu-features.h>
132#include "content/renderer/android/synchronous_compositor_factory.h"
133#include "content/renderer/media/android/renderer_demuxer_android.h"
134#endif
135
136#if defined(OS_MACOSX)
137#include "content/renderer/webscrollbarbehavior_impl_mac.h"
138#endif
139
140#if defined(OS_POSIX)
141#include "ipc/ipc_channel_posix.h"
142#endif
143
144#if defined(OS_WIN)
145#include <windows.h>
146#include <objbase.h>
147#else
148// TODO(port)
149#include "content/child/npapi/np_channel_base.h"
150#endif
151
152#if defined(ENABLE_PLUGINS)
153#include "content/renderer/npapi/plugin_channel_host.h"
154#endif
155
156using base::ThreadRestrictions;
157using blink::WebDocument;
158using blink::WebFrame;
159using blink::WebNetworkStateNotifier;
160using blink::WebRuntimeFeatures;
161using blink::WebScriptController;
162using blink::WebSecurityPolicy;
163using blink::WebString;
164using blink::WebView;
165
166namespace content {
167
168namespace {
169
170const int64 kInitialIdleHandlerDelayMs = 1000;
171const int64 kShortIdleHandlerDelayMs = 1000;
172const int64 kLongIdleHandlerDelayMs = 30*1000;
173const int kIdleCPUUsageThresholdInPercents = 3;
174const int kMinRasterThreads = 1;
175const int kMaxRasterThreads = 64;
176
177// Maximum allocation size allowed for image scaling filters that
178// require pre-scaling. Skia will fallback to a filter that doesn't
179// require pre-scaling if the default filter would require an
180// allocation that exceeds this limit.
181const size_t kImageCacheSingleAllocationByteLimit = 64 * 1024 * 1024;
182
183// Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
184// incorrectly from the wrong thread.
185base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> >
186    lazy_tls = LAZY_INSTANCE_INITIALIZER;
187
188class RenderViewZoomer : public RenderViewVisitor {
189 public:
190  RenderViewZoomer(const std::string& scheme,
191                   const std::string& host,
192                   double zoom_level) : scheme_(scheme),
193                                        host_(host),
194                                        zoom_level_(zoom_level) {
195  }
196
197  virtual bool Visit(RenderView* render_view) OVERRIDE {
198    WebView* webview = render_view->GetWebView();
199    WebDocument document = webview->mainFrame()->document();
200
201    // Don't set zoom level for full-page plugin since they don't use the same
202    // zoom settings.
203    if (document.isPluginDocument())
204      return true;
205    GURL url(document.url());
206    // Empty scheme works as wildcard that matches any scheme,
207    if ((net::GetHostOrSpecFromURL(url) == host_) &&
208        (scheme_.empty() || scheme_ == url.scheme()) &&
209        !static_cast<RenderViewImpl*>(render_view)
210             ->uses_temporary_zoom_level()) {
211      webview->hidePopups();
212      webview->setZoomLevel(zoom_level_);
213    }
214    return true;
215  }
216
217 private:
218  const std::string scheme_;
219  const std::string host_;
220  const double zoom_level_;
221
222  DISALLOW_COPY_AND_ASSIGN(RenderViewZoomer);
223};
224
225std::string HostToCustomHistogramSuffix(const std::string& host) {
226  if (host == "mail.google.com")
227    return ".gmail";
228  if (host == "docs.google.com" || host == "drive.google.com")
229    return ".docs";
230  if (host == "plus.google.com")
231    return ".plus";
232  return std::string();
233}
234
235void* CreateHistogram(
236    const char *name, int min, int max, size_t buckets) {
237  if (min <= 0)
238    min = 1;
239  std::string histogram_name;
240  RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
241  if (render_thread_impl) {  // Can be null in tests.
242    histogram_name = render_thread_impl->
243        histogram_customizer()->ConvertToCustomHistogramName(name);
244  } else {
245    histogram_name = std::string(name);
246  }
247  base::HistogramBase* histogram = base::Histogram::FactoryGet(
248      histogram_name, min, max, buckets,
249      base::Histogram::kUmaTargetedHistogramFlag);
250  return histogram;
251}
252
253void AddHistogramSample(void* hist, int sample) {
254  base::Histogram* histogram = static_cast<base::Histogram*>(hist);
255  histogram->Add(sample);
256}
257
258scoped_ptr<base::SharedMemory> AllocateSharedMemoryFunction(size_t size) {
259  return RenderThreadImpl::Get()->HostAllocateSharedMemoryBuffer(size);
260}
261
262void EnableBlinkPlatformLogChannels(const std::string& channels) {
263  if (channels.empty())
264    return;
265  base::StringTokenizer t(channels, ", ");
266  while (t.GetNext())
267    blink::enableLogChannel(t.token().c_str());
268}
269
270void NotifyTimezoneChangeOnThisThread() {
271  v8::Isolate* isolate = v8::Isolate::GetCurrent();
272  if (!isolate)
273    return;
274  v8::Date::DateTimeConfigurationChangeNotification(isolate);
275}
276
277class RenderFrameSetupImpl : public mojo::InterfaceImpl<RenderFrameSetup> {
278 public:
279  virtual void GetServiceProviderForFrame(
280      int32_t frame_routing_id,
281      mojo::InterfaceRequest<mojo::ServiceProvider> request) OVERRIDE {
282    RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_routing_id);
283    // We can receive a GetServiceProviderForFrame message for a frame not yet
284    // created due to a race between the message and a ViewMsg_New IPC that
285    // triggers creation of the RenderFrame we want.
286    if (!frame) {
287      RenderThreadImpl::current()->RegisterPendingRenderFrameConnect(
288          frame_routing_id, request.PassMessagePipe());
289      return;
290    }
291
292    frame->BindServiceRegistry(request.PassMessagePipe());
293  }
294};
295
296void CreateRenderFrameSetup(mojo::InterfaceRequest<RenderFrameSetup> request) {
297  mojo::BindToRequest(new RenderFrameSetupImpl(), &request);
298}
299
300bool ShouldUseMojoChannel() {
301  return CommandLine::ForCurrentProcess()->HasSwitch(
302      switches::kEnableRendererMojoChannel);
303}
304
305}  // namespace
306
307// For measuring memory usage after each task. Behind a command line flag.
308class MemoryObserver : public base::MessageLoop::TaskObserver {
309 public:
310  MemoryObserver() {}
311  virtual ~MemoryObserver() {}
312
313  virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
314  }
315
316  virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
317    HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
318  }
319
320 private:
321  DISALLOW_COPY_AND_ASSIGN(MemoryObserver);
322};
323
324RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() {
325  custom_histograms_.insert("V8.MemoryExternalFragmentationTotal");
326  custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted");
327  custom_histograms_.insert("V8.MemoryHeapSampleTotalUsed");
328}
329
330RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {}
331
332void RenderThreadImpl::HistogramCustomizer::RenderViewNavigatedToHost(
333    const std::string& host, size_t view_count) {
334  if (CommandLine::ForCurrentProcess()->HasSwitch(
335      switches::kDisableHistogramCustomizer)) {
336    return;
337  }
338  // Check if all RenderViews are displaying a page from the same host. If there
339  // is only one RenderView, the common host is this view's host. If there are
340  // many, check if this one shares the common host of the other
341  // RenderViews. It's ok to not detect some cases where the RenderViews share a
342  // common host. This information is only used for producing custom histograms.
343  if (view_count == 1)
344    SetCommonHost(host);
345  else if (host != common_host_)
346    SetCommonHost(std::string());
347}
348
349std::string RenderThreadImpl::HistogramCustomizer::ConvertToCustomHistogramName(
350    const char* histogram_name) const {
351  std::string name(histogram_name);
352  if (!common_host_histogram_suffix_.empty() &&
353      custom_histograms_.find(name) != custom_histograms_.end())
354    name += common_host_histogram_suffix_;
355  return name;
356}
357
358void RenderThreadImpl::HistogramCustomizer::SetCommonHost(
359    const std::string& host) {
360  if (host != common_host_) {
361    common_host_ = host;
362    common_host_histogram_suffix_ = HostToCustomHistogramSuffix(host);
363    blink::mainThreadIsolate()->SetCreateHistogramFunction(CreateHistogram);
364  }
365}
366
367RenderThreadImpl* RenderThreadImpl::current() {
368  return lazy_tls.Pointer()->Get();
369}
370
371// When we run plugins in process, we actually run them on the render thread,
372// which means that we need to make the render thread pump UI events.
373RenderThreadImpl::RenderThreadImpl()
374    : ChildThread(Options(ShouldUseMojoChannel())) {
375  Init();
376}
377
378RenderThreadImpl::RenderThreadImpl(const std::string& channel_name)
379    : ChildThread(Options(channel_name, ShouldUseMojoChannel())) {
380  Init();
381}
382
383void RenderThreadImpl::Init() {
384  TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, "");
385
386  base::debug::TraceLog::GetInstance()->SetThreadSortIndex(
387      base::PlatformThread::CurrentId(),
388      kTraceEventRendererMainThreadSortIndex);
389
390#if defined(OS_MACOSX) || defined(OS_ANDROID)
391  // On Mac and Android, the select popups are rendered by the browser.
392  blink::WebView::setUseExternalPopupMenus(true);
393#endif
394
395  lazy_tls.Pointer()->Set(this);
396
397  // Register this object as the main thread.
398  ChildProcess::current()->set_main_thread(this);
399
400  // In single process the single process is all there is.
401  suspend_webkit_shared_timer_ = true;
402  notify_webkit_of_modal_loop_ = true;
403  webkit_shared_timer_suspended_ = false;
404  widget_count_ = 0;
405  hidden_widget_count_ = 0;
406  idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs;
407  idle_notifications_to_skip_ = 0;
408  layout_test_mode_ = false;
409
410  appcache_dispatcher_.reset(
411      new AppCacheDispatcher(Get(), new AppCacheFrontendImpl()));
412  dom_storage_dispatcher_.reset(new DomStorageDispatcher());
413  main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
414      thread_safe_sender()));
415  embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher());
416
417  media_stream_center_ = NULL;
418
419  db_message_filter_ = new DBMessageFilter();
420  AddFilter(db_message_filter_.get());
421
422  vc_manager_.reset(new VideoCaptureImplManager());
423  AddFilter(vc_manager_->video_capture_message_filter());
424
425#if defined(ENABLE_WEBRTC)
426  peer_connection_tracker_.reset(new PeerConnectionTracker());
427  AddObserver(peer_connection_tracker_.get());
428
429  p2p_socket_dispatcher_ =
430      new P2PSocketDispatcher(GetIOMessageLoopProxy().get());
431  AddFilter(p2p_socket_dispatcher_.get());
432
433  webrtc_identity_service_.reset(new WebRTCIdentityService());
434
435  aec_dump_message_filter_ =
436      new AecDumpMessageFilter(GetIOMessageLoopProxy(),
437                               message_loop()->message_loop_proxy());
438  AddFilter(aec_dump_message_filter_.get());
439
440  peer_connection_factory_.reset(new PeerConnectionDependencyFactory(
441      p2p_socket_dispatcher_.get()));
442#endif  // defined(ENABLE_WEBRTC)
443
444  audio_input_message_filter_ =
445      new AudioInputMessageFilter(GetIOMessageLoopProxy());
446  AddFilter(audio_input_message_filter_.get());
447
448  audio_message_filter_ = new AudioMessageFilter(GetIOMessageLoopProxy());
449  AddFilter(audio_message_filter_.get());
450
451  midi_message_filter_ = new MidiMessageFilter(GetIOMessageLoopProxy());
452  AddFilter(midi_message_filter_.get());
453
454  AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter());
455
456  AddFilter((new EmbeddedWorkerContextMessageFilter())->GetFilter());
457
458  GetContentClient()->renderer()->RenderThreadStarted();
459
460  InitSkiaEventTracer();
461
462  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
463  if (command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking))
464      RegisterExtension(GpuBenchmarkingExtension::Get());
465
466  is_impl_side_painting_enabled_ =
467      command_line.HasSwitch(switches::kEnableImplSidePainting);
468  WebLayerImpl::SetImplSidePaintingEnabled(is_impl_side_painting_enabled_);
469
470  is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy) &&
471                          !command_line.HasSwitch(switches::kDisableZeroCopy);
472
473  is_one_copy_enabled_ = command_line.HasSwitch(switches::kEnableOneCopy);
474
475  if (command_line.HasSwitch(switches::kDisableLCDText)) {
476    is_lcd_text_enabled_ = false;
477  } else if (command_line.HasSwitch(switches::kEnableLCDText)) {
478    is_lcd_text_enabled_ = true;
479  } else {
480#if defined(OS_ANDROID)
481    is_lcd_text_enabled_ = false;
482#else
483    is_lcd_text_enabled_ = true;
484#endif
485  }
486
487  is_gpu_rasterization_enabled_ =
488      command_line.HasSwitch(switches::kEnableGpuRasterization);
489  is_gpu_rasterization_forced_ =
490      command_line.HasSwitch(switches::kForceGpuRasterization);
491
492  if (command_line.HasSwitch(switches::kDisableDistanceFieldText)) {
493    is_distance_field_text_enabled_ = false;
494  } else if (command_line.HasSwitch(switches::kEnableDistanceFieldText)) {
495    is_distance_field_text_enabled_ = true;
496  } else {
497    is_distance_field_text_enabled_ = false;
498  }
499
500  is_low_res_tiling_enabled_ = true;
501  if (command_line.HasSwitch(switches::kDisableLowResTiling) &&
502      !command_line.HasSwitch(switches::kEnableLowResTiling)) {
503    is_low_res_tiling_enabled_ = false;
504  }
505
506  // Note that under Linux, the media library will normally already have
507  // been initialized by the Zygote before this instance became a Renderer.
508  base::FilePath media_path;
509  PathService::Get(DIR_MEDIA_LIBS, &media_path);
510  if (!media_path.empty())
511    media::InitializeMediaLibrary(media_path);
512
513  memory_pressure_listener_.reset(new base::MemoryPressureListener(
514      base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this))));
515
516  std::vector<base::DiscardableMemoryType> supported_types;
517  base::DiscardableMemory::GetSupportedTypes(&supported_types);
518  DCHECK(!supported_types.empty());
519
520  // The default preferred type is always the first one in list.
521  base::DiscardableMemoryType type = supported_types[0];
522
523  if (command_line.HasSwitch(switches::kUseDiscardableMemory)) {
524    std::string requested_type_name = command_line.GetSwitchValueASCII(
525        switches::kUseDiscardableMemory);
526    base::DiscardableMemoryType requested_type =
527        base::DiscardableMemory::GetNamedType(requested_type_name);
528    if (std::find(supported_types.begin(),
529                  supported_types.end(),
530                  requested_type) != supported_types.end()) {
531      type = requested_type;
532    } else {
533      LOG(ERROR) << "Requested discardable memory type is not supported.";
534    }
535  }
536
537  base::DiscardableMemory::SetPreferredType(type);
538
539  // Allow discardable memory implementations to register memory pressure
540  // listeners.
541  base::DiscardableMemory::RegisterMemoryPressureListeners();
542
543  // AllocateGpuMemoryBuffer must be used exclusively on one thread but
544  // it doesn't have to be the same thread RenderThreadImpl is created on.
545  allocate_gpu_memory_buffer_thread_checker_.DetachFromThread();
546
547  if (command_line.HasSwitch(switches::kNumRasterThreads)) {
548    int num_raster_threads;
549    std::string string_value =
550        command_line.GetSwitchValueASCII(switches::kNumRasterThreads);
551    if (base::StringToInt(string_value, &num_raster_threads) &&
552        num_raster_threads >= kMinRasterThreads &&
553        num_raster_threads <= kMaxRasterThreads) {
554      cc::RasterWorkerPool::SetNumRasterThreads(num_raster_threads);
555    } else {
556      LOG(WARNING) << "Failed to parse switch " <<
557                      switches::kNumRasterThreads  << ": " << string_value;
558    }
559  }
560
561  service_registry()->AddService<RenderFrameSetup>(
562      base::Bind(CreateRenderFrameSetup));
563
564  TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, "");
565}
566
567RenderThreadImpl::~RenderThreadImpl() {
568  for (std::map<int, mojo::MessagePipeHandle>::iterator it =
569           pending_render_frame_connects_.begin();
570       it != pending_render_frame_connects_.end();
571       ++it) {
572    mojo::CloseRaw(it->second);
573  }
574}
575
576void RenderThreadImpl::Shutdown() {
577  FOR_EACH_OBSERVER(
578      RenderProcessObserver, observers_, OnRenderProcessShutdown());
579
580  ChildThread::Shutdown();
581
582  if (memory_observer_) {
583    message_loop()->RemoveTaskObserver(memory_observer_.get());
584    memory_observer_.reset();
585  }
586
587  // Wait for all databases to be closed.
588  if (webkit_platform_support_) {
589    // WaitForAllDatabasesToClose might run a nested message loop. To avoid
590    // processing timer events while we're already in the process of shutting
591    // down blink, put a ScopePageLoadDeferrer on the stack.
592    WebView::willEnterModalLoop();
593    webkit_platform_support_->web_database_observer_impl()->
594        WaitForAllDatabasesToClose();
595    WebView::didExitModalLoop();
596  }
597
598  // Shutdown in reverse of the initialization order.
599  if (devtools_agent_message_filter_.get()) {
600    RemoveFilter(devtools_agent_message_filter_.get());
601    devtools_agent_message_filter_ = NULL;
602  }
603
604  RemoveFilter(audio_input_message_filter_.get());
605  audio_input_message_filter_ = NULL;
606
607  RemoveFilter(audio_message_filter_.get());
608  audio_message_filter_ = NULL;
609
610#if defined(ENABLE_WEBRTC)
611  RTCPeerConnectionHandler::DestructAllHandlers();
612
613  peer_connection_factory_.reset();
614#endif
615  RemoveFilter(vc_manager_->video_capture_message_filter());
616  vc_manager_.reset();
617
618  RemoveFilter(db_message_filter_.get());
619  db_message_filter_ = NULL;
620
621  // Shutdown the file thread if it's running.
622  if (file_thread_)
623    file_thread_->Stop();
624
625  if (compositor_output_surface_filter_.get()) {
626    RemoveFilter(compositor_output_surface_filter_.get());
627    compositor_output_surface_filter_ = NULL;
628  }
629
630  media_thread_.reset();
631  compositor_thread_.reset();
632  input_handler_manager_.reset();
633  if (input_event_filter_.get()) {
634    RemoveFilter(input_event_filter_.get());
635    input_event_filter_ = NULL;
636  }
637
638  // RemoveEmbeddedWorkerRoute may be called while deleting
639  // EmbeddedWorkerDispatcher. So it must be deleted before deleting
640  // RenderThreadImpl.
641  embedded_worker_dispatcher_.reset();
642
643  // Ramp down IDB before we ramp down WebKit (and V8), since IDB classes might
644  // hold pointers to V8 objects (e.g., via pending requests).
645  main_thread_indexed_db_dispatcher_.reset();
646
647  if (webkit_platform_support_)
648    blink::shutdown();
649
650  lazy_tls.Pointer()->Set(NULL);
651
652  // TODO(port)
653#if defined(OS_WIN)
654  // Clean up plugin channels before this thread goes away.
655  NPChannelBase::CleanupChannels();
656#endif
657}
658
659bool RenderThreadImpl::Send(IPC::Message* msg) {
660  // Certain synchronous messages cannot always be processed synchronously by
661  // the browser, e.g., putting up UI and waiting for the user. This could cause
662  // a complete hang of Chrome if a windowed plug-in is trying to communicate
663  // with the renderer thread since the browser's UI thread could be stuck
664  // (within a Windows API call) trying to synchronously communicate with the
665  // plug-in.  The remedy is to pump messages on this thread while the browser
666  // is processing this request. This creates an opportunity for re-entrancy
667  // into WebKit, so we need to take care to disable callbacks, timers, and
668  // pending network loads that could trigger such callbacks.
669  bool pumping_events = false;
670  if (msg->is_sync()) {
671    if (msg->is_caller_pumping_messages()) {
672      pumping_events = true;
673    }
674  }
675
676  bool suspend_webkit_shared_timer = true;  // default value
677  std::swap(suspend_webkit_shared_timer, suspend_webkit_shared_timer_);
678
679  bool notify_webkit_of_modal_loop = true;  // default value
680  std::swap(notify_webkit_of_modal_loop, notify_webkit_of_modal_loop_);
681
682#if defined(ENABLE_PLUGINS)
683  int render_view_id = MSG_ROUTING_NONE;
684#endif
685
686  if (pumping_events) {
687    if (suspend_webkit_shared_timer)
688      webkit_platform_support_->SuspendSharedTimer();
689
690    if (notify_webkit_of_modal_loop)
691      WebView::willEnterModalLoop();
692#if defined(ENABLE_PLUGINS)
693    RenderViewImpl* render_view =
694        RenderViewImpl::FromRoutingID(msg->routing_id());
695    if (render_view) {
696      render_view_id = msg->routing_id();
697      PluginChannelHost::Broadcast(
698          new PluginMsg_SignalModalDialogEvent(render_view_id));
699    }
700#endif
701  }
702
703  bool rv = ChildThread::Send(msg);
704
705  if (pumping_events) {
706#if defined(ENABLE_PLUGINS)
707    if (render_view_id != MSG_ROUTING_NONE) {
708      PluginChannelHost::Broadcast(
709          new PluginMsg_ResetModalDialogEvent(render_view_id));
710    }
711#endif
712
713    if (notify_webkit_of_modal_loop)
714      WebView::didExitModalLoop();
715
716    if (suspend_webkit_shared_timer)
717      webkit_platform_support_->ResumeSharedTimer();
718  }
719
720  return rv;
721}
722
723base::MessageLoop* RenderThreadImpl::GetMessageLoop() {
724  return message_loop();
725}
726
727IPC::SyncChannel* RenderThreadImpl::GetChannel() {
728  return channel();
729}
730
731std::string RenderThreadImpl::GetLocale() {
732  // The browser process should have passed the locale to the renderer via the
733  // --lang command line flag.
734  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
735  const std::string& lang =
736      parsed_command_line.GetSwitchValueASCII(switches::kLang);
737  DCHECK(!lang.empty());
738  return lang;
739}
740
741IPC::SyncMessageFilter* RenderThreadImpl::GetSyncMessageFilter() {
742  return sync_message_filter();
743}
744
745scoped_refptr<base::MessageLoopProxy>
746    RenderThreadImpl::GetIOMessageLoopProxy() {
747  return ChildProcess::current()->io_message_loop_proxy();
748}
749
750void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) {
751  ChildThread::GetRouter()->AddRoute(routing_id, listener);
752  std::map<int, mojo::MessagePipeHandle>::iterator it =
753      pending_render_frame_connects_.find(routing_id);
754  if (it == pending_render_frame_connects_.end())
755    return;
756
757  RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(routing_id);
758  if (!frame)
759    return;
760
761  mojo::ScopedMessagePipeHandle handle(it->second);
762  pending_render_frame_connects_.erase(it);
763  frame->BindServiceRegistry(handle.Pass());
764}
765
766void RenderThreadImpl::RemoveRoute(int32 routing_id) {
767  ChildThread::GetRouter()->RemoveRoute(routing_id);
768}
769
770void RenderThreadImpl::AddEmbeddedWorkerRoute(int32 routing_id,
771                                              IPC::Listener* listener) {
772  AddRoute(routing_id, listener);
773  if (devtools_agent_message_filter_.get()) {
774    devtools_agent_message_filter_->AddEmbeddedWorkerRouteOnMainThread(
775        routing_id);
776  }
777}
778
779void RenderThreadImpl::RemoveEmbeddedWorkerRoute(int32 routing_id) {
780  RemoveRoute(routing_id);
781  if (devtools_agent_message_filter_.get()) {
782    devtools_agent_message_filter_->RemoveEmbeddedWorkerRouteOnMainThread(
783        routing_id);
784  }
785}
786
787void RenderThreadImpl::RegisterPendingRenderFrameConnect(
788    int routing_id,
789    mojo::ScopedMessagePipeHandle handle) {
790  std::pair<std::map<int, mojo::MessagePipeHandle>::iterator, bool> result =
791      pending_render_frame_connects_.insert(
792          std::make_pair(routing_id, handle.release()));
793  CHECK(result.second) << "Inserting a duplicate item.";
794}
795
796int RenderThreadImpl::GenerateRoutingID() {
797  int routing_id = MSG_ROUTING_NONE;
798  Send(new ViewHostMsg_GenerateRoutingID(&routing_id));
799  return routing_id;
800}
801
802void RenderThreadImpl::AddFilter(IPC::MessageFilter* filter) {
803  channel()->AddFilter(filter);
804}
805
806void RenderThreadImpl::RemoveFilter(IPC::MessageFilter* filter) {
807  channel()->RemoveFilter(filter);
808}
809
810void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) {
811  observers_.AddObserver(observer);
812}
813
814void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) {
815  observers_.RemoveObserver(observer);
816}
817
818void RenderThreadImpl::SetResourceDispatcherDelegate(
819    ResourceDispatcherDelegate* delegate) {
820  resource_dispatcher()->set_delegate(delegate);
821}
822
823void RenderThreadImpl::EnsureWebKitInitialized() {
824  if (webkit_platform_support_)
825    return;
826
827  webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
828  blink::initialize(webkit_platform_support_.get());
829
830  v8::Isolate* isolate = blink::mainThreadIsolate();
831
832  isolate->SetCounterFunction(base::StatsTable::FindLocation);
833  isolate->SetCreateHistogramFunction(CreateHistogram);
834  isolate->SetAddHistogramSampleFunction(AddHistogramSample);
835
836  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
837
838  bool enable = !command_line.HasSwitch(switches::kDisableThreadedCompositing);
839  if (enable) {
840#if defined(OS_ANDROID)
841    if (SynchronousCompositorFactory* factory =
842        SynchronousCompositorFactory::GetInstance())
843      compositor_message_loop_proxy_ =
844          factory->GetCompositorMessageLoop();
845#endif
846    if (!compositor_message_loop_proxy_.get()) {
847      compositor_thread_.reset(new base::Thread("Compositor"));
848      compositor_thread_->Start();
849#if defined(OS_ANDROID)
850      compositor_thread_->SetPriority(base::kThreadPriority_Display);
851#endif
852      compositor_message_loop_proxy_ =
853          compositor_thread_->message_loop_proxy();
854      compositor_message_loop_proxy_->PostTask(
855          FROM_HERE,
856          base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed),
857                     false));
858    }
859
860    InputHandlerManagerClient* input_handler_manager_client = NULL;
861#if defined(OS_ANDROID)
862    if (SynchronousCompositorFactory* factory =
863        SynchronousCompositorFactory::GetInstance()) {
864      input_handler_manager_client = factory->GetInputHandlerManagerClient();
865    }
866#endif
867    if (!input_handler_manager_client) {
868      input_event_filter_ =
869          new InputEventFilter(this, compositor_message_loop_proxy_);
870      AddFilter(input_event_filter_.get());
871      input_handler_manager_client = input_event_filter_.get();
872    }
873    input_handler_manager_.reset(
874        new InputHandlerManager(compositor_message_loop_proxy_,
875                                input_handler_manager_client));
876  }
877
878  scoped_refptr<base::MessageLoopProxy> output_surface_loop;
879  if (enable)
880    output_surface_loop = compositor_message_loop_proxy_;
881  else
882    output_surface_loop = base::MessageLoopProxy::current();
883
884  compositor_output_surface_filter_ =
885      CompositorOutputSurface::CreateFilter(output_surface_loop.get());
886  AddFilter(compositor_output_surface_filter_.get());
887
888  gamepad_shared_memory_reader_.reset(
889      new GamepadSharedMemoryReader(webkit_platform_support_.get()));
890  AddObserver(gamepad_shared_memory_reader_.get());
891
892  RenderThreadImpl::RegisterSchemes();
893
894  EnableBlinkPlatformLogChannels(
895      command_line.GetSwitchValueASCII(switches::kBlinkPlatformLogChannels));
896
897  SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
898
899  if (!media::IsMediaLibraryInitialized()) {
900    WebRuntimeFeatures::enableMediaPlayer(false);
901    WebRuntimeFeatures::enableWebAudio(false);
902  }
903
904  FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
905
906  devtools_agent_message_filter_ = new DevToolsAgentFilter();
907  AddFilter(devtools_agent_message_filter_.get());
908
909  if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
910    ScheduleIdleHandler(kLongIdleHandlerDelayMs);
911
912  SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
913
914  // Limit use of the scaled image cache to when deferred image decoding is
915  // enabled.
916  if (!command_line.HasSwitch(switches::kEnableDeferredImageDecoding) &&
917      !is_impl_side_painting_enabled_)
918    SkGraphics::SetImageCacheByteLimit(0u);
919
920  SkGraphics::SetImageCacheSingleAllocationByteLimit(
921      kImageCacheSingleAllocationByteLimit);
922
923  if (command_line.HasSwitch(switches::kMemoryMetrics)) {
924    memory_observer_.reset(new MemoryObserver());
925    message_loop()->AddTaskObserver(memory_observer_.get());
926  }
927}
928
929void RenderThreadImpl::RegisterSchemes() {
930  // swappedout: pages should not be accessible, and should also
931  // be treated as empty documents that can commit synchronously.
932  WebString swappedout_scheme(base::ASCIIToUTF16(kSwappedOutScheme));
933  WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(swappedout_scheme);
934  WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme);
935}
936
937void RenderThreadImpl::NotifyTimezoneChange() {
938  NotifyTimezoneChangeOnThisThread();
939  RenderThread::Get()->PostTaskToAllWebWorkers(
940      base::Bind(&NotifyTimezoneChangeOnThisThread));
941}
942
943void RenderThreadImpl::RecordAction(const base::UserMetricsAction& action) {
944  Send(new ViewHostMsg_UserMetricsRecordAction(action.str_));
945}
946
947void RenderThreadImpl::RecordComputedAction(const std::string& action) {
948  Send(new ViewHostMsg_UserMetricsRecordAction(action));
949}
950
951scoped_ptr<base::SharedMemory>
952    RenderThreadImpl::HostAllocateSharedMemoryBuffer(size_t size) {
953  if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
954    return scoped_ptr<base::SharedMemory>();
955
956  base::SharedMemoryHandle handle;
957  bool success;
958  IPC::Message* message =
959      new ChildProcessHostMsg_SyncAllocateSharedMemory(size, &handle);
960
961  // Allow calling this from the compositor thread.
962  if (base::MessageLoop::current() == message_loop())
963    success = ChildThread::Send(message);
964  else
965    success = sync_message_filter()->Send(message);
966
967  if (!success)
968    return scoped_ptr<base::SharedMemory>();
969
970  if (!base::SharedMemory::IsHandleValid(handle))
971    return scoped_ptr<base::SharedMemory>();
972
973  return scoped_ptr<base::SharedMemory>(new base::SharedMemory(handle, false));
974}
975
976void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
977  WebScriptController::registerExtension(extension);
978}
979
980void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) {
981  idle_notification_delay_in_ms_ = initial_delay_ms;
982  idle_timer_.Stop();
983  idle_timer_.Start(FROM_HERE,
984      base::TimeDelta::FromMilliseconds(initial_delay_ms),
985      this, &RenderThreadImpl::IdleHandler);
986}
987
988void RenderThreadImpl::IdleHandler() {
989  bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) &&
990                               GetContentClient()->renderer()->
991                                   RunIdleHandlerWhenWidgetsHidden();
992  if (run_in_foreground_tab) {
993    IdleHandlerInForegroundTab();
994    return;
995  }
996
997  base::allocator::ReleaseFreeMemory();
998
999  // Continue the idle timer if the webkit shared timer is not suspended or
1000  // something is left to do.
1001  bool continue_timer = !webkit_shared_timer_suspended_;
1002
1003  if (blink::mainThreadIsolate() &&
1004      !blink::mainThreadIsolate()->IdleNotification(1000)) {
1005    continue_timer = true;
1006  }
1007  if (!base::DiscardableMemory::ReduceMemoryUsage()) {
1008    continue_timer = true;
1009  }
1010
1011  // Schedule next invocation.
1012  // Dampen the delay using the algorithm (if delay is in seconds):
1013  //    delay = delay + 1 / (delay + 2)
1014  // Using floor(delay) has a dampening effect such as:
1015  //    1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
1016  // If the delay is in milliseconds, the above formula is equivalent to:
1017  //    delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
1018  // which is equivalent to
1019  //    delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
1020  // Note that idle_notification_delay_in_ms_ would be reset to
1021  // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden.
1022  if (continue_timer) {
1023    ScheduleIdleHandler(idle_notification_delay_in_ms_ +
1024                        1000000 / (idle_notification_delay_in_ms_ + 2000));
1025
1026  } else {
1027    idle_timer_.Stop();
1028  }
1029
1030  FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
1031}
1032
1033void RenderThreadImpl::IdleHandlerInForegroundTab() {
1034  // Increase the delay in the same way as in IdleHandler,
1035  // but make it periodic by reseting it once it is too big.
1036  int64 new_delay_ms = idle_notification_delay_in_ms_ +
1037                       1000000 / (idle_notification_delay_in_ms_ + 2000);
1038  if (new_delay_ms >= kLongIdleHandlerDelayMs)
1039    new_delay_ms = kShortIdleHandlerDelayMs;
1040
1041  if (idle_notifications_to_skip_ > 0) {
1042    idle_notifications_to_skip_--;
1043  } else  {
1044    int cpu_usage = 0;
1045    Send(new ViewHostMsg_GetCPUUsage(&cpu_usage));
1046    // Idle notification hint roughly specifies the expected duration of the
1047    // idle pause. We set it proportional to the idle timer delay.
1048    int idle_hint = static_cast<int>(new_delay_ms / 10);
1049    if (cpu_usage < kIdleCPUUsageThresholdInPercents) {
1050      base::allocator::ReleaseFreeMemory();
1051
1052      bool finished_idle_work = true;
1053      if (blink::mainThreadIsolate() &&
1054          !blink::mainThreadIsolate()->IdleNotification(idle_hint)) {
1055        finished_idle_work = false;
1056      }
1057      if (!base::DiscardableMemory::ReduceMemoryUsage())
1058        finished_idle_work = false;
1059
1060      // V8 finished collecting garbage and discardable memory system has no
1061      // more idle work left.
1062      if (finished_idle_work)
1063        new_delay_ms = kLongIdleHandlerDelayMs;
1064    }
1065  }
1066  ScheduleIdleHandler(new_delay_ms);
1067}
1068
1069int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
1070  return idle_notification_delay_in_ms_;
1071}
1072
1073void RenderThreadImpl::SetIdleNotificationDelayInMs(
1074    int64 idle_notification_delay_in_ms) {
1075  idle_notification_delay_in_ms_ = idle_notification_delay_in_ms;
1076}
1077
1078void RenderThreadImpl::UpdateHistograms(int sequence_number) {
1079  child_histogram_message_filter()->SendHistograms(sequence_number);
1080}
1081
1082int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) {
1083  return WorkerTaskRunner::Instance()->PostTaskToAllThreads(closure);
1084}
1085
1086bool RenderThreadImpl::ResolveProxy(const GURL& url, std::string* proxy_list) {
1087  bool result = false;
1088  Send(new ViewHostMsg_ResolveProxy(url, &result, proxy_list));
1089  return result;
1090}
1091
1092void RenderThreadImpl::PostponeIdleNotification() {
1093  idle_notifications_to_skip_ = 2;
1094}
1095
1096scoped_refptr<media::GpuVideoAcceleratorFactories>
1097RenderThreadImpl::GetGpuFactories() {
1098  DCHECK(IsMainThread());
1099
1100  scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
1101  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
1102  scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories;
1103  scoped_refptr<base::MessageLoopProxy> media_loop_proxy =
1104      GetMediaThreadMessageLoopProxy();
1105  if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
1106    if (!gpu_va_context_provider_ ||
1107        gpu_va_context_provider_->DestroyedOnMainThread()) {
1108      if (!gpu_channel_host) {
1109        gpu_channel_host = EstablishGpuChannelSync(
1110            CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
1111      }
1112      blink::WebGraphicsContext3D::Attributes attributes;
1113      bool lose_context_when_out_of_memory = false;
1114      gpu_va_context_provider_ = ContextProviderCommandBuffer::Create(
1115          make_scoped_ptr(
1116              WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
1117                  gpu_channel_host.get(),
1118                  attributes,
1119                  lose_context_when_out_of_memory,
1120                  GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"),
1121                  WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
1122                  NULL)),
1123          "GPU-VideoAccelerator-Offscreen");
1124    }
1125  }
1126  if (gpu_va_context_provider_) {
1127    gpu_factories = RendererGpuVideoAcceleratorFactories::Create(
1128        gpu_channel_host, media_loop_proxy, gpu_va_context_provider_);
1129  }
1130  return gpu_factories;
1131}
1132
1133scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
1134RenderThreadImpl::CreateOffscreenContext3d() {
1135  blink::WebGraphicsContext3D::Attributes attributes;
1136  attributes.shareResources = true;
1137  attributes.depth = false;
1138  attributes.stencil = false;
1139  attributes.antialias = false;
1140  attributes.noAutomaticFlushes = true;
1141  bool lose_context_when_out_of_memory = true;
1142
1143  scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
1144      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
1145  return make_scoped_ptr(
1146      WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
1147          gpu_channel_host.get(),
1148          attributes,
1149          lose_context_when_out_of_memory,
1150          GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"),
1151          WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
1152          NULL));
1153}
1154
1155scoped_refptr<webkit::gpu::ContextProviderWebContext>
1156RenderThreadImpl::SharedMainThreadContextProvider() {
1157  DCHECK(IsMainThread());
1158#if defined(OS_ANDROID)
1159  if (SynchronousCompositorFactory* factory =
1160      SynchronousCompositorFactory::GetInstance())
1161    return factory->GetSharedOffscreenContextProviderForMainThread();
1162#endif
1163
1164  if (!shared_main_thread_contexts_ ||
1165      shared_main_thread_contexts_->DestroyedOnMainThread()) {
1166    shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
1167        CreateOffscreenContext3d(), "Offscreen-MainThread");
1168  }
1169  if (shared_main_thread_contexts_ &&
1170      !shared_main_thread_contexts_->BindToCurrentThread())
1171    shared_main_thread_contexts_ = NULL;
1172  return shared_main_thread_contexts_;
1173}
1174
1175AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
1176  if (!audio_renderer_mixer_manager_) {
1177    audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager(
1178        GetAudioHardwareConfig()));
1179  }
1180
1181  return audio_renderer_mixer_manager_.get();
1182}
1183
1184media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() {
1185  if (!audio_hardware_config_) {
1186    media::AudioParameters input_params;
1187    media::AudioParameters output_params;
1188    Send(new ViewHostMsg_GetAudioHardwareConfig(
1189        &input_params, &output_params));
1190
1191    audio_hardware_config_.reset(new media::AudioHardwareConfig(
1192        input_params, output_params));
1193    audio_message_filter_->SetAudioHardwareConfig(audio_hardware_config_.get());
1194  }
1195
1196  return audio_hardware_config_.get();
1197}
1198
1199base::WaitableEvent* RenderThreadImpl::GetShutdownEvent() {
1200  return ChildProcess::current()->GetShutDownEvent();
1201}
1202
1203#if defined(OS_WIN)
1204void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
1205                                              const base::string16& str) {
1206  Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str));
1207}
1208
1209void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) {
1210  Send(new ChildProcessHostMsg_PreCacheFont(log_font));
1211}
1212
1213void RenderThreadImpl::ReleaseCachedFonts() {
1214  Send(new ChildProcessHostMsg_ReleaseCachedFonts());
1215}
1216
1217#endif  // OS_WIN
1218
1219ServiceRegistry* RenderThreadImpl::GetServiceRegistry() {
1220  return service_registry();
1221}
1222
1223bool RenderThreadImpl::IsMainThread() {
1224  return !!current();
1225}
1226
1227base::MessageLoop* RenderThreadImpl::GetMainLoop() {
1228  return message_loop();
1229}
1230
1231scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() {
1232  return io_message_loop_proxy_;
1233}
1234
1235scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory(
1236    size_t size) {
1237  return scoped_ptr<base::SharedMemory>(
1238      HostAllocateSharedMemoryBuffer(size));
1239}
1240
1241CreateCommandBufferResult RenderThreadImpl::CreateViewCommandBuffer(
1242      int32 surface_id,
1243      const GPUCreateCommandBufferConfig& init_params,
1244      int32 route_id) {
1245  TRACE_EVENT1("gpu",
1246               "RenderThreadImpl::CreateViewCommandBuffer",
1247               "surface_id",
1248               surface_id);
1249
1250  CreateCommandBufferResult result = CREATE_COMMAND_BUFFER_FAILED;
1251  IPC::Message* message = new GpuHostMsg_CreateViewCommandBuffer(
1252      surface_id,
1253      init_params,
1254      route_id,
1255      &result);
1256
1257  // Allow calling this from the compositor thread.
1258  thread_safe_sender()->Send(message);
1259
1260  return result;
1261}
1262
1263scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer(
1264    size_t width,
1265    size_t height,
1266    unsigned internalformat,
1267    unsigned usage) {
1268  DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread());
1269
1270  if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
1271    return scoped_ptr<gfx::GpuMemoryBuffer>();
1272
1273  gfx::GpuMemoryBufferHandle handle;
1274  bool success;
1275  IPC::Message* message = new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(
1276      width, height, internalformat, usage, &handle);
1277
1278  // Allow calling this from the compositor thread.
1279  if (base::MessageLoop::current() == message_loop())
1280    success = ChildThread::Send(message);
1281  else
1282    success = sync_message_filter()->Send(message);
1283
1284  if (!success)
1285    return scoped_ptr<gfx::GpuMemoryBuffer>();
1286
1287  return GpuMemoryBufferImpl::CreateFromHandle(
1288             handle, gfx::Size(width, height), internalformat)
1289      .PassAs<gfx::GpuMemoryBuffer>();
1290}
1291
1292void RenderThreadImpl::DeleteGpuMemoryBuffer(
1293    scoped_ptr<gfx::GpuMemoryBuffer> buffer) {
1294  gfx::GpuMemoryBufferHandle handle(buffer->GetHandle());
1295
1296  IPC::Message* message = new ChildProcessHostMsg_DeletedGpuMemoryBuffer(
1297      handle.type, handle.global_id);
1298
1299  // Allow calling this from the compositor thread.
1300  thread_safe_sender()->Send(message);
1301}
1302
1303void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
1304  suspend_webkit_shared_timer_ = false;
1305}
1306
1307void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
1308  notify_webkit_of_modal_loop_ = false;
1309}
1310
1311bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
1312  ObserverListBase<RenderProcessObserver>::Iterator it(observers_);
1313  RenderProcessObserver* observer;
1314  while ((observer = it.GetNext()) != NULL) {
1315    if (observer->OnControlMessageReceived(msg))
1316      return true;
1317  }
1318
1319  // Some messages are handled by delegates.
1320  if (appcache_dispatcher_->OnMessageReceived(msg) ||
1321      dom_storage_dispatcher_->OnMessageReceived(msg) ||
1322      embedded_worker_dispatcher_->OnMessageReceived(msg)) {
1323    return true;
1324  }
1325
1326  bool handled = true;
1327  IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg)
1328    IPC_MESSAGE_HANDLER(FrameMsg_NewFrame, OnCreateNewFrame)
1329    IPC_MESSAGE_HANDLER(FrameMsg_NewFrameProxy, OnCreateNewFrameProxy)
1330    IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL,
1331                        OnSetZoomLevelForCurrentURL)
1332    // TODO(port): removed from render_messages_internal.h;
1333    // is there a new non-windows message I should add here?
1334    IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
1335    IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
1336    IPC_MESSAGE_HANDLER(ViewMsg_NetworkTypeChanged, OnNetworkTypeChanged)
1337    IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData)
1338    IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateNewSharedWorker)
1339    IPC_MESSAGE_HANDLER(ViewMsg_TimezoneChange, OnUpdateTimezone)
1340#if defined(OS_ANDROID)
1341    IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended,
1342                        OnSetWebKitSharedTimersSuspended)
1343#endif
1344#if defined(OS_MACOSX)
1345    IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
1346#endif
1347    IPC_MESSAGE_UNHANDLED(handled = false)
1348  IPC_END_MESSAGE_MAP()
1349  return handled;
1350}
1351
1352void RenderThreadImpl::OnCreateNewFrame(int routing_id, int parent_routing_id) {
1353  RenderFrameImpl::CreateFrame(routing_id, parent_routing_id);
1354}
1355
1356void RenderThreadImpl::OnCreateNewFrameProxy(int routing_id,
1357                                             int parent_routing_id,
1358                                             int render_view_routing_id) {
1359  RenderFrameProxy::CreateFrameProxy(
1360      routing_id, parent_routing_id, render_view_routing_id);
1361}
1362
1363void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme,
1364                                                   const std::string& host,
1365                                                   double zoom_level) {
1366  RenderViewZoomer zoomer(scheme, host, zoom_level);
1367  RenderView::ForEach(&zoomer);
1368}
1369
1370void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
1371  EnsureWebKitInitialized();
1372  // When bringing in render_view, also bring in webkit's glue and jsbindings.
1373  RenderViewImpl::Create(params.opener_route_id,
1374                         params.window_was_created_with_opener,
1375                         params.renderer_preferences,
1376                         params.web_preferences,
1377                         params.view_id,
1378                         params.main_frame_routing_id,
1379                         params.surface_id,
1380                         params.session_storage_namespace_id,
1381                         params.frame_name,
1382                         false,
1383                         params.swapped_out,
1384                         params.proxy_routing_id,
1385                         params.hidden,
1386                         params.never_visible,
1387                         params.next_page_id,
1388                         params.screen_info);
1389}
1390
1391GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
1392    CauseForGpuLaunch cause_for_gpu_launch) {
1393  TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync");
1394
1395  if (gpu_channel_.get()) {
1396    // Do nothing if we already have a GPU channel or are already
1397    // establishing one.
1398    if (!gpu_channel_->IsLost())
1399      return gpu_channel_.get();
1400
1401    // Recreate the channel if it has been lost.
1402    gpu_channel_ = NULL;
1403  }
1404
1405  // Ask the browser for the channel name.
1406  int client_id = 0;
1407  IPC::ChannelHandle channel_handle;
1408  gpu::GPUInfo gpu_info;
1409  if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch,
1410                                               &client_id,
1411                                               &channel_handle,
1412                                               &gpu_info)) ||
1413#if defined(OS_POSIX)
1414      channel_handle.socket.fd == -1 ||
1415#endif
1416      channel_handle.name.empty()) {
1417    // Otherwise cancel the connection.
1418    return NULL;
1419  }
1420
1421  GetContentClient()->SetGpuInfo(gpu_info);
1422
1423  // Cache some variables that are needed on the compositor thread for our
1424  // implementation of GpuChannelHostFactory.
1425  io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy();
1426
1427  gpu_channel_ = GpuChannelHost::Create(
1428      this, gpu_info, channel_handle,
1429      ChildProcess::current()->GetShutDownEvent());
1430  return gpu_channel_.get();
1431}
1432
1433blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
1434    blink::WebMediaStreamCenterClient* client) {
1435#if defined(OS_ANDROID)
1436  if (CommandLine::ForCurrentProcess()->HasSwitch(
1437      switches::kDisableWebRTC))
1438    return NULL;
1439#endif
1440
1441#if defined(ENABLE_WEBRTC)
1442  if (!media_stream_center_) {
1443    media_stream_center_ = GetContentClient()->renderer()
1444        ->OverrideCreateWebMediaStreamCenter(client);
1445    if (!media_stream_center_) {
1446      scoped_ptr<MediaStreamCenter> media_stream_center(
1447          new MediaStreamCenter(client, GetPeerConnectionDependencyFactory()));
1448      AddObserver(media_stream_center.get());
1449      media_stream_center_ = media_stream_center.release();
1450    }
1451  }
1452#endif
1453  return media_stream_center_;
1454}
1455
1456PeerConnectionDependencyFactory*
1457RenderThreadImpl::GetPeerConnectionDependencyFactory() {
1458  return peer_connection_factory_.get();
1459}
1460
1461GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
1462  if (!gpu_channel_.get())
1463    return NULL;
1464
1465  if (gpu_channel_->IsLost())
1466    return NULL;
1467
1468  return gpu_channel_.get();
1469}
1470
1471void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
1472  EnsureWebKitInitialized();
1473  // The call below will cause a GetPlugins call with refresh=true, but at this
1474  // point we already know that the browser has refreshed its list, so disable
1475  // refresh temporarily to prevent each renderer process causing the list to be
1476  // regenerated.
1477  webkit_platform_support_->set_plugin_refresh_allowed(false);
1478  blink::resetPluginCache(reload_pages);
1479  webkit_platform_support_->set_plugin_refresh_allowed(true);
1480
1481  FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
1482}
1483
1484void RenderThreadImpl::OnNetworkTypeChanged(
1485    net::NetworkChangeNotifier::ConnectionType type) {
1486  EnsureWebKitInitialized();
1487  bool online = type != net::NetworkChangeNotifier::CONNECTION_NONE;
1488  WebNetworkStateNotifier::setOnLine(online);
1489  FOR_EACH_OBSERVER(
1490      RenderProcessObserver, observers_, NetworkStateChanged(online));
1491  WebNetworkStateNotifier::setWebConnectionType(
1492      NetConnectionTypeToWebConnectionType(type));
1493}
1494
1495void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
1496  GetContentClient()->SetActiveURL(data);
1497  CHECK(false);
1498}
1499
1500void RenderThreadImpl::OnUpdateTimezone() {
1501  NotifyTimezoneChange();
1502}
1503
1504#if defined(OS_ANDROID)
1505void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
1506  if (suspend_webkit_shared_timer_) {
1507    EnsureWebKitInitialized();
1508    if (suspend) {
1509      webkit_platform_support_->SuspendSharedTimer();
1510    } else {
1511      webkit_platform_support_->ResumeSharedTimer();
1512    }
1513    webkit_shared_timer_suspended_ = suspend;
1514  }
1515}
1516#endif
1517
1518#if defined(OS_MACOSX)
1519void RenderThreadImpl::OnUpdateScrollbarTheme(
1520    float initial_button_delay,
1521    float autoscroll_button_delay,
1522    bool jump_on_track_click,
1523    blink::ScrollerStyle preferred_scroller_style,
1524    bool redraw) {
1525  EnsureWebKitInitialized();
1526  static_cast<WebScrollbarBehaviorImpl*>(
1527      webkit_platform_support_->scrollbarBehavior())->set_jump_on_track_click(
1528          jump_on_track_click);
1529  blink::WebScrollbarTheme::updateScrollbars(initial_button_delay,
1530                                             autoscroll_button_delay,
1531                                             preferred_scroller_style,
1532                                             redraw);
1533}
1534#endif
1535
1536void RenderThreadImpl::OnCreateNewSharedWorker(
1537    const WorkerProcessMsg_CreateWorker_Params& params) {
1538  // EmbeddedSharedWorkerStub will self-destruct.
1539  new EmbeddedSharedWorkerStub(params.url,
1540                               params.name,
1541                               params.content_security_policy,
1542                               params.security_policy_type,
1543                               params.pause_on_start,
1544                               params.route_id);
1545}
1546
1547void RenderThreadImpl::OnMemoryPressure(
1548    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
1549  base::allocator::ReleaseFreeMemory();
1550
1551  // Trigger full v8 garbage collection on critical memory notification. This
1552  // will potentially hang the renderer for a long time, however, when we
1553  // receive a memory pressure notification, we might be about to be killed.
1554  if (webkit_platform_support_ && blink::mainThreadIsolate()) {
1555    blink::mainThreadIsolate()->LowMemoryNotification();
1556  }
1557
1558  if (memory_pressure_level ==
1559      base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL) {
1560    if (webkit_platform_support_) {
1561      // Clear the image cache. Do not call into blink if it is not initialized.
1562      blink::WebImageCache::clear();
1563    }
1564
1565    // Purge Skia font cache, by setting it to 0 and then again to the previous
1566    // limit.
1567    size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0);
1568    SkGraphics::SetFontCacheLimit(font_cache_limit);
1569  }
1570}
1571
1572scoped_refptr<base::MessageLoopProxy>
1573RenderThreadImpl::GetFileThreadMessageLoopProxy() {
1574  DCHECK(message_loop() == base::MessageLoop::current());
1575  if (!file_thread_) {
1576    file_thread_.reset(new base::Thread("Renderer::FILE"));
1577    file_thread_->Start();
1578  }
1579  return file_thread_->message_loop_proxy();
1580}
1581
1582scoped_refptr<base::MessageLoopProxy>
1583RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
1584  DCHECK(message_loop() == base::MessageLoop::current());
1585  if (!media_thread_) {
1586    media_thread_.reset(new base::Thread("Media"));
1587    media_thread_->Start();
1588
1589#if defined(OS_ANDROID)
1590    renderer_demuxer_ = new RendererDemuxerAndroid();
1591    AddFilter(renderer_demuxer_.get());
1592#endif
1593  }
1594  return media_thread_->message_loop_proxy();
1595}
1596
1597void RenderThreadImpl::SetFlingCurveParameters(
1598    const std::vector<float>& new_touchpad,
1599    const std::vector<float>& new_touchscreen) {
1600  webkit_platform_support_->SetFlingCurveParameters(new_touchpad,
1601                                                    new_touchscreen);
1602
1603}
1604
1605void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
1606  gamepad_shared_memory_reader_->SampleGamepads(*data);
1607}
1608
1609void RenderThreadImpl::SetGamepadListener(blink::WebGamepadListener* listener) {
1610  gamepad_shared_memory_reader_->SetGamepadListener(listener);
1611}
1612
1613void RenderThreadImpl::WidgetCreated() {
1614  widget_count_++;
1615}
1616
1617void RenderThreadImpl::WidgetDestroyed() {
1618  widget_count_--;
1619}
1620
1621void RenderThreadImpl::WidgetHidden() {
1622  DCHECK_LT(hidden_widget_count_, widget_count_);
1623  hidden_widget_count_++;
1624
1625  if (widget_count_ && hidden_widget_count_ == widget_count_) {
1626    if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
1627      ScheduleIdleHandler(kInitialIdleHandlerDelayMs);
1628  }
1629}
1630
1631void RenderThreadImpl::WidgetRestored() {
1632  DCHECK_GT(hidden_widget_count_, 0);
1633  hidden_widget_count_--;
1634
1635  if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) {
1636    return;
1637  }
1638
1639  ScheduleIdleHandler(kLongIdleHandlerDelayMs);
1640}
1641
1642}  // namespace content
1643