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