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