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