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