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