3975856b9b0a14cfd62120fd9ddbb8ec296a849c
[platform/framework/web/crosswalk.git] / src / content / renderer / render_thread_impl.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/render_thread_impl.h"
6
7 #include <algorithm>
8 #include <limits>
9 #include <map>
10 #include <vector>
11
12 #include "base/allocator/allocator_extension.h"
13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h"
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "base/memory/discardable_memory.h"
18 #include "base/memory/discardable_memory_emulated.h"
19 #include "base/memory/shared_memory.h"
20 #include "base/metrics/field_trial.h"
21 #include "base/metrics/histogram.h"
22 #include "base/metrics/stats_table.h"
23 #include "base/path_service.h"
24 #include "base/strings/string16.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_tokenizer.h"
27 #include "base/strings/utf_string_conversions.h"
28 #include "base/threading/thread_local.h"
29 #include "base/threading/thread_restrictions.h"
30 #include "base/values.h"
31 #include "cc/base/switches.h"
32 #include "cc/resources/raster_worker_pool.h"
33 #include "content/child/appcache/appcache_dispatcher.h"
34 #include "content/child/appcache/appcache_frontend_impl.h"
35 #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
160 using base::ThreadRestrictions;
161 using blink::WebDocument;
162 using blink::WebFrame;
163 using blink::WebNetworkStateNotifier;
164 using blink::WebRuntimeFeatures;
165 using blink::WebScriptController;
166 using blink::WebSecurityPolicy;
167 using blink::WebString;
168 using blink::WebView;
169
170 namespace content {
171
172 namespace {
173
174 const int64 kInitialIdleHandlerDelayMs = 1000;
175 const int64 kShortIdleHandlerDelayMs = 1000;
176 const int64 kLongIdleHandlerDelayMs = 30*1000;
177 const int kIdleCPUUsageThresholdInPercents = 3;
178 const int kMinRasterThreads = 1;
179 const 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.
185 const size_t kImageCacheSingleAllocationByteLimit = 64 * 1024 * 1024;
186
187 const 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.
192 base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> >
193     lazy_tls = LAZY_INSTANCE_INITIALIZER;
194
195 class 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
232 std::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
242 void* 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
260 void AddHistogramSample(void* hist, int sample) {
261   base::Histogram* histogram = static_cast<base::Histogram*>(hist);
262   histogram->Add(sample);
263 }
264
265 scoped_ptr<base::SharedMemory> AllocateSharedMemoryFunction(size_t size) {
266   return RenderThreadImpl::Get()->HostAllocateSharedMemoryBuffer(size);
267 }
268
269 void 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
277 void NotifyTimezoneChangeOnThisThread() {
278   v8::Isolate* isolate = v8::Isolate::GetCurrent();
279   if (!isolate)
280     return;
281   v8::Date::DateTimeConfigurationChangeNotification(isolate);
282 }
283
284 class 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
303 void CreateRenderFrameSetup(mojo::InterfaceRequest<RenderFrameSetup> request) {
304   mojo::BindToRequest(new RenderFrameSetupImpl(), &request);
305 }
306
307 bool ShouldUseMojoChannel() {
308   return CommandLine::ForCurrentProcess()->HasSwitch(
309       switches::kEnableRendererMojoChannel);
310 }
311
312 blink::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.
325 class 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
341 RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() {
342   custom_histograms_.insert("V8.MemoryExternalFragmentationTotal");
343   custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted");
344   custom_histograms_.insert("V8.MemoryHeapSampleTotalUsed");
345 }
346
347 RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {}
348
349 void 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
366 std::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
375 void 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
384 RenderThreadImpl* 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.
390 RenderThreadImpl::RenderThreadImpl()
391     : ChildThread(Options(ShouldUseMojoChannel())) {
392   Init();
393 }
394
395 RenderThreadImpl::RenderThreadImpl(const std::string& channel_name)
396     : ChildThread(Options(channel_name, ShouldUseMojoChannel())) {
397   Init();
398 }
399
400 void 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
580 RenderThreadImpl::~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
589 void 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
672 bool 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
736 base::MessageLoop* RenderThreadImpl::GetMessageLoop() {
737   return message_loop();
738 }
739
740 IPC::SyncChannel* RenderThreadImpl::GetChannel() {
741   return channel();
742 }
743
744 std::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
754 IPC::SyncMessageFilter* RenderThreadImpl::GetSyncMessageFilter() {
755   return sync_message_filter();
756 }
757
758 scoped_refptr<base::MessageLoopProxy>
759     RenderThreadImpl::GetIOMessageLoopProxy() {
760   return ChildProcess::current()->io_message_loop_proxy();
761 }
762
763 void 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
779 void RenderThreadImpl::RemoveRoute(int32 routing_id) {
780   ChildThread::GetRouter()->RemoveRoute(routing_id);
781 }
782
783 void 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
792 void 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
800 void 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
809 int RenderThreadImpl::GenerateRoutingID() {
810   int routing_id = MSG_ROUTING_NONE;
811   Send(new ViewHostMsg_GenerateRoutingID(&routing_id));
812   return routing_id;
813 }
814
815 void RenderThreadImpl::AddFilter(IPC::MessageFilter* filter) {
816   channel()->AddFilter(filter);
817 }
818
819 void RenderThreadImpl::RemoveFilter(IPC::MessageFilter* filter) {
820   channel()->RemoveFilter(filter);
821 }
822
823 void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) {
824   observers_.AddObserver(observer);
825 }
826
827 void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) {
828   observers_.RemoveObserver(observer);
829 }
830
831 void RenderThreadImpl::SetResourceDispatcherDelegate(
832     ResourceDispatcherDelegate* delegate) {
833   resource_dispatcher()->set_delegate(delegate);
834 }
835
836 void 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
942 void 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
950 void RenderThreadImpl::NotifyTimezoneChange() {
951   NotifyTimezoneChangeOnThisThread();
952   RenderThread::Get()->PostTaskToAllWebWorkers(
953       base::Bind(&NotifyTimezoneChangeOnThisThread));
954 }
955
956 void RenderThreadImpl::RecordAction(const base::UserMetricsAction& action) {
957   Send(new ViewHostMsg_UserMetricsRecordAction(action.str_));
958 }
959
960 void RenderThreadImpl::RecordComputedAction(const std::string& action) {
961   Send(new ViewHostMsg_UserMetricsRecordAction(action));
962 }
963
964 scoped_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
989 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
990   WebScriptController::registerExtension(extension);
991 }
992
993 void 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
1001 void 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
1046 void 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
1082 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
1083   return idle_notification_delay_in_ms_;
1084 }
1085
1086 void RenderThreadImpl::SetIdleNotificationDelayInMs(
1087     int64 idle_notification_delay_in_ms) {
1088   idle_notification_delay_in_ms_ = idle_notification_delay_in_ms;
1089 }
1090
1091 void RenderThreadImpl::UpdateHistograms(int sequence_number) {
1092   child_histogram_message_filter()->SendHistograms(sequence_number);
1093 }
1094
1095 int RenderThreadImpl::PostTaskToAllWebWorkers(const base::Closure& closure) {
1096   return WorkerTaskRunner::Instance()->PostTaskToAllThreads(closure);
1097 }
1098
1099 bool 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
1105 void RenderThreadImpl::PostponeIdleNotification() {
1106   idle_notifications_to_skip_ = 2;
1107 }
1108
1109 scoped_refptr<media::GpuVideoAcceleratorFactories>
1110 RenderThreadImpl::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
1146 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
1147 RenderThreadImpl::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
1163 scoped_refptr<webkit::gpu::ContextProviderWebContext>
1164 RenderThreadImpl::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
1187 AudioRendererMixerManager* 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
1196 media::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
1211 base::WaitableEvent* RenderThreadImpl::GetShutdownEvent() {
1212   return ChildProcess::current()->GetShutDownEvent();
1213 }
1214
1215 #if defined(OS_WIN)
1216 void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
1217                                               const base::string16& str) {
1218   Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str));
1219 }
1220
1221 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) {
1222   Send(new ChildProcessHostMsg_PreCacheFont(log_font));
1223 }
1224
1225 void RenderThreadImpl::ReleaseCachedFonts() {
1226   Send(new ChildProcessHostMsg_ReleaseCachedFonts());
1227 }
1228
1229 #endif  // OS_WIN
1230
1231 ServiceRegistry* RenderThreadImpl::GetServiceRegistry() {
1232   return service_registry();
1233 }
1234
1235 bool RenderThreadImpl::IsMainThread() {
1236   return !!current();
1237 }
1238
1239 base::MessageLoop* RenderThreadImpl::GetMainLoop() {
1240   return message_loop();
1241 }
1242
1243 scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() {
1244   return io_message_loop_proxy_;
1245 }
1246
1247 scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory(
1248     size_t size) {
1249   return scoped_ptr<base::SharedMemory>(
1250       HostAllocateSharedMemoryBuffer(size));
1251 }
1252
1253 CreateCommandBufferResult 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
1275 scoped_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
1304 void 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
1315 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
1316   suspend_webkit_shared_timer_ = false;
1317 }
1318
1319 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
1320   notify_webkit_of_modal_loop_ = false;
1321 }
1322
1323 bool 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
1364 void RenderThreadImpl::OnCreateNewFrame(int routing_id, int parent_routing_id) {
1365   RenderFrameImpl::CreateFrame(routing_id, parent_routing_id);
1366 }
1367
1368 void 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
1375 void 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
1382 void 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
1403 GpuChannelHost* 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
1445 blink::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)
1469 PeerConnectionDependencyFactory*
1470 RenderThreadImpl::GetPeerConnectionDependencyFactory() {
1471   return peer_connection_factory_.get();
1472 }
1473 #endif
1474
1475 GpuChannelHost* 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
1485 void 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
1498 void 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
1509 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
1510   GetContentClient()->SetActiveURL(data);
1511   CHECK(false);
1512 }
1513
1514 void RenderThreadImpl::OnUpdateTimezone() {
1515   NotifyTimezoneChange();
1516 }
1517
1518 #if defined(OS_ANDROID)
1519 void 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)
1533 void 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
1550 void 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
1561 void 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
1586 scoped_refptr<base::MessageLoopProxy>
1587 RenderThreadImpl::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
1596 scoped_refptr<base::MessageLoopProxy>
1597 RenderThreadImpl::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
1611 void 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
1619 void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
1620   gamepad_shared_memory_reader_->SampleGamepads(*data);
1621 }
1622
1623 void RenderThreadImpl::SetGamepadListener(blink::WebGamepadListener* listener) {
1624   gamepad_shared_memory_reader_->SetGamepadListener(listener);
1625 }
1626
1627 void RenderThreadImpl::WidgetCreated() {
1628   widget_count_++;
1629 }
1630
1631 void RenderThreadImpl::WidgetDestroyed() {
1632   widget_count_--;
1633 }
1634
1635 void 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
1651 void 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