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