render_process_host_impl.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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// Represents the browser side of the browser <--> renderer communication
6// channel. There will be one RenderProcessHost per renderer process.
7
8#include "content/browser/renderer_host/render_process_host_impl.h"
9
10#include <algorithm>
11#include <limits>
12#include <vector>
13
14#if defined(OS_POSIX)
15#include <utility>  // for pair<>
16#endif
17
18#include "base/base_switches.h"
19#include "base/bind.h"
20#include "base/bind_helpers.h"
21#include "base/callback.h"
22#include "base/command_line.h"
23#include "base/debug/trace_event.h"
24#include "base/lazy_instance.h"
25#include "base/logging.h"
26#include "base/metrics/field_trial.h"
27#include "base/metrics/histogram.h"
28#include "base/path_service.h"
29#include "base/platform_file.h"
30#include "base/process_util.h"
31#include "base/rand_util.h"
32#include "base/stl_util.h"
33#include "base/strings/string_util.h"
34#include "base/supports_user_data.h"
35#include "base/sys_info.h"
36#include "base/threading/thread.h"
37#include "base/threading/thread_restrictions.h"
38#include "base/tracked_objects.h"
39#include "cc/base/switches.h"
40#include "content/browser/appcache/appcache_dispatcher_host.h"
41#include "content/browser/appcache/chrome_appcache_service.h"
42#include "content/browser/browser_main.h"
43#include "content/browser/browser_main_loop.h"
44#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
45#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
46#include "content/browser/child_process_security_policy_impl.h"
47#include "content/browser/device_orientation/orientation_message_filter.h"
48#include "content/browser/dom_storage/dom_storage_context_impl.h"
49#include "content/browser/dom_storage/dom_storage_message_filter.h"
50#include "content/browser/download/mhtml_generation_manager.h"
51#include "content/browser/fileapi/chrome_blob_storage_context.h"
52#include "content/browser/fileapi/fileapi_message_filter.h"
53#include "content/browser/geolocation/geolocation_dispatcher_host.h"
54#include "content/browser/gpu/gpu_data_manager_impl.h"
55#include "content/browser/gpu/gpu_process_host.h"
56#include "content/browser/gpu/shader_disk_cache.h"
57#include "content/browser/histogram_message_filter.h"
58#include "content/browser/hyphenator/hyphenator_message_filter.h"
59#include "content/browser/indexed_db/indexed_db_context_impl.h"
60#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
61#include "content/browser/loader/resource_message_filter.h"
62#include "content/browser/loader/resource_scheduler_filter.h"
63#include "content/browser/media/media_internals.h"
64#include "content/browser/mime_registry_message_filter.h"
65#include "content/browser/plugin_service_impl.h"
66#include "content/browser/profiler_message_filter.h"
67#include "content/browser/renderer_host/clipboard_message_filter.h"
68#include "content/browser/renderer_host/database_message_filter.h"
69#include "content/browser/renderer_host/device_motion_browser_message_filter.h"
70#include "content/browser/renderer_host/file_utilities_message_filter.h"
71#include "content/browser/renderer_host/gamepad_browser_message_filter.h"
72#include "content/browser/renderer_host/gpu_message_filter.h"
73#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
74#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
75#include "content/browser/renderer_host/media/audio_renderer_host.h"
76#include "content/browser/renderer_host/media/device_request_message_filter.h"
77#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
78#include "content/browser/renderer_host/media/midi_host.h"
79#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
80#include "content/browser/renderer_host/media/video_capture_host.h"
81#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
82#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
83#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
84#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
85#include "content/browser/renderer_host/quota_dispatcher_host.h"
86#include "content/browser/renderer_host/render_message_filter.h"
87#include "content/browser/renderer_host/render_view_host_delegate.h"
88#include "content/browser/renderer_host/render_view_host_impl.h"
89#include "content/browser/renderer_host/render_widget_helper.h"
90#include "content/browser/renderer_host/render_widget_host_impl.h"
91#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
92#include "content/browser/renderer_host/text_input_client_message_filter.h"
93#include "content/browser/resolve_proxy_msg_helper.h"
94#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
95#include "content/browser/speech/speech_recognition_dispatcher_host.h"
96#include "content/browser/storage_partition_impl.h"
97#include "content/browser/tracing/trace_message_filter.h"
98#include "content/browser/webui/web_ui_controller_factory_registry.h"
99#include "content/browser/worker_host/worker_message_filter.h"
100#include "content/browser/worker_host/worker_storage_partition.h"
101#include "content/common/child_process_host_impl.h"
102#include "content/common/child_process_messages.h"
103#include "content/common/gpu/gpu_messages.h"
104#include "content/common/resource_messages.h"
105#include "content/common/view_messages.h"
106#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
107#include "content/public/browser/browser_context.h"
108#include "content/public/browser/content_browser_client.h"
109#include "content/public/browser/notification_service.h"
110#include "content/public/browser/notification_types.h"
111#include "content/public/browser/render_process_host_factory.h"
112#include "content/public/browser/render_widget_host.h"
113#include "content/public/browser/resource_context.h"
114#include "content/public/browser/user_metrics.h"
115#include "content/public/common/content_constants.h"
116#include "content/public/common/content_switches.h"
117#include "content/public/common/process_type.h"
118#include "content/public/common/result_codes.h"
119#include "content/public/common/url_constants.h"
120#include "content/renderer/render_process_impl.h"
121#include "content/renderer/render_thread_impl.h"
122#include "gpu/command_buffer/service/gpu_switches.h"
123#include "ipc/ipc_channel.h"
124#include "ipc/ipc_logging.h"
125#include "ipc/ipc_platform_file.h"
126#include "ipc/ipc_switches.h"
127#include "media/base/media_switches.h"
128#include "net/url_request/url_request_context_getter.h"
129#include "ppapi/shared_impl/ppapi_switches.h"
130#include "ui/base/ui_base_switches.h"
131#include "ui/gl/gl_switches.h"
132#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
133#include "webkit/glue/resource_type.h"
134#include "webkit/plugins/plugin_switches.h"
135
136#if defined(OS_WIN)
137#include "base/win/scoped_com_initializer.h"
138#include "content/common/font_cache_dispatcher_win.h"
139#include "content/common/sandbox_win.h"
140#include "content/public/common/sandboxed_process_launcher_delegate.h"
141#endif
142
143#if defined(ENABLE_WEBRTC)
144#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
145#endif
146
147#include "third_party/skia/include/core/SkBitmap.h"
148
149extern bool g_exited_main_message_loop;
150
151static const char* kSiteProcessMapKeyName = "content_site_process_map";
152
153namespace content {
154namespace {
155
156base::MessageLoop* g_in_process_thread;
157
158void CacheShaderInfo(int32 id, base::FilePath path) {
159  ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
160}
161
162void RemoveShaderInfo(int32 id) {
163  ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
164}
165
166}  // namespace
167
168// This class creates the IO thread for the renderer when running in
169// single-process mode.  It's not used in multi-process mode.
170class RendererMainThread : public base::Thread {
171 public:
172  explicit RendererMainThread(const std::string& channel_id)
173      : Thread("Chrome_InProcRendererThread"),
174        channel_id_(channel_id) {
175  }
176
177  virtual ~RendererMainThread() {
178    Stop();
179  }
180
181 protected:
182  virtual void Init() OVERRIDE {
183    render_process_.reset(new RenderProcessImpl());
184    new RenderThreadImpl(channel_id_);
185    g_in_process_thread = message_loop();
186  }
187
188  virtual void CleanUp() OVERRIDE {
189    g_in_process_thread = NULL;
190    render_process_.reset();
191
192    // It's a little lame to manually set this flag.  But the single process
193    // RendererThread will receive the WM_QUIT.  We don't need to assert on
194    // this thread, so just force the flag manually.
195    // If we want to avoid this, we could create the InProcRendererThread
196    // directly with _beginthreadex() rather than using the Thread class.
197    // We used to set this flag in the Init function above. However there
198    // other threads like WebThread which are created by this thread
199    // which resets this flag. Please see Thread::StartWithOptions. Setting
200    // this flag to true in Cleanup works around these problems.
201    SetThreadWasQuitProperly(true);
202  }
203
204 private:
205  std::string channel_id_;
206  scoped_ptr<RenderProcess> render_process_;
207
208  DISALLOW_COPY_AND_ASSIGN(RendererMainThread);
209};
210
211namespace {
212
213// Helper class that we pass to ResourceMessageFilter so that it can find the
214// right net::URLRequestContext for a request.
215class RendererURLRequestContextSelector
216    : public ResourceMessageFilter::URLRequestContextSelector {
217 public:
218  RendererURLRequestContextSelector(BrowserContext* browser_context,
219                                    int render_child_id)
220      : request_context_(browser_context->GetRequestContextForRenderProcess(
221                             render_child_id)),
222        media_request_context_(
223            browser_context->GetMediaRequestContextForRenderProcess(
224                render_child_id)) {
225  }
226
227  virtual net::URLRequestContext* GetRequestContext(
228      ResourceType::Type resource_type) OVERRIDE {
229    net::URLRequestContextGetter* request_context = request_context_.get();
230    // If the request has resource type of ResourceType::MEDIA, we use a request
231    // context specific to media for handling it because these resources have
232    // specific needs for caching.
233    if (resource_type == ResourceType::MEDIA)
234      request_context = media_request_context_.get();
235    return request_context->GetURLRequestContext();
236  }
237
238 private:
239  virtual ~RendererURLRequestContextSelector() {}
240
241  scoped_refptr<net::URLRequestContextGetter> request_context_;
242  scoped_refptr<net::URLRequestContextGetter> media_request_context_;
243};
244
245// the global list of all renderer processes
246base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
247    g_all_hosts = LAZY_INSTANCE_INITIALIZER;
248
249base::LazyInstance<scoped_refptr<BrowserPluginGeolocationPermissionContext> >
250    g_browser_plugin_geolocation_context = LAZY_INSTANCE_INITIALIZER;
251
252// Map of site to process, to ensure we only have one RenderProcessHost per
253// site in process-per-site mode.  Each map is specific to a BrowserContext.
254class SiteProcessMap : public base::SupportsUserData::Data {
255 public:
256  typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap;
257  SiteProcessMap() {}
258
259  void RegisterProcess(const std::string& site, RenderProcessHost* process) {
260    map_[site] = process;
261  }
262
263  RenderProcessHost* FindProcess(const std::string& site) {
264    SiteToProcessMap::iterator i = map_.find(site);
265    if (i != map_.end())
266      return i->second;
267    return NULL;
268  }
269
270  void RemoveProcess(RenderProcessHost* host) {
271    // Find all instances of this process in the map, then separately remove
272    // them.
273    std::set<std::string> sites;
274    for (SiteToProcessMap::const_iterator i = map_.begin();
275         i != map_.end();
276         i++) {
277      if (i->second == host)
278        sites.insert(i->first);
279    }
280    for (std::set<std::string>::iterator i = sites.begin();
281         i != sites.end();
282         i++) {
283      SiteToProcessMap::iterator iter = map_.find(*i);
284      if (iter != map_.end()) {
285        DCHECK_EQ(iter->second, host);
286        map_.erase(iter);
287      }
288    }
289  }
290
291 private:
292  SiteToProcessMap map_;
293};
294
295// Find the SiteProcessMap specific to the given context.
296SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
297  DCHECK(context);
298  SiteProcessMap* map = static_cast<SiteProcessMap*>(
299      context->GetUserData(kSiteProcessMapKeyName));
300  if (!map) {
301    map = new SiteProcessMap();
302    context->SetUserData(kSiteProcessMapKeyName, map);
303  }
304  return map;
305}
306
307#if defined(OS_WIN)
308// NOTE: changes to this class need to be reviewed by the security team.
309class RendererSandboxedProcessLauncherDelegate
310    : public content::SandboxedProcessLauncherDelegate {
311 public:
312  RendererSandboxedProcessLauncherDelegate() {}
313  virtual ~RendererSandboxedProcessLauncherDelegate() {}
314
315  virtual void ShouldSandbox(bool* in_sandbox) OVERRIDE {
316#if !defined (GOOGLE_CHROME_BUILD)
317    if (CommandLine::ForCurrentProcess()->HasSwitch(
318        switches::kInProcessPlugins)) {
319      *in_sandbox = false;
320    }
321#endif
322  }
323
324  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
325                              bool* success) {
326    AddBaseHandleClosePolicy(policy);
327    GetContentClient()->browser()->PreSpawnRenderer(policy, success);
328  }
329};
330#endif  // OS_WIN
331
332}  // namespace
333
334// Stores the maximum number of renderer processes the content module can
335// create.
336static size_t g_max_renderer_count_override = 0;
337
338// static
339size_t RenderProcessHost::GetMaxRendererProcessCount() {
340  if (g_max_renderer_count_override)
341    return g_max_renderer_count_override;
342
343  // Defines the maximum number of renderer processes according to the
344  // amount of installed memory as reported by the OS. The calculation
345  // assumes that you want the renderers to use half of the installed
346  // RAM and assuming that each WebContents uses ~40MB.
347  // If you modify this assumption, you need to adjust the
348  // ThirtyFourTabs test to match the expected number of processes.
349  //
350  // With the given amounts of installed memory below on a 32-bit CPU,
351  // the maximum renderer count will roughly be as follows:
352  //
353  //   128 MB -> 3
354  //   512 MB -> 6
355  //  1024 MB -> 12
356  //  4096 MB -> 51
357  // 16384 MB -> 82 (kMaxRendererProcessCount)
358
359  static size_t max_count = 0;
360  if (!max_count) {
361    const size_t kEstimatedWebContentsMemoryUsage =
362#if defined(ARCH_CPU_64_BITS)
363        60;  // In MB
364#else
365        40;  // In MB
366#endif
367    max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
368    max_count /= kEstimatedWebContentsMemoryUsage;
369
370    const size_t kMinRendererProcessCount = 3;
371    max_count = std::max(max_count, kMinRendererProcessCount);
372    max_count = std::min(max_count, kMaxRendererProcessCount);
373  }
374  return max_count;
375}
376
377// static
378bool g_run_renderer_in_process_ = false;
379
380// static
381void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
382  g_max_renderer_count_override = count;
383}
384
385RenderProcessHostImpl::RenderProcessHostImpl(
386    BrowserContext* browser_context,
387    StoragePartitionImpl* storage_partition_impl,
388    bool supports_browser_plugin,
389    bool is_guest)
390        : fast_shutdown_started_(false),
391          deleting_soon_(false),
392          pending_views_(0),
393          visible_widgets_(0),
394          backgrounded_(true),
395          cached_dibs_cleaner_(
396              FROM_HERE, base::TimeDelta::FromSeconds(5),
397              this, &RenderProcessHostImpl::ClearTransportDIBCache),
398          is_initialized_(false),
399          id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
400          browser_context_(browser_context),
401          storage_partition_impl_(storage_partition_impl),
402          sudden_termination_allowed_(true),
403          ignore_input_events_(false),
404          supports_browser_plugin_(supports_browser_plugin),
405          is_guest_(is_guest),
406          gpu_observer_registered_(false) {
407  widget_helper_ = new RenderWidgetHelper();
408
409  ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
410
411  CHECK(!g_exited_main_message_loop);
412  RegisterHost(GetID(), this);
413  g_all_hosts.Get().set_check_on_null_data(true);
414  // Initialize |child_process_activity_time_| to a reasonable value.
415  mark_child_process_activity_time();
416
417  if (!GetBrowserContext()->IsOffTheRecord() &&
418      !CommandLine::ForCurrentProcess()->HasSwitch(
419          switches::kDisableGpuShaderDiskCache)) {
420    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
421                            base::Bind(&CacheShaderInfo, GetID(),
422                                       storage_partition_impl_->GetPath()));
423  }
424
425  // Note: When we create the RenderProcessHostImpl, it's technically
426  //       backgrounded, because it has no visible listeners.  But the process
427  //       doesn't actually exist yet, so we'll Background it later, after
428  //       creation.
429}
430
431RenderProcessHostImpl::~RenderProcessHostImpl() {
432  DCHECK(!run_renderer_in_process());
433  ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
434
435  if (gpu_observer_registered_) {
436    GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
437    gpu_observer_registered_ = false;
438  }
439
440  // We may have some unsent messages at this point, but that's OK.
441  channel_.reset();
442  while (!queued_messages_.empty()) {
443    delete queued_messages_.front();
444    queued_messages_.pop();
445  }
446
447  ClearTransportDIBCache();
448  UnregisterHost(GetID());
449
450  if (!CommandLine::ForCurrentProcess()->HasSwitch(
451      switches::kDisableGpuShaderDiskCache)) {
452    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
453                            base::Bind(&RemoveShaderInfo, GetID()));
454  }
455}
456
457void RenderProcessHostImpl::EnableSendQueue() {
458  is_initialized_ = false;
459}
460
461bool RenderProcessHostImpl::Init() {
462  // calling Init() more than once does nothing, this makes it more convenient
463  // for the view host which may not be sure in some cases
464  if (channel_)
465    return true;
466
467  CommandLine::StringType renderer_prefix;
468#if defined(OS_POSIX)
469  // A command prefix is something prepended to the command line of the spawned
470  // process. It is supported only on POSIX systems.
471  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
472  renderer_prefix =
473      browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
474#endif  // defined(OS_POSIX)
475
476#if defined(OS_LINUX)
477  int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
478                                        ChildProcessHost::CHILD_NORMAL;
479#else
480  int flags = ChildProcessHost::CHILD_NORMAL;
481#endif
482
483  // Find the renderer before creating the channel so if this fails early we
484  // return without creating the channel.
485  base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags);
486  if (renderer_path.empty())
487    return false;
488
489  // Setup the IPC channel.
490  const std::string channel_id =
491      IPC::Channel::GenerateVerifiedChannelID(std::string());
492  channel_.reset(
493          new IPC::ChannelProxy(channel_id,
494                                IPC::Channel::MODE_SERVER,
495                                this,
496                                BrowserThread::GetMessageLoopProxyForThread(
497                                    BrowserThread::IO).get()));
498
499  // Call the embedder first so that their IPC filters have priority.
500  GetContentClient()->browser()->RenderProcessHostCreated(this);
501
502  CreateMessageFilters();
503
504  // Single-process mode not supported in split-dll mode.
505#if !defined(CHROME_SPLIT_DLL)
506  if (run_renderer_in_process()) {
507    // Crank up a thread and run the initialization there.  With the way that
508    // messages flow between the browser and renderer, this thread is required
509    // to prevent a deadlock in single-process mode.  Since the primordial
510    // thread in the renderer process runs the WebKit code and can sometimes
511    // make blocking calls to the UI thread (i.e. this thread), they need to run
512    // on separate threads.
513    in_process_renderer_.reset(new RendererMainThread(channel_id));
514
515    base::Thread::Options options;
516#if defined(OS_WIN) && !defined(OS_MACOSX)
517    // In-process plugins require this to be a UI message loop.
518    options.message_loop_type = base::MessageLoop::TYPE_UI;
519#else
520    // We can't have multiple UI loops on Linux and Android, so we don't support
521    // in-process plugins.
522    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
523#endif
524    in_process_renderer_->StartWithOptions(options);
525
526    OnProcessLaunched();  // Fake a callback that the process is ready.
527  } else
528#endif  // !CHROME_SPLIT_DLL
529  {
530    // Build command line for renderer.  We call AppendRendererCommandLine()
531    // first so the process type argument will appear first.
532    CommandLine* cmd_line = new CommandLine(renderer_path);
533    if (!renderer_prefix.empty())
534      cmd_line->PrependWrapper(renderer_prefix);
535    AppendRendererCommandLine(cmd_line);
536    cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
537
538    // Spawn the child process asynchronously to avoid blocking the UI thread.
539    // As long as there's no renderer prefix, we can use the zygote process
540    // at this stage.
541    child_process_launcher_.reset(new ChildProcessLauncher(
542#if defined(OS_WIN)
543        new RendererSandboxedProcessLauncherDelegate,
544#elif defined(OS_POSIX)
545        renderer_prefix.empty(),
546        base::EnvironmentVector(),
547        channel_->TakeClientFileDescriptor(),
548#endif
549        cmd_line,
550        GetID(),
551        this));
552
553    fast_shutdown_started_ = false;
554  }
555
556  if (!gpu_observer_registered_) {
557    gpu_observer_registered_ = true;
558    GpuDataManagerImpl::GetInstance()->AddObserver(this);
559  }
560
561  is_initialized_ = true;
562  return true;
563}
564
565void RenderProcessHostImpl::CreateMessageFilters() {
566  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567  channel_->AddFilter(new ResourceSchedulerFilter(GetID()));
568  MediaInternals* media_internals = MediaInternals::GetInstance();;
569  media::AudioManager* audio_manager =
570      BrowserMainLoop::GetInstance()->audio_manager();
571  // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
572  // from guests.
573  if (supports_browser_plugin_) {
574    scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
575        new BrowserPluginMessageFilter(GetID(), IsGuest()));
576    channel_->AddFilter(bp_message_filter.get());
577  }
578
579  scoped_refptr<RenderMessageFilter> render_message_filter(
580      new RenderMessageFilter(
581          GetID(),
582#if defined(ENABLE_PLUGINS)
583          PluginServiceImpl::GetInstance(),
584#else
585          NULL,
586#endif
587          GetBrowserContext(),
588          GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
589          widget_helper_.get(),
590          audio_manager,
591          media_internals,
592          storage_partition_impl_->GetDOMStorageContext()));
593  channel_->AddFilter(render_message_filter.get());
594  BrowserContext* browser_context = GetBrowserContext();
595  ResourceContext* resource_context = browser_context->GetResourceContext();
596
597  ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
598      GetID(), PROCESS_TYPE_RENDERER, resource_context,
599      storage_partition_impl_->GetAppCacheService(),
600      ChromeBlobStorageContext::GetFor(browser_context),
601      storage_partition_impl_->GetFileSystemContext(),
602      new RendererURLRequestContextSelector(browser_context, GetID()));
603
604  channel_->AddFilter(resource_message_filter);
605  MediaStreamManager* media_stream_manager =
606      BrowserMainLoop::GetInstance()->media_stream_manager();
607  channel_->AddFilter(new AudioInputRendererHost(
608      audio_manager,
609      media_stream_manager,
610      BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
611  channel_->AddFilter(new AudioRendererHost(
612      GetID(), audio_manager,
613      BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
614      media_internals, media_stream_manager));
615  channel_->AddFilter(
616      new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
617  channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
618  channel_->AddFilter(new AppCacheDispatcherHost(
619      storage_partition_impl_->GetAppCacheService(),
620      GetID()));
621  channel_->AddFilter(new ClipboardMessageFilter);
622  channel_->AddFilter(new DOMStorageMessageFilter(
623      GetID(),
624      storage_partition_impl_->GetDOMStorageContext()));
625  channel_->AddFilter(new IndexedDBDispatcherHost(
626      GetID(),
627      storage_partition_impl_->GetIndexedDBContext()));
628  if (IsGuest()) {
629    if (!g_browser_plugin_geolocation_context.Get().get()) {
630      g_browser_plugin_geolocation_context.Get() =
631          new BrowserPluginGeolocationPermissionContext();
632    }
633    channel_->AddFilter(GeolocationDispatcherHost::New(
634        GetID(), g_browser_plugin_geolocation_context.Get().get()));
635  } else {
636    channel_->AddFilter(GeolocationDispatcherHost::New(
637        GetID(), browser_context->GetGeolocationPermissionContext()));
638  }
639  gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
640  channel_->AddFilter(gpu_message_filter_);
641#if defined(ENABLE_WEBRTC)
642  channel_->AddFilter(new WebRTCIdentityServiceHost(
643      storage_partition_impl_->GetWebRTCIdentityStore()));
644  peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
645  channel_->AddFilter(peer_connection_tracker_host_.get());
646  channel_->AddFilter(new MediaStreamDispatcherHost(
647      GetID(), media_stream_manager));
648  channel_->AddFilter(new DeviceRequestMessageFilter(media_stream_manager));
649#endif
650#if defined(ENABLE_PLUGINS)
651  // TODO(raymes): PepperMessageFilter should be removed from here.
652  channel_->AddFilter(new PepperMessageFilter(GetID(), browser_context));
653  channel_->AddFilter(new PepperRendererConnection);
654#endif
655#if defined(ENABLE_INPUT_SPEECH)
656  channel_->AddFilter(new InputTagSpeechDispatcherHost(
657      IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext()));
658#endif
659  channel_->AddFilter(new SpeechRecognitionDispatcherHost(
660      GetID(), storage_partition_impl_->GetURLRequestContext()));
661  channel_->AddFilter(new FileAPIMessageFilter(
662      GetID(),
663      storage_partition_impl_->GetURLRequestContext(),
664      storage_partition_impl_->GetFileSystemContext(),
665      ChromeBlobStorageContext::GetFor(browser_context)));
666  channel_->AddFilter(new OrientationMessageFilter());
667  channel_->AddFilter(new FileUtilitiesMessageFilter(GetID()));
668  channel_->AddFilter(new MimeRegistryMessageFilter());
669  channel_->AddFilter(new DatabaseMessageFilter(
670      storage_partition_impl_->GetDatabaseTracker()));
671#if defined(OS_MACOSX)
672  channel_->AddFilter(new TextInputClientMessageFilter(GetID()));
673#elif defined(OS_WIN)
674  channel_->AddFilter(new FontCacheDispatcher());
675#endif
676
677  SocketStreamDispatcherHost* socket_stream_dispatcher_host =
678      new SocketStreamDispatcherHost(GetID(),
679          new RendererURLRequestContextSelector(browser_context, GetID()),
680          resource_context);
681  channel_->AddFilter(socket_stream_dispatcher_host);
682
683  channel_->AddFilter(new WorkerMessageFilter(
684      GetID(),
685      resource_context,
686      WorkerStoragePartition(
687          storage_partition_impl_->GetURLRequestContext(),
688          storage_partition_impl_->GetMediaURLRequestContext(),
689          storage_partition_impl_->GetAppCacheService(),
690          storage_partition_impl_->GetQuotaManager(),
691          storage_partition_impl_->GetFileSystemContext(),
692          storage_partition_impl_->GetDatabaseTracker(),
693          storage_partition_impl_->GetIndexedDBContext()),
694      base::Bind(&RenderWidgetHelper::GetNextRoutingID,
695                 base::Unretained(widget_helper_.get()))));
696
697#if defined(ENABLE_WEBRTC)
698  channel_->AddFilter(new P2PSocketDispatcherHost(
699      resource_context,
700      browser_context->GetRequestContextForRenderProcess(GetID())));
701#endif
702
703  channel_->AddFilter(new TraceMessageFilter());
704  channel_->AddFilter(new ResolveProxyMsgHelper(
705      browser_context->GetRequestContextForRenderProcess(GetID())));
706  channel_->AddFilter(new QuotaDispatcherHost(
707      GetID(),
708      storage_partition_impl_->GetQuotaManager(),
709      GetContentClient()->browser()->CreateQuotaPermissionContext()));
710  channel_->AddFilter(new GamepadBrowserMessageFilter());
711  channel_->AddFilter(new DeviceMotionBrowserMessageFilter());
712  channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
713  channel_->AddFilter(new HistogramMessageFilter());
714  channel_->AddFilter(new HyphenatorMessageFilter(this));
715#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
716  if (CommandLine::ForCurrentProcess()->HasSwitch(
717      switches::kEnableMemoryBenchmarking))
718    channel_->AddFilter(new MemoryBenchmarkMessageFilter());
719#endif
720}
721
722int RenderProcessHostImpl::GetNextRoutingID() {
723  return widget_helper_->GetNextRoutingID();
724}
725
726
727void RenderProcessHostImpl::ResumeDeferredNavigation(
728    const GlobalRequestID& request_id) {
729  widget_helper_->ResumeDeferredNavigation(request_id);
730}
731
732void RenderProcessHostImpl::AddRoute(
733    int32 routing_id,
734    IPC::Listener* listener) {
735  listeners_.AddWithID(listener, routing_id);
736}
737
738void RenderProcessHostImpl::RemoveRoute(int32 routing_id) {
739  DCHECK(listeners_.Lookup(routing_id) != NULL);
740  listeners_.Remove(routing_id);
741
742#if defined(OS_WIN)
743  // Dump the handle table if handle auditing is enabled.
744  const CommandLine& browser_command_line =
745      *CommandLine::ForCurrentProcess();
746  if (browser_command_line.HasSwitch(switches::kAuditHandles) ||
747      browser_command_line.HasSwitch(switches::kAuditAllHandles)) {
748    DumpHandles();
749
750    // We wait to close the channels until the child process has finished
751    // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
752    return;
753  }
754#endif
755  // Keep the one renderer thread around forever in single process mode.
756  if (!run_renderer_in_process())
757    Cleanup();
758}
759
760bool RenderProcessHostImpl::WaitForBackingStoreMsg(
761    int render_widget_id,
762    const base::TimeDelta& max_delay,
763    IPC::Message* msg) {
764  // The post task to this thread with the process id could be in queue, and we
765  // don't want to dispatch a message before then since it will need the handle.
766  if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
767    return false;
768
769  return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
770                                                max_delay, msg);
771}
772
773void RenderProcessHostImpl::ReceivedBadMessage() {
774  if (run_renderer_in_process()) {
775    // In single process mode it is better if we don't suicide but just
776    // crash.
777    CHECK(false);
778  }
779  // We kill the renderer but don't include a NOTREACHED, because we want the
780  // browser to try to survive when it gets illegal messages from the renderer.
781  base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE,
782                    false);
783}
784
785void RenderProcessHostImpl::WidgetRestored() {
786  // Verify we were properly backgrounded.
787  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
788  visible_widgets_++;
789  SetBackgrounded(false);
790}
791
792void RenderProcessHostImpl::WidgetHidden() {
793  // On startup, the browser will call Hide
794  if (backgrounded_)
795    return;
796
797  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
798  visible_widgets_--;
799  DCHECK_GE(visible_widgets_, 0);
800  if (visible_widgets_ == 0) {
801    DCHECK(!backgrounded_);
802    SetBackgrounded(true);
803  }
804}
805
806int RenderProcessHostImpl::VisibleWidgetCount() const {
807  return visible_widgets_;
808}
809
810bool RenderProcessHostImpl::IsGuest() const {
811  return is_guest_;
812}
813
814StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
815  return storage_partition_impl_;
816}
817
818void RenderProcessHostImpl::AppendRendererCommandLine(
819    CommandLine* command_line) const {
820  // Pass the process type first, so it shows first in process listings.
821  command_line->AppendSwitchASCII(switches::kProcessType,
822                                  switches::kRendererProcess);
823
824  // Now send any options from our own command line we want to propagate.
825  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
826  PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
827
828  // Pass on the browser locale.
829  const std::string locale =
830      GetContentClient()->browser()->GetApplicationLocale();
831  command_line->AppendSwitchASCII(switches::kLang, locale);
832
833  // If we run base::FieldTrials, we want to pass to their state to the
834  // renderer so that it can act in accordance with each state, or record
835  // histograms relating to the base::FieldTrial states.
836  std::string field_trial_states;
837  base::FieldTrialList::StatesToString(&field_trial_states);
838  if (!field_trial_states.empty()) {
839    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
840                                    field_trial_states);
841  }
842
843  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
844      command_line, GetID());
845
846  // Appending disable-gpu-feature switches due to software rendering list.
847  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
848  DCHECK(gpu_data_manager);
849  gpu_data_manager->AppendRendererCommandLine(command_line);
850}
851
852void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
853    const CommandLine& browser_cmd,
854    CommandLine* renderer_cmd) const {
855  // Propagate the following switches to the renderer command line (along
856  // with any associated values) if present in the browser command line.
857  static const char* const kSwitchNames[] = {
858    switches::kAudioBufferSize,
859    switches::kAuditAllHandles,
860    switches::kAuditHandles,
861    switches::kDisable3DAPIs,
862    switches::kDisableAcceleratedCompositing,
863    switches::kDisableAcceleratedVideoDecode,
864    switches::kDisableApplicationCache,
865    switches::kDisableAudio,
866    switches::kDisableBreakpad,
867    switches::kDisableDatabases,
868    switches::kDisableDelegatedRenderer,
869    switches::kDisableDesktopNotifications,
870    switches::kDisableDeviceOrientation,
871    switches::kDisableFileSystem,
872    switches::kDisableGeolocation,
873    switches::kDisableGLMultisampling,
874    switches::kDisableGpuVsync,
875    switches::kDisableGpu,
876    switches::kDisableHistogramCustomizer,
877    switches::kDisableLocalStorage,
878    switches::kDisableLogging,
879    switches::kDisableNewDialogStyle,
880    switches::kDisableSeccompFilterSandbox,
881    switches::kDisableSessionStorage,
882    switches::kDisableSharedWorkers,
883    switches::kDisableSpeechInput,
884    switches::kDisableTouchDragDrop,
885    switches::kDisableTouchEditing,
886#if defined(OS_ANDROID)
887    switches::kDisableWebRTC,
888    switches::kEnableSpeechRecognition,
889#endif
890    switches::kDisableWebAudio,
891#if defined(ENABLE_WEBRTC)
892    switches::kEnableDeviceEnumeration,
893    switches::kEnableSCTPDataChannels,
894#endif
895    switches::kEnableWebAnimationsCSS,
896    switches::kEnableWebAnimationsSVG,
897    switches::kEnableWebMIDI,
898    switches::kEnableExperimentalCanvasFeatures,
899    switches::kEnableExperimentalWebSocket,
900    switches::kDomAutomationController,
901    switches::kEnableAccessibilityLogging,
902    switches::kEnableBeginFrameScheduling,
903    switches::kEnableBrowserInputController,
904    switches::kEnableBrowserPluginForAllViewTypes,
905    switches::kEnableDCHECK,
906    switches::kEnableDelegatedRenderer,
907    switches::kEnableEncryptedMedia,
908    switches::kDisableLegacyEncryptedMedia,
909    switches::kOverrideEncryptedMediaCanPlayType,
910    switches::kEnableExperimentalWebPlatformFeatures,
911    switches::kEnableFixedLayout,
912    switches::kEnableDeferredImageDecoding,
913    switches::kEnableGPUServiceLogging,
914    switches::kEnableGPUClientLogging,
915    switches::kEnableGpuClientTracing,
916    switches::kEnableGpuBenchmarking,
917    switches::kEnableMemoryBenchmarking,
918    switches::kEnableSkiaBenchmarking,
919    switches::kEnableLogging,
920    switches::kEnableSpeechSynthesis,
921    switches::kEnableTouchDragDrop,
922    switches::kEnableTouchEditing,
923#if defined(ENABLE_WEBRTC)
924    switches::kEnableWebRtcAecRecordings,
925    switches::kEnableWebRtcTcpServerSocket,
926    switches::kEnableWebRtcHWDecoding,
927#endif
928#if defined(ANDROID) && !defined(GOOGLE_TV)
929    switches::kEnableWebKitMediaSource,
930#else
931    switches::kDisableWebKitMediaSource,
932#endif
933    switches::kEnableOverscrollNotifications,
934    switches::kEnableStrictSiteIsolation,
935    switches::kDisableFullScreen,
936    switches::kEnableNewDialogStyle,
937#if defined(ENABLE_PLUGINS)
938    switches::kEnablePepperTesting,
939    switches::kDisablePepper3d,
940#endif
941    switches::kEnablePreparsedJsCaching,
942    switches::kEnablePruneGpuCommandBuffers,
943    switches::kEnablePinch,
944    switches::kDisablePinch,
945#if defined(OS_MACOSX)
946    // Allow this to be set when invoking the browser and relayed along.
947    switches::kEnableSandboxLogging,
948#endif
949    switches::kEnableSoftwareCompositingGLAdapter,
950    switches::kEnableStatsTable,
951    switches::kEnableThreadedCompositing,
952    switches::kEnableCompositingForFixedPosition,
953    switches::kEnableHighDpiCompositingForFixedPosition,
954    switches::kDisableCompositingForFixedPosition,
955    switches::kEnableAcceleratedOverflowScroll,
956    switches::kEnableCompositingForTransition,
957    switches::kDisableCompositingForTransition,
958    switches::kEnableAcceleratedFixedRootBackground,
959    switches::kDisableAcceleratedFixedRootBackground,
960    switches::kDisableThreadedCompositing,
961    switches::kDisableTouchAdjustment,
962    switches::kDefaultTileWidth,
963    switches::kDefaultTileHeight,
964    switches::kMaxUntiledLayerWidth,
965    switches::kMaxUntiledLayerHeight,
966#if defined(OS_CHROMEOS)
967    switches::kEnableEncodedScreenCapture,
968#endif
969    switches::kEnableViewport,
970    switches::kEnableInbandTextTracks,
971    switches::kEnableOpusPlayback,
972    switches::kEnableVp8AlphaPlayback,
973    switches::kEnableEac3Playback,
974    switches::kForceDeviceScaleFactor,
975    switches::kFullMemoryCrashReport,
976#if defined(OS_ANDROID)
977    switches::kHideScrollbars,
978#endif
979#if !defined (GOOGLE_CHROME_BUILD)
980    // These are unsupported and not fully tested modes, so don't enable them
981    // for official Google Chrome builds.
982    switches::kInProcessPlugins,
983#endif  // GOOGLE_CHROME_BUILD
984    switches::kJavaScriptFlags,
985    switches::kLoggingLevel,
986    switches::kMemoryMetrics,
987#if defined(OS_ANDROID)
988    switches::kNetworkCountryIso,
989    switches::kDisableGestureRequirementForMediaPlayback,
990#endif
991#if defined(GOOGLE_TV)
992    switches::kUseExternalVideoSurfaceThresholdInPixels,
993#endif
994    switches::kNoReferrers,
995    switches::kNoSandbox,
996    switches::kEnableVtune,
997    switches::kPpapiInProcess,
998    switches::kRegisterPepperPlugins,
999    switches::kRendererAssertTest,
1000#if defined(OS_POSIX)
1001    switches::kChildCleanExit,
1002#endif
1003    switches::kRendererStartupDialog,
1004    switches::kShowPaintRects,
1005    switches::kSitePerProcess,
1006    switches::kStatsCollectionController,
1007    switches::kTestSandbox,
1008    switches::kTouchEvents,
1009    switches::kTraceStartup,
1010    // This flag needs to be propagated to the renderer process for
1011    // --in-process-webgl.
1012    switches::kUseGL,
1013    switches::kUseMobileUserAgent,
1014    switches::kUserAgent,
1015    switches::kV,
1016    switches::kVideoThreads,
1017    switches::kVModule,
1018    switches::kWebCoreLogChannels,
1019    switches::kEnableWebGLDraftExtensions,
1020    switches::kTraceToConsole,
1021    switches::kEnableDeviceMotion,
1022    // Please keep these in alphabetical order. Compositor switches here should
1023    // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
1024    cc::switches::kBackgroundColorInsteadOfCheckerboard,
1025    cc::switches::kCompositeToMailbox,
1026    cc::switches::kDisableImplSidePainting,
1027    cc::switches::kDisableThreadedAnimation,
1028    cc::switches::kEnableImplSidePainting,
1029    cc::switches::kEnablePartialSwap,
1030    cc::switches::kEnablePerTilePainting,
1031    cc::switches::kEnablePinchVirtualViewport,
1032    cc::switches::kEnableTopControlsPositionCalculation,
1033    cc::switches::kForceDirectLayerDrawing,
1034    cc::switches::kLowResolutionContentsScaleFactor,
1035    cc::switches::kMaxTilesForInterestArea,
1036    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
1037    cc::switches::kNumRasterThreads,
1038    cc::switches::kShowCompositedLayerBorders,
1039    cc::switches::kShowFPSCounter,
1040    cc::switches::kShowNonOccludingRects,
1041    cc::switches::kShowOccludingRects,
1042    cc::switches::kShowPropertyChangedRects,
1043    cc::switches::kShowReplicaScreenSpaceRects,
1044    cc::switches::kShowScreenSpaceRects,
1045    cc::switches::kShowSurfaceDamageRects,
1046    cc::switches::kSlowDownRasterScaleFactor,
1047    cc::switches::kStrictLayerPropertyChangeChecking,
1048    cc::switches::kTopControlsHeight,
1049    cc::switches::kTopControlsHideThreshold,
1050    cc::switches::kTopControlsShowThreshold,
1051    cc::switches::kTraceOverdraw,
1052    cc::switches::kUseMapImage,
1053  };
1054  renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
1055                                 arraysize(kSwitchNames));
1056
1057  // Disable databases in incognito mode.
1058  if (GetBrowserContext()->IsOffTheRecord() &&
1059      !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
1060    renderer_cmd->AppendSwitch(switches::kDisableDatabases);
1061#if defined(OS_ANDROID)
1062    renderer_cmd->AppendSwitch(switches::kDisableMediaHistoryLogging);
1063#endif
1064  }
1065
1066  // Enforce the extra command line flags for impl-side painting.
1067  if (cc::switches::IsImplSidePaintingEnabled() &&
1068      !browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding))
1069    renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding);
1070}
1071
1072base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
1073  if (run_renderer_in_process())
1074    return base::Process::Current().handle();
1075
1076  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1077    return base::kNullProcessHandle;
1078
1079  return child_process_launcher_->GetHandle();
1080}
1081
1082bool RenderProcessHostImpl::FastShutdownIfPossible() {
1083  if (run_renderer_in_process())
1084    return false;  // Single process mode never shutdown the renderer.
1085
1086  if (!GetContentClient()->browser()->IsFastShutdownPossible())
1087    return false;
1088
1089  if (!child_process_launcher_.get() ||
1090      child_process_launcher_->IsStarting() ||
1091      !GetHandle())
1092    return false;  // Render process hasn't started or is probably crashed.
1093
1094  // Test if there's an unload listener.
1095  // NOTE: It's possible that an onunload listener may be installed
1096  // while we're shutting down, so there's a small race here.  Given that
1097  // the window is small, it's unlikely that the web page has much
1098  // state that will be lost by not calling its unload handlers properly.
1099  if (!SuddenTerminationAllowed())
1100    return false;
1101
1102  ProcessDied(false /* already_dead */);
1103  fast_shutdown_started_ = true;
1104  return true;
1105}
1106
1107void RenderProcessHostImpl::DumpHandles() {
1108#if defined(OS_WIN)
1109  Send(new ChildProcessMsg_DumpHandles());
1110  return;
1111#endif
1112
1113  NOTIMPLEMENTED();
1114}
1115
1116// This is a platform specific function for mapping a transport DIB given its id
1117TransportDIB* RenderProcessHostImpl::MapTransportDIB(
1118    TransportDIB::Id dib_id) {
1119#if defined(OS_WIN)
1120  // On Windows we need to duplicate the handle from the remote process
1121  HANDLE section;
1122  DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), &section,
1123                  STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
1124                  FALSE, 0);
1125  return TransportDIB::Map(section);
1126#elif defined(TOOLKIT_GTK)
1127  return TransportDIB::Map(dib_id.shmkey);
1128#elif defined(OS_ANDROID)
1129  return TransportDIB::Map(dib_id);
1130#else
1131  // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1132  // for each.
1133  return widget_helper_->MapTransportDIB(dib_id);
1134#endif
1135}
1136
1137TransportDIB* RenderProcessHostImpl::GetTransportDIB(
1138    TransportDIB::Id dib_id) {
1139  if (!TransportDIB::is_valid_id(dib_id))
1140    return NULL;
1141
1142  const std::map<TransportDIB::Id, TransportDIB*>::iterator
1143      i = cached_dibs_.find(dib_id);
1144  if (i != cached_dibs_.end()) {
1145    cached_dibs_cleaner_.Reset();
1146    return i->second;
1147  }
1148
1149  TransportDIB* dib = MapTransportDIB(dib_id);
1150  if (!dib)
1151    return NULL;
1152
1153  if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
1154    // Clean a single entry from the cache
1155    std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
1156    size_t smallest_size = std::numeric_limits<size_t>::max();
1157
1158    for (std::map<TransportDIB::Id, TransportDIB*>::iterator
1159         i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
1160      if (i->second->size() <= smallest_size) {
1161        smallest_iterator = i;
1162        smallest_size = i->second->size();
1163      }
1164    }
1165
1166#if defined(TOOLKIT_GTK)
1167    smallest_iterator->second->Detach();
1168#else
1169    delete smallest_iterator->second;
1170#endif
1171    cached_dibs_.erase(smallest_iterator);
1172  }
1173
1174  cached_dibs_[dib_id] = dib;
1175  cached_dibs_cleaner_.Reset();
1176  return dib;
1177}
1178
1179void RenderProcessHostImpl::ClearTransportDIBCache() {
1180#if defined(TOOLKIT_GTK)
1181  std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib =
1182      cached_dibs_.begin();
1183  for (; dib != cached_dibs_.end(); ++dib)
1184    dib->second->Detach();
1185#else
1186  STLDeleteContainerPairSecondPointers(
1187      cached_dibs_.begin(), cached_dibs_.end());
1188#endif
1189  cached_dibs_.clear();
1190}
1191
1192bool RenderProcessHostImpl::Send(IPC::Message* msg) {
1193  if (!channel_) {
1194    if (!is_initialized_) {
1195      queued_messages_.push(msg);
1196      return true;
1197    } else {
1198      delete msg;
1199      return false;
1200    }
1201  }
1202
1203  if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
1204    queued_messages_.push(msg);
1205    return true;
1206  }
1207
1208  return channel_->Send(msg);
1209}
1210
1211bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
1212  // If we're about to be deleted, or have initiated the fast shutdown sequence,
1213  // we ignore incoming messages.
1214
1215  if (deleting_soon_ || fast_shutdown_started_)
1216    return false;
1217
1218  mark_child_process_activity_time();
1219  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
1220    // Dispatch control messages.
1221    bool msg_is_ok = true;
1222    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1223      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
1224                          OnShutdownRequest)
1225      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone,
1226                          OnDumpHandlesDone)
1227      IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
1228                          SuddenTerminationChanged)
1229      IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
1230                          OnUserMetricsRecordAction)
1231      IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
1232      // Adding single handlers for your service here is fine, but once your
1233      // service needs more than one handler, please extract them into a new
1234      // message filter and add that filter to CreateMessageFilters().
1235      IPC_MESSAGE_UNHANDLED_ERROR()
1236    IPC_END_MESSAGE_MAP_EX()
1237
1238    if (!msg_is_ok) {
1239      // The message had a handler, but its de-serialization failed.
1240      // We consider this a capital crime. Kill the renderer if we have one.
1241      LOG(ERROR) << "bad message " << msg.type() << " terminating renderer.";
1242      RecordAction(UserMetricsAction("BadMessageTerminate_BRPH"));
1243      ReceivedBadMessage();
1244    }
1245    return true;
1246  }
1247
1248  // Dispatch incoming messages to the appropriate IPC::Listener.
1249  IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
1250  if (!listener) {
1251    if (msg.is_sync()) {
1252      // The listener has gone away, so we must respond or else the caller will
1253      // hang waiting for a reply.
1254      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
1255      reply->set_reply_error();
1256      Send(reply);
1257    }
1258
1259    // If this is a SwapBuffers, we need to ack it if we're not going to handle
1260    // it so that the GPU process doesn't get stuck in unscheduled state.
1261    bool msg_is_ok = true;
1262    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1263      IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
1264                          OnCompositorSurfaceBuffersSwappedNoHost)
1265    IPC_END_MESSAGE_MAP_EX()
1266    return true;
1267  }
1268  return listener->OnMessageReceived(msg);
1269}
1270
1271void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) {
1272#if defined(IPC_MESSAGE_LOG_ENABLED)
1273  Send(new ChildProcessMsg_SetIPCLoggingEnabled(
1274      IPC::Logging::GetInstance()->Enabled()));
1275#endif
1276
1277  tracked_objects::ThreadData::Status status =
1278      tracked_objects::ThreadData::status();
1279  Send(new ChildProcessMsg_SetProfilerStatus(status));
1280}
1281
1282void RenderProcessHostImpl::OnChannelError() {
1283  ProcessDied(true /* already_dead */);
1284}
1285
1286BrowserContext* RenderProcessHostImpl::GetBrowserContext() const {
1287  return browser_context_;
1288}
1289
1290bool RenderProcessHostImpl::InSameStoragePartition(
1291    StoragePartition* partition) const {
1292  return storage_partition_impl_ == partition;
1293}
1294
1295int RenderProcessHostImpl::GetID() const {
1296  return id_;
1297}
1298
1299bool RenderProcessHostImpl::HasConnection() const {
1300  return channel_.get() != NULL;
1301}
1302
1303void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1304  ignore_input_events_ = ignore_input_events;
1305}
1306
1307bool RenderProcessHostImpl::IgnoreInputEvents() const {
1308  return ignore_input_events_;
1309}
1310
1311void RenderProcessHostImpl::Cleanup() {
1312  // When no other owners of this object, we can delete ourselves
1313  if (listeners_.IsEmpty()) {
1314    DCHECK_EQ(0, pending_views_);
1315    NotificationService::current()->Notify(
1316        NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1317        Source<RenderProcessHost>(this),
1318        NotificationService::NoDetails());
1319
1320    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1321    deleting_soon_ = true;
1322    // It's important not to wait for the DeleteTask to delete the channel
1323    // proxy. Kill it off now. That way, in case the profile is going away, the
1324    // rest of the objects attached to this RenderProcessHost start going
1325    // away first, since deleting the channel proxy will post a
1326    // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
1327    channel_.reset();
1328    gpu_message_filter_ = NULL;
1329
1330    // Remove ourself from the list of renderer processes so that we can't be
1331    // reused in between now and when the Delete task runs.
1332    UnregisterHost(GetID());
1333  }
1334}
1335
1336void RenderProcessHostImpl::AddPendingView() {
1337  pending_views_++;
1338}
1339
1340void RenderProcessHostImpl::RemovePendingView() {
1341  DCHECK(pending_views_);
1342  pending_views_--;
1343}
1344
1345void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
1346  sudden_termination_allowed_ = enabled;
1347}
1348
1349bool RenderProcessHostImpl::SuddenTerminationAllowed() const {
1350  return sudden_termination_allowed_;
1351}
1352
1353base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const {
1354  return base::TimeTicks::Now() - child_process_activity_time_;
1355}
1356
1357void RenderProcessHostImpl::SurfaceUpdated(int32 surface_id) {
1358  if (!gpu_message_filter_)
1359    return;
1360  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1361      &GpuMessageFilter::SurfaceUpdated,
1362      gpu_message_filter_,
1363      surface_id));
1364}
1365
1366void RenderProcessHostImpl::ResumeRequestsForView(int route_id) {
1367  widget_helper_->ResumeRequestsForView(route_id);
1368}
1369
1370IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
1371  return channel_.get();
1372}
1373
1374bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) {
1375  if (static_cast<size_t>(GetActiveViewCount()) == count)
1376    return FastShutdownIfPossible();
1377  return false;
1378}
1379
1380bool RenderProcessHostImpl::FastShutdownStarted() const {
1381  return fast_shutdown_started_;
1382}
1383
1384// static
1385void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
1386  g_all_hosts.Get().AddWithID(host, host_id);
1387}
1388
1389// static
1390void RenderProcessHostImpl::UnregisterHost(int host_id) {
1391  RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id);
1392  if (!host)
1393    return;
1394
1395  g_all_hosts.Get().Remove(host_id);
1396
1397  // Look up the map of site to process for the given browser_context,
1398  // in case we need to remove this process from it.  It will be registered
1399  // under any sites it rendered that use process-per-site mode.
1400  SiteProcessMap* map =
1401      GetSiteProcessMapForBrowserContext(host->GetBrowserContext());
1402  map->RemoveProcess(host);
1403}
1404
1405// static
1406bool RenderProcessHostImpl::IsSuitableHost(
1407    RenderProcessHost* host,
1408    BrowserContext* browser_context,
1409    const GURL& site_url) {
1410  if (run_renderer_in_process())
1411    return true;
1412
1413  if (host->GetBrowserContext() != browser_context)
1414    return false;
1415
1416  // Check whether the given host and the intended site_url will be using the
1417  // same StoragePartition, since a RenderProcessHost can only support a single
1418  // StoragePartition.  This is relevant for packaged apps, browser tags, and
1419  // isolated sites.
1420  StoragePartition* dest_partition =
1421      BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
1422  if (!host->InSameStoragePartition(dest_partition))
1423    return false;
1424
1425  // All URLs are suitable if this is associated with a guest renderer process.
1426  // TODO(fsamuel, creis): Further validation is needed to ensure that only
1427  // normal web URLs are permitted in guest processes. We need to investigate
1428  // where this validation should happen.
1429  if (host->IsGuest())
1430    return true;
1431
1432  if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme))
1433    return false;
1434
1435  if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1436          host->GetID()) !=
1437      WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1438          browser_context, site_url)) {
1439    return false;
1440  }
1441
1442  return GetContentClient()->browser()->IsSuitableHost(host, site_url);
1443}
1444
1445// static
1446bool RenderProcessHost::run_renderer_in_process() {
1447  return g_run_renderer_in_process_;
1448}
1449
1450// static
1451void RenderProcessHost::SetRunRendererInProcess(bool value) {
1452  g_run_renderer_in_process_ = value;
1453
1454  CommandLine* command_line = CommandLine::ForCurrentProcess();
1455  if (value && !command_line->HasSwitch(switches::kLang)) {
1456    // Modify the current process' command line to include the browser locale,
1457    // as the renderer expects this flag to be set.
1458    const std::string locale =
1459        GetContentClient()->browser()->GetApplicationLocale();
1460    command_line->AppendSwitchASCII(switches::kLang, locale);
1461  }
1462}
1463
1464RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
1465  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1466  return iterator(g_all_hosts.Pointer());
1467}
1468
1469// static
1470RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
1471  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1472  return g_all_hosts.Get().Lookup(render_process_id);
1473}
1474
1475// static
1476bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1477    BrowserContext* browser_context, const GURL& url) {
1478  // Experimental:
1479  // If --enable-strict-site-isolation or --site-per-process is enabled, do not
1480  // try to reuse renderer processes when over the limit.  (We could allow pages
1481  // from the same site to share, if we knew what the given process was
1482  // dedicated to.  Allowing no sharing is simpler for now.)  This may cause
1483  // resource exhaustion issues if too many sites are open at once.
1484  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1485  if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
1486      command_line.HasSwitch(switches::kSitePerProcess))
1487    return false;
1488
1489  if (run_renderer_in_process())
1490    return true;
1491
1492  // NOTE: Sometimes it's necessary to create more render processes than
1493  //       GetMaxRendererProcessCount(), for instance when we want to create
1494  //       a renderer process for a browser context that has no existing
1495  //       renderers. This is OK in moderation, since the
1496  //       GetMaxRendererProcessCount() is conservative.
1497  if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount())
1498    return true;
1499
1500  return GetContentClient()->browser()->
1501      ShouldTryToUseExistingProcessHost(browser_context, url);
1502}
1503
1504// static
1505RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
1506    BrowserContext* browser_context,
1507    const GURL& site_url) {
1508  // First figure out which existing renderers we can use.
1509  std::vector<RenderProcessHost*> suitable_renderers;
1510  suitable_renderers.reserve(g_all_hosts.Get().size());
1511
1512  iterator iter(AllHostsIterator());
1513  while (!iter.IsAtEnd()) {
1514    if (RenderProcessHostImpl::IsSuitableHost(
1515            iter.GetCurrentValue(),
1516            browser_context, site_url))
1517      suitable_renderers.push_back(iter.GetCurrentValue());
1518
1519    iter.Advance();
1520  }
1521
1522  // Now pick a random suitable renderer, if we have any.
1523  if (!suitable_renderers.empty()) {
1524    int suitable_count = static_cast<int>(suitable_renderers.size());
1525    int random_index = base::RandInt(0, suitable_count - 1);
1526    return suitable_renderers[random_index];
1527  }
1528
1529  return NULL;
1530}
1531
1532// static
1533bool RenderProcessHost::ShouldUseProcessPerSite(
1534    BrowserContext* browser_context,
1535    const GURL& url) {
1536  // Returns true if we should use the process-per-site model.  This will be
1537  // the case if the --process-per-site switch is specified, or in
1538  // process-per-site-instance for particular sites (e.g., WebUI).
1539  // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
1540  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1541  if (command_line.HasSwitch(switches::kProcessPerSite))
1542    return true;
1543
1544  // We want to consolidate particular sites like WebUI even when we are using
1545  // the process-per-tab or process-per-site-instance models.
1546  // Note: DevTools pages have WebUI type but should not reuse the same host.
1547  if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
1548          browser_context, url) &&
1549      !url.SchemeIs(chrome::kChromeDevToolsScheme)) {
1550    return true;
1551  }
1552
1553  // Otherwise let the content client decide, defaulting to false.
1554  return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context,
1555                                                                url);
1556}
1557
1558// static
1559RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
1560    BrowserContext* browser_context,
1561    const GURL& url) {
1562  // Look up the map of site to process for the given browser_context.
1563  SiteProcessMap* map =
1564      GetSiteProcessMapForBrowserContext(browser_context);
1565
1566  // See if we have an existing process with appropriate bindings for this site.
1567  // If not, the caller should create a new process and register it.
1568  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1569      .possibly_invalid_spec();
1570  RenderProcessHost* host = map->FindProcess(site);
1571  if (host && !IsSuitableHost(host, browser_context, url)) {
1572    // The registered process does not have an appropriate set of bindings for
1573    // the url.  Remove it from the map so we can register a better one.
1574    RecordAction(UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
1575    map->RemoveProcess(host);
1576    host = NULL;
1577  }
1578
1579  return host;
1580}
1581
1582void RenderProcessHostImpl::RegisterProcessHostForSite(
1583    BrowserContext* browser_context,
1584    RenderProcessHost* process,
1585    const GURL& url) {
1586  // Look up the map of site to process for the given browser_context.
1587  SiteProcessMap* map =
1588      GetSiteProcessMapForBrowserContext(browser_context);
1589
1590  // Only register valid, non-empty sites.  Empty or invalid sites will not
1591  // use process-per-site mode.  We cannot check whether the process has
1592  // appropriate bindings here, because the bindings have not yet been granted.
1593  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1594      .possibly_invalid_spec();
1595  if (!site.empty())
1596    map->RegisterProcess(site, process);
1597}
1598
1599base::MessageLoop*
1600    RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
1601  return g_in_process_thread;
1602}
1603
1604void RenderProcessHostImpl::ProcessDied(bool already_dead) {
1605  // Our child process has died.  If we didn't expect it, it's a crash.
1606  // In any case, we need to let everyone know it's gone.
1607  // The OnChannelError notification can fire multiple times due to nested sync
1608  // calls to a renderer. If we don't have a valid channel here it means we
1609  // already handled the error.
1610
1611  // child_process_launcher_ can be NULL in single process mode or if fast
1612  // termination happened.
1613  int exit_code = 0;
1614  base::TerminationStatus status =
1615      child_process_launcher_.get() ?
1616      child_process_launcher_->GetChildTerminationStatus(already_dead,
1617                                                         &exit_code) :
1618      base::TERMINATION_STATUS_NORMAL_TERMINATION;
1619
1620  RendererClosedDetails details(GetHandle(), status, exit_code);
1621  NotificationService::current()->Notify(
1622      NOTIFICATION_RENDERER_PROCESS_CLOSED,
1623      Source<RenderProcessHost>(this),
1624      Details<RendererClosedDetails>(&details));
1625
1626  child_process_launcher_.reset();
1627  channel_.reset();
1628  gpu_message_filter_ = NULL;
1629
1630  IDMap<IPC::Listener>::iterator iter(&listeners_);
1631  while (!iter.IsAtEnd()) {
1632    iter.GetCurrentValue()->OnMessageReceived(
1633        ViewHostMsg_RenderProcessGone(iter.GetCurrentKey(),
1634                                      static_cast<int>(status),
1635                                      exit_code));
1636    iter.Advance();
1637  }
1638
1639  ClearTransportDIBCache();
1640
1641  // this object is not deleted at this point and may be reused later.
1642  // TODO(darin): clean this up
1643}
1644
1645int RenderProcessHostImpl::GetActiveViewCount() {
1646  int num_active_views = 0;
1647  RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts();
1648  for (size_t i = 0; i < widgets.size(); ++i) {
1649    // Count only RenderWidgetHosts in this process.
1650    if (widgets[i]->GetProcess()->GetID() == GetID())
1651      num_active_views++;
1652  }
1653  return num_active_views;
1654}
1655
1656// Frame subscription API for this class is for accelerated composited path
1657// only. These calls are redirected to GpuMessageFilter.
1658void RenderProcessHostImpl::BeginFrameSubscription(
1659    int route_id,
1660    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1661  if (!gpu_message_filter_)
1662    return;
1663  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1664      &GpuMessageFilter::BeginFrameSubscription,
1665      gpu_message_filter_,
1666      route_id, base::Passed(&subscriber)));
1667}
1668
1669void RenderProcessHostImpl::EndFrameSubscription(int route_id) {
1670  if (!gpu_message_filter_)
1671    return;
1672  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1673      &GpuMessageFilter::EndFrameSubscription,
1674      gpu_message_filter_,
1675      route_id));
1676}
1677
1678void RenderProcessHostImpl::OnShutdownRequest() {
1679  // Don't shut down if there are active RenderViews, or if there are pending
1680  // RenderViews being swapped back in.
1681  // In single process mode, we never shutdown the renderer.
1682  int num_active_views = GetActiveViewCount();
1683  if (pending_views_ || num_active_views > 0 || run_renderer_in_process())
1684    return;
1685
1686  // Notify any contents that might have swapped out renderers from this
1687  // process. They should not attempt to swap them back in.
1688  NotificationService::current()->Notify(
1689      NOTIFICATION_RENDERER_PROCESS_CLOSING,
1690      Source<RenderProcessHost>(this),
1691      NotificationService::NoDetails());
1692
1693  Send(new ChildProcessMsg_Shutdown());
1694}
1695
1696void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
1697  SetSuddenTerminationAllowed(enabled);
1698}
1699
1700void RenderProcessHostImpl::OnDumpHandlesDone() {
1701  Cleanup();
1702}
1703
1704void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
1705  // Note: we always set the backgrounded_ value.  If the process is NULL
1706  // (and hence hasn't been created yet), we will set the process priority
1707  // later when we create the process.
1708  backgrounded_ = backgrounded;
1709  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1710    return;
1711
1712#if defined(OS_WIN)
1713  // The cbstext.dll loads as a global GetMessage hook in the browser process
1714  // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
1715  // background thread. If the UI thread invokes this API just when it is
1716  // intercepted the stack is messed up on return from the interceptor
1717  // which causes random crashes in the browser process. Our hack for now
1718  // is to not invoke the SetPriorityClass API if the dll is loaded.
1719  if (GetModuleHandle(L"cbstext.dll"))
1720    return;
1721#endif  // OS_WIN
1722
1723  child_process_launcher_->SetProcessBackgrounded(backgrounded);
1724}
1725
1726void RenderProcessHostImpl::OnProcessLaunched() {
1727  // No point doing anything, since this object will be destructed soon.  We
1728  // especially don't want to send the RENDERER_PROCESS_CREATED notification,
1729  // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
1730  // properly cleanup.
1731  if (deleting_soon_)
1732    return;
1733
1734  if (child_process_launcher_) {
1735    if (!child_process_launcher_->GetHandle()) {
1736      OnChannelError();
1737      return;
1738    }
1739
1740    child_process_launcher_->SetProcessBackgrounded(backgrounded_);
1741  }
1742
1743  // NOTE: This needs to be before sending queued messages because
1744  // ExtensionService uses this notification to initialize the renderer process
1745  // with state that must be there before any JavaScript executes.
1746  //
1747  // The queued messages contain such things as "navigate". If this notification
1748  // was after, we can end up executing JavaScript before the initialization
1749  // happens.
1750  NotificationService::current()->Notify(
1751      NOTIFICATION_RENDERER_PROCESS_CREATED,
1752      Source<RenderProcessHost>(this),
1753      NotificationService::NoDetails());
1754
1755  while (!queued_messages_.empty()) {
1756    Send(queued_messages_.front());
1757    queued_messages_.pop();
1758  }
1759}
1760
1761void RenderProcessHostImpl::OnUserMetricsRecordAction(
1762    const std::string& action) {
1763  RecordComputedAction(action);
1764}
1765
1766void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
1767  MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
1768}
1769
1770void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
1771      const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1772  TRACE_EVENT0("renderer_host",
1773               "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
1774  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1775  ack_params.sync_point = 0;
1776  RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1777                                                 params.gpu_process_host_id,
1778                                                 ack_params);
1779}
1780
1781void RenderProcessHostImpl::OnGpuSwitching() {
1782  // We are updating all widgets including swapped out ones.
1783  RenderWidgetHost::List widgets =
1784      RenderWidgetHostImpl::GetAllRenderWidgetHosts();
1785  for (size_t i = 0; i < widgets.size(); ++i) {
1786    if (!widgets[i]->IsRenderView())
1787      continue;
1788
1789    // Skip widgets in other processes.
1790    if (widgets[i]->GetProcess()->GetID() != GetID())
1791      continue;
1792
1793    RenderViewHost* rvh = RenderViewHost::From(widgets[i]);
1794    rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
1795  }
1796}
1797
1798}  // namespace content
1799