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