render_process_host_impl.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/rand_util.h"
31#include "base/stl_util.h"
32#include "base/strings/string_util.h"
33#include "base/supports_user_data.h"
34#include "base/sys_info.h"
35#include "base/threading/thread.h"
36#include "base/threading/thread_restrictions.h"
37#include "base/tracked_objects.h"
38#include "cc/base/switches.h"
39#include "content/browser/appcache/appcache_dispatcher_host.h"
40#include "content/browser/appcache/chrome_appcache_service.h"
41#include "content/browser/browser_main.h"
42#include "content/browser/browser_main_loop.h"
43#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
44#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
45#include "content/browser/child_process_security_policy_impl.h"
46#include "content/browser/device_orientation/device_motion_message_filter.h"
47#include "content/browser/device_orientation/device_orientation_message_filter.h"
48#include "content/browser/dom_storage/dom_storage_context_wrapper.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/frame_host/render_frame_message_filter.h"
54#include "content/browser/gpu/compositor_util.h"
55#include "content/browser/gpu/gpu_data_manager_impl.h"
56#include "content/browser/gpu/gpu_process_host.h"
57#include "content/browser/gpu/shader_disk_cache.h"
58#include "content/browser/histogram_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/android/browser_demuxer_android.h"
64#include "content/browser/media/capture/audio_mirroring_manager.h"
65#include "content/browser/media/media_internals.h"
66#include "content/browser/message_port_message_filter.h"
67#include "content/browser/mime_registry_message_filter.h"
68#include "content/browser/plugin_service_impl.h"
69#include "content/browser/profiler_message_filter.h"
70#include "content/browser/quota_dispatcher_host.h"
71#include "content/browser/renderer_host/clipboard_message_filter.h"
72#include "content/browser/renderer_host/database_message_filter.h"
73#include "content/browser/renderer_host/file_utilities_message_filter.h"
74#include "content/browser/renderer_host/gamepad_browser_message_filter.h"
75#include "content/browser/renderer_host/gpu_message_filter.h"
76#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
77#include "content/browser/renderer_host/media/audio_renderer_host.h"
78#include "content/browser/renderer_host/media/device_request_message_filter.h"
79#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
80#include "content/browser/renderer_host/media/midi_dispatcher_host.h"
81#include "content/browser/renderer_host/media/midi_host.h"
82#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
83#include "content/browser/renderer_host/media/video_capture_host.h"
84#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
85#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
86#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
87#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
88#include "content/browser/renderer_host/render_message_filter.h"
89#include "content/browser/renderer_host/render_view_host_delegate.h"
90#include "content/browser/renderer_host/render_view_host_impl.h"
91#include "content/browser/renderer_host/render_widget_helper.h"
92#include "content/browser/renderer_host/render_widget_host_impl.h"
93#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
94#include "content/browser/renderer_host/text_input_client_message_filter.h"
95#include "content/browser/renderer_host/websocket_dispatcher_host.h"
96#include "content/browser/resolve_proxy_msg_helper.h"
97#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
98#include "content/browser/service_worker/service_worker_context_wrapper.h"
99#include "content/browser/service_worker/service_worker_dispatcher_host.h"
100#include "content/browser/shared_worker/shared_worker_message_filter.h"
101#include "content/browser/speech/input_tag_speech_dispatcher_host.h"
102#include "content/browser/speech/speech_recognition_dispatcher_host.h"
103#include "content/browser/storage_partition_impl.h"
104#include "content/browser/streams/stream_context.h"
105#include "content/browser/tracing/trace_message_filter.h"
106#include "content/browser/vibration/vibration_message_filter.h"
107#include "content/browser/webui/web_ui_controller_factory_registry.h"
108#include "content/browser/worker_host/worker_message_filter.h"
109#include "content/browser/worker_host/worker_storage_partition.h"
110#include "content/common/child_process_host_impl.h"
111#include "content/common/child_process_messages.h"
112#include "content/common/content_switches_internal.h"
113#include "content/common/gpu/gpu_messages.h"
114#include "content/common/resource_messages.h"
115#include "content/common/view_messages.h"
116#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
117#include "content/public/browser/browser_context.h"
118#include "content/public/browser/content_browser_client.h"
119#include "content/public/browser/notification_service.h"
120#include "content/public/browser/notification_types.h"
121#include "content/public/browser/render_process_host_factory.h"
122#include "content/public/browser/render_process_host_observer.h"
123#include "content/public/browser/render_widget_host.h"
124#include "content/public/browser/render_widget_host_iterator.h"
125#include "content/public/browser/resource_context.h"
126#include "content/public/browser/user_metrics.h"
127#include "content/public/browser/worker_service.h"
128#include "content/public/common/content_constants.h"
129#include "content/public/common/content_switches.h"
130#include "content/public/common/process_type.h"
131#include "content/public/common/result_codes.h"
132#include "content/public/common/sandboxed_process_launcher_delegate.h"
133#include "content/public/common/url_constants.h"
134#include "gpu/command_buffer/service/gpu_switches.h"
135#include "ipc/ipc_channel.h"
136#include "ipc/ipc_logging.h"
137#include "ipc/ipc_switches.h"
138#include "media/base/media_switches.h"
139#include "net/url_request/url_request_context_getter.h"
140#include "ppapi/shared_impl/ppapi_switches.h"
141#include "ui/base/ui_base_switches.h"
142#include "ui/events/event_switches.h"
143#include "ui/gfx/switches.h"
144#include "ui/gl/gl_switches.h"
145#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
146#include "webkit/common/resource_type.h"
147
148#if defined(OS_WIN)
149#include "base/win/scoped_com_initializer.h"
150#include "content/common/font_cache_dispatcher_win.h"
151#include "content/common/sandbox_win.h"
152#endif
153
154#if defined(ENABLE_WEBRTC)
155#include "content/browser/media/webrtc_internals.h"
156#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
157#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
158#include "content/common/media/media_stream_messages.h"
159#endif
160
161#include "third_party/skia/include/core/SkBitmap.h"
162
163extern bool g_exited_main_message_loop;
164
165static const char* kSiteProcessMapKeyName = "content_site_process_map";
166
167namespace content {
168namespace {
169
170void CacheShaderInfo(int32 id, base::FilePath path) {
171  ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
172}
173
174void RemoveShaderInfo(int32 id) {
175  ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id);
176}
177
178net::URLRequestContext* GetRequestContext(
179    scoped_refptr<net::URLRequestContextGetter> request_context,
180    scoped_refptr<net::URLRequestContextGetter> media_request_context,
181    ResourceType::Type resource_type) {
182  // If the request has resource type of ResourceType::MEDIA, we use a request
183  // context specific to media for handling it because these resources have
184  // specific needs for caching.
185  if (resource_type == ResourceType::MEDIA)
186    return media_request_context->GetURLRequestContext();
187  return request_context->GetURLRequestContext();
188}
189
190void GetContexts(
191    ResourceContext* resource_context,
192    scoped_refptr<net::URLRequestContextGetter> request_context,
193    scoped_refptr<net::URLRequestContextGetter> media_request_context,
194    const ResourceHostMsg_Request& request,
195    ResourceContext** resource_context_out,
196    net::URLRequestContext** request_context_out) {
197  *resource_context_out = resource_context;
198  *request_context_out =
199      GetRequestContext(request_context, media_request_context,
200                        request.resource_type);
201}
202
203#if defined(ENABLE_WEBRTC)
204// Creates a file used for diagnostic echo canceller recordings for handing
205// over to the renderer.
206IPC::PlatformFileForTransit CreateAecDumpFileForProcess(
207    base::FilePath file_path,
208    base::ProcessHandle process) {
209  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
210  base::PlatformFileError error = base::PLATFORM_FILE_OK;
211  base::PlatformFile aec_dump_file = base::CreatePlatformFile(
212      file_path,
213      base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_APPEND,
214      NULL,
215      &error);
216  if (error != base::PLATFORM_FILE_OK) {
217    VLOG(1) << "Could not open AEC dump file, error=" << error;
218    return IPC::InvalidPlatformFileForTransit();
219  }
220  return IPC::GetFileHandleForProcess(aec_dump_file, process, true);
221}
222
223// Does nothing. Just to avoid races between enable and disable.
224void DisableAecDumpOnFileThread() {
225  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
226}
227#endif
228
229// the global list of all renderer processes
230base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
231    g_all_hosts = LAZY_INSTANCE_INITIALIZER;
232
233base::LazyInstance<scoped_refptr<BrowserPluginGeolocationPermissionContext> >
234    g_browser_plugin_geolocation_context = LAZY_INSTANCE_INITIALIZER;
235
236// Map of site to process, to ensure we only have one RenderProcessHost per
237// site in process-per-site mode.  Each map is specific to a BrowserContext.
238class SiteProcessMap : public base::SupportsUserData::Data {
239 public:
240  typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap;
241  SiteProcessMap() {}
242
243  void RegisterProcess(const std::string& site, RenderProcessHost* process) {
244    map_[site] = process;
245  }
246
247  RenderProcessHost* FindProcess(const std::string& site) {
248    SiteToProcessMap::iterator i = map_.find(site);
249    if (i != map_.end())
250      return i->second;
251    return NULL;
252  }
253
254  void RemoveProcess(RenderProcessHost* host) {
255    // Find all instances of this process in the map, then separately remove
256    // them.
257    std::set<std::string> sites;
258    for (SiteToProcessMap::const_iterator i = map_.begin();
259         i != map_.end();
260         i++) {
261      if (i->second == host)
262        sites.insert(i->first);
263    }
264    for (std::set<std::string>::iterator i = sites.begin();
265         i != sites.end();
266         i++) {
267      SiteToProcessMap::iterator iter = map_.find(*i);
268      if (iter != map_.end()) {
269        DCHECK_EQ(iter->second, host);
270        map_.erase(iter);
271      }
272    }
273  }
274
275 private:
276  SiteToProcessMap map_;
277};
278
279// Find the SiteProcessMap specific to the given context.
280SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
281  DCHECK(context);
282  SiteProcessMap* map = static_cast<SiteProcessMap*>(
283      context->GetUserData(kSiteProcessMapKeyName));
284  if (!map) {
285    map = new SiteProcessMap();
286    context->SetUserData(kSiteProcessMapKeyName, map);
287  }
288  return map;
289}
290
291// NOTE: changes to this class need to be reviewed by the security team.
292class RendererSandboxedProcessLauncherDelegate
293    : public content::SandboxedProcessLauncherDelegate {
294 public:
295  RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel)
296#if defined(OS_POSIX)
297       : ipc_fd_(channel->TakeClientFileDescriptor())
298#endif  // OS_POSIX
299  {}
300
301  virtual ~RendererSandboxedProcessLauncherDelegate() {}
302
303#if defined(OS_WIN)
304  virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
305                              bool* success) {
306    AddBaseHandleClosePolicy(policy);
307    GetContentClient()->browser()->PreSpawnRenderer(policy, success);
308  }
309
310#elif defined(OS_POSIX)
311  virtual bool ShouldUseZygote() OVERRIDE {
312    const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
313    CommandLine::StringType renderer_prefix =
314        browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
315    return renderer_prefix.empty();
316  }
317  virtual int GetIpcFd() OVERRIDE {
318    return ipc_fd_;
319  }
320#endif  // OS_WIN
321
322 private:
323#if defined(OS_POSIX)
324  int ipc_fd_;
325#endif  // OS_POSIX
326};
327
328}  // namespace
329
330RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
331
332void RenderProcessHost::RegisterRendererMainThreadFactory(
333    RendererMainThreadFactoryFunction create) {
334  g_renderer_main_thread_factory = create;
335}
336
337base::MessageLoop* g_in_process_thread;
338
339base::MessageLoop*
340    RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
341  return g_in_process_thread;
342}
343
344// Stores the maximum number of renderer processes the content module can
345// create.
346static size_t g_max_renderer_count_override = 0;
347
348// static
349size_t RenderProcessHost::GetMaxRendererProcessCount() {
350  if (g_max_renderer_count_override)
351    return g_max_renderer_count_override;
352
353  // Defines the maximum number of renderer processes according to the
354  // amount of installed memory as reported by the OS. The calculation
355  // assumes that you want the renderers to use half of the installed
356  // RAM and assuming that each WebContents uses ~40MB.
357  // If you modify this assumption, you need to adjust the
358  // ThirtyFourTabs test to match the expected number of processes.
359  //
360  // With the given amounts of installed memory below on a 32-bit CPU,
361  // the maximum renderer count will roughly be as follows:
362  //
363  //   128 MB -> 3
364  //   512 MB -> 6
365  //  1024 MB -> 12
366  //  4096 MB -> 51
367  // 16384 MB -> 82 (kMaxRendererProcessCount)
368
369  static size_t max_count = 0;
370  if (!max_count) {
371    const size_t kEstimatedWebContentsMemoryUsage =
372#if defined(ARCH_CPU_64_BITS)
373        60;  // In MB
374#else
375        40;  // In MB
376#endif
377    max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
378    max_count /= kEstimatedWebContentsMemoryUsage;
379
380    const size_t kMinRendererProcessCount = 3;
381    max_count = std::max(max_count, kMinRendererProcessCount);
382    max_count = std::min(max_count, kMaxRendererProcessCount);
383  }
384  return max_count;
385}
386
387// static
388bool g_run_renderer_in_process_ = false;
389
390// static
391void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
392  g_max_renderer_count_override = count;
393}
394
395RenderProcessHostImpl::RenderProcessHostImpl(
396    BrowserContext* browser_context,
397    StoragePartitionImpl* storage_partition_impl,
398    bool supports_browser_plugin,
399    bool is_guest)
400    : fast_shutdown_started_(false),
401      deleting_soon_(false),
402#ifndef NDEBUG
403      is_self_deleted_(false),
404#endif
405      pending_views_(0),
406      visible_widgets_(0),
407      backgrounded_(true),
408      cached_dibs_cleaner_(FROM_HERE,
409                           base::TimeDelta::FromSeconds(5),
410                           this,
411                           &RenderProcessHostImpl::ClearTransportDIBCache),
412      is_initialized_(false),
413      id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
414      browser_context_(browser_context),
415      storage_partition_impl_(storage_partition_impl),
416      sudden_termination_allowed_(true),
417      ignore_input_events_(false),
418      supports_browser_plugin_(supports_browser_plugin),
419      is_guest_(is_guest),
420      gpu_observer_registered_(false),
421      delayed_cleanup_needed_(false),
422      within_process_died_observer_(false),
423      power_monitor_broadcaster_(this),
424      geolocation_dispatcher_host_(NULL),
425      weak_factory_(this),
426      screen_orientation_dispatcher_host_(NULL),
427      worker_ref_count_(0) {
428  widget_helper_ = new RenderWidgetHelper();
429
430  ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID());
431
432  CHECK(!g_exited_main_message_loop);
433  RegisterHost(GetID(), this);
434  g_all_hosts.Get().set_check_on_null_data(true);
435  // Initialize |child_process_activity_time_| to a reasonable value.
436  mark_child_process_activity_time();
437
438  if (!GetBrowserContext()->IsOffTheRecord() &&
439      !CommandLine::ForCurrentProcess()->HasSwitch(
440          switches::kDisableGpuShaderDiskCache)) {
441    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
442                            base::Bind(&CacheShaderInfo, GetID(),
443                                       storage_partition_impl_->GetPath()));
444  }
445
446  // Note: When we create the RenderProcessHostImpl, it's technically
447  //       backgrounded, because it has no visible listeners.  But the process
448  //       doesn't actually exist yet, so we'll Background it later, after
449  //       creation.
450}
451
452// static
453void RenderProcessHostImpl::ShutDownInProcessRenderer() {
454  DCHECK(g_run_renderer_in_process_);
455
456  switch (g_all_hosts.Pointer()->size()) {
457    case 0:
458      return;
459    case 1: {
460      RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
461          AllHostsIterator().GetCurrentValue());
462      FOR_EACH_OBSERVER(RenderProcessHostObserver,
463                        host->observers_,
464                        RenderProcessHostDestroyed(host));
465#ifndef NDEBUG
466      host->is_self_deleted_ = true;
467#endif
468      delete host;
469      return;
470    }
471    default:
472      NOTREACHED() << "There should be only one RenderProcessHost when running "
473                   << "in-process.";
474  }
475}
476
477RenderProcessHostImpl::~RenderProcessHostImpl() {
478#ifndef NDEBUG
479  DCHECK(is_self_deleted_)
480      << "RenderProcessHostImpl is destroyed by something other than itself";
481#endif
482
483  // Make sure to clean up the in-process renderer before the channel, otherwise
484  // it may still run and have its IPCs fail, causing asserts.
485  in_process_renderer_.reset();
486
487  ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
488
489  if (gpu_observer_registered_) {
490    GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
491    gpu_observer_registered_ = false;
492  }
493
494  // We may have some unsent messages at this point, but that's OK.
495  channel_.reset();
496  while (!queued_messages_.empty()) {
497    delete queued_messages_.front();
498    queued_messages_.pop();
499  }
500
501  ClearTransportDIBCache();
502  UnregisterHost(GetID());
503
504  if (!CommandLine::ForCurrentProcess()->HasSwitch(
505      switches::kDisableGpuShaderDiskCache)) {
506    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
507                            base::Bind(&RemoveShaderInfo, GetID()));
508  }
509}
510
511void RenderProcessHostImpl::EnableSendQueue() {
512  is_initialized_ = false;
513}
514
515bool RenderProcessHostImpl::Init() {
516  // calling Init() more than once does nothing, this makes it more convenient
517  // for the view host which may not be sure in some cases
518  if (channel_)
519    return true;
520
521  CommandLine::StringType renderer_prefix;
522#if defined(OS_POSIX)
523  // A command prefix is something prepended to the command line of the spawned
524  // process. It is supported only on POSIX systems.
525  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
526  renderer_prefix =
527      browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
528#endif  // defined(OS_POSIX)
529
530#if defined(OS_LINUX)
531  int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
532                                        ChildProcessHost::CHILD_NORMAL;
533#else
534  int flags = ChildProcessHost::CHILD_NORMAL;
535#endif
536
537  // Find the renderer before creating the channel so if this fails early we
538  // return without creating the channel.
539  base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags);
540  if (renderer_path.empty())
541    return false;
542
543  // Setup the IPC channel.
544  const std::string channel_id =
545      IPC::Channel::GenerateVerifiedChannelID(std::string());
546  channel_.reset(
547          new IPC::ChannelProxy(channel_id,
548                                IPC::Channel::MODE_SERVER,
549                                this,
550                                BrowserThread::GetMessageLoopProxyForThread(
551                                    BrowserThread::IO).get()));
552
553  // Call the embedder first so that their IPC filters have priority.
554  GetContentClient()->browser()->RenderProcessWillLaunch(this);
555
556  CreateMessageFilters();
557
558  if (run_renderer_in_process()) {
559    DCHECK(g_renderer_main_thread_factory);
560    // Crank up a thread and run the initialization there.  With the way that
561    // messages flow between the browser and renderer, this thread is required
562    // to prevent a deadlock in single-process mode.  Since the primordial
563    // thread in the renderer process runs the WebKit code and can sometimes
564    // make blocking calls to the UI thread (i.e. this thread), they need to run
565    // on separate threads.
566    in_process_renderer_.reset(g_renderer_main_thread_factory(channel_id));
567
568    base::Thread::Options options;
569#if defined(OS_WIN) && !defined(OS_MACOSX)
570    // In-process plugins require this to be a UI message loop.
571    options.message_loop_type = base::MessageLoop::TYPE_UI;
572#else
573    // We can't have multiple UI loops on Linux and Android, so we don't support
574    // in-process plugins.
575    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
576#endif
577    in_process_renderer_->StartWithOptions(options);
578
579    g_in_process_thread = in_process_renderer_->message_loop();
580
581    OnProcessLaunched();  // Fake a callback that the process is ready.
582  } else {
583    // Build command line for renderer.  We call AppendRendererCommandLine()
584    // first so the process type argument will appear first.
585    CommandLine* cmd_line = new CommandLine(renderer_path);
586    if (!renderer_prefix.empty())
587      cmd_line->PrependWrapper(renderer_prefix);
588    AppendRendererCommandLine(cmd_line);
589    cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
590
591    // Spawn the child process asynchronously to avoid blocking the UI thread.
592    // As long as there's no renderer prefix, we can use the zygote process
593    // at this stage.
594    child_process_launcher_.reset(new ChildProcessLauncher(
595        new RendererSandboxedProcessLauncherDelegate(channel_.get()),
596        cmd_line,
597        GetID(),
598        this));
599
600    fast_shutdown_started_ = false;
601  }
602
603  if (!gpu_observer_registered_) {
604    gpu_observer_registered_ = true;
605    GpuDataManagerImpl::GetInstance()->AddObserver(this);
606  }
607
608  is_initialized_ = true;
609  return true;
610}
611
612void RenderProcessHostImpl::CreateMessageFilters() {
613  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
614  AddFilter(new ResourceSchedulerFilter(GetID()));
615  MediaInternals* media_internals = MediaInternals::GetInstance();
616  media::AudioManager* audio_manager =
617      BrowserMainLoop::GetInstance()->audio_manager();
618  // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
619  // from guests.
620  if (supports_browser_plugin_) {
621    scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
622        new BrowserPluginMessageFilter(GetID(), IsGuest()));
623    AddFilter(bp_message_filter.get());
624  }
625
626  scoped_refptr<RenderMessageFilter> render_message_filter(
627      new RenderMessageFilter(
628          GetID(),
629          IsGuest(),
630#if defined(ENABLE_PLUGINS)
631          PluginServiceImpl::GetInstance(),
632#else
633          NULL,
634#endif
635          GetBrowserContext(),
636          GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
637          widget_helper_.get(),
638          audio_manager,
639          media_internals,
640          storage_partition_impl_->GetDOMStorageContext()));
641  AddFilter(render_message_filter.get());
642  AddFilter(
643      new RenderFrameMessageFilter(GetID(), widget_helper_.get()));
644  BrowserContext* browser_context = GetBrowserContext();
645  ResourceContext* resource_context = browser_context->GetResourceContext();
646
647  scoped_refptr<net::URLRequestContextGetter> request_context(
648      browser_context->GetRequestContextForRenderProcess(GetID()));
649  scoped_refptr<net::URLRequestContextGetter> media_request_context(
650      browser_context->GetMediaRequestContextForRenderProcess(GetID()));
651
652  ResourceMessageFilter::GetContextsCallback get_contexts_callback(
653      base::Bind(&GetContexts, browser_context->GetResourceContext(),
654                 request_context, media_request_context));
655
656  ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
657      GetID(), PROCESS_TYPE_RENDERER,
658      storage_partition_impl_->GetAppCacheService(),
659      ChromeBlobStorageContext::GetFor(browser_context),
660      storage_partition_impl_->GetFileSystemContext(),
661      storage_partition_impl_->GetServiceWorkerContext(),
662      get_contexts_callback);
663
664  AddFilter(resource_message_filter);
665  MediaStreamManager* media_stream_manager =
666      BrowserMainLoop::GetInstance()->media_stream_manager();
667  AddFilter(new AudioInputRendererHost(
668      audio_manager,
669      media_stream_manager,
670      BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
671      BrowserMainLoop::GetInstance()->user_input_monitor()));
672  // The AudioRendererHost needs to be available for lookup, so it's
673  // stashed in a member variable.
674  audio_renderer_host_ = new AudioRendererHost(
675      GetID(),
676      audio_manager,
677      BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
678      media_internals,
679      media_stream_manager);
680  AddFilter(audio_renderer_host_);
681  AddFilter(
682      new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
683  AddFilter(new MidiDispatcherHost(GetID(), browser_context));
684  AddFilter(new VideoCaptureHost(media_stream_manager));
685  AddFilter(new AppCacheDispatcherHost(
686      storage_partition_impl_->GetAppCacheService(),
687      GetID()));
688  AddFilter(new ClipboardMessageFilter);
689  AddFilter(new DOMStorageMessageFilter(
690      GetID(),
691      storage_partition_impl_->GetDOMStorageContext()));
692  AddFilter(new IndexedDBDispatcherHost(
693      storage_partition_impl_->GetIndexedDBContext()));
694
695  scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
696      new ServiceWorkerDispatcherHost(GetID());
697  service_worker_filter->Init(
698      storage_partition_impl_->GetServiceWorkerContext());
699  AddFilter(service_worker_filter);
700
701  if (IsGuest()) {
702    if (!g_browser_plugin_geolocation_context.Get().get()) {
703      g_browser_plugin_geolocation_context.Get() =
704          new BrowserPluginGeolocationPermissionContext();
705    }
706    geolocation_dispatcher_host_ = GeolocationDispatcherHost::New(
707        GetID(), g_browser_plugin_geolocation_context.Get().get());
708  } else {
709    geolocation_dispatcher_host_ = GeolocationDispatcherHost::New(
710        GetID(), browser_context->GetGeolocationPermissionContext());
711  }
712  AddFilter(geolocation_dispatcher_host_);
713  gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
714  AddFilter(gpu_message_filter_);
715#if defined(ENABLE_WEBRTC)
716  AddFilter(new WebRTCIdentityServiceHost(
717      GetID(), storage_partition_impl_->GetWebRTCIdentityStore()));
718  peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
719  AddFilter(peer_connection_tracker_host_.get());
720  AddFilter(new MediaStreamDispatcherHost(
721      GetID(),
722      browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
723      media_stream_manager));
724  AddFilter(
725      new DeviceRequestMessageFilter(resource_context, media_stream_manager));
726  AddFilter(new MediaStreamTrackMetricsHost());
727#endif
728#if defined(ENABLE_PLUGINS)
729  AddFilter(new PepperRendererConnection(GetID()));
730#endif
731#if defined(ENABLE_INPUT_SPEECH)
732  AddFilter(new InputTagSpeechDispatcherHost(
733      IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext()));
734#endif
735  AddFilter(new SpeechRecognitionDispatcherHost(
736      IsGuest(), GetID(), storage_partition_impl_->GetURLRequestContext()));
737  AddFilter(new FileAPIMessageFilter(
738      GetID(),
739      storage_partition_impl_->GetURLRequestContext(),
740      storage_partition_impl_->GetFileSystemContext(),
741      ChromeBlobStorageContext::GetFor(browser_context),
742      StreamContext::GetFor(browser_context)));
743  AddFilter(new FileUtilitiesMessageFilter(GetID()));
744  AddFilter(new MimeRegistryMessageFilter());
745  AddFilter(new DatabaseMessageFilter(
746      storage_partition_impl_->GetDatabaseTracker()));
747#if defined(OS_MACOSX)
748  AddFilter(new TextInputClientMessageFilter(GetID()));
749#elif defined(OS_WIN)
750  channel_->AddFilter(new FontCacheDispatcher());
751#elif defined(OS_ANDROID)
752  browser_demuxer_android_ = new BrowserDemuxerAndroid();
753  AddFilter(browser_demuxer_android_);
754#endif
755
756  SocketStreamDispatcherHost::GetRequestContextCallback
757      request_context_callback(
758          base::Bind(&GetRequestContext, request_context,
759                     media_request_context));
760
761  SocketStreamDispatcherHost* socket_stream_dispatcher_host =
762      new SocketStreamDispatcherHost(
763          GetID(), request_context_callback, resource_context);
764  AddFilter(socket_stream_dispatcher_host);
765
766  WebSocketDispatcherHost::GetRequestContextCallback
767      websocket_request_context_callback(
768          base::Bind(&GetRequestContext, request_context,
769                     media_request_context, ResourceType::SUB_RESOURCE));
770
771  AddFilter(new WebSocketDispatcherHost(websocket_request_context_callback));
772
773  message_port_message_filter_ = new MessagePortMessageFilter(
774      base::Bind(&RenderWidgetHelper::GetNextRoutingID,
775                 base::Unretained(widget_helper_.get())));
776  AddFilter(message_port_message_filter_);
777
778  // If "--enable-embedded-shared-worker" is set, we use
779  // SharedWorkerMessageFilter in stead of WorkerMessageFilter.
780  if (WorkerService::EmbeddedSharedWorkerEnabled()) {
781    AddFilter(new SharedWorkerMessageFilter(
782        GetID(),
783        resource_context,
784        WorkerStoragePartition(
785            storage_partition_impl_->GetURLRequestContext(),
786            storage_partition_impl_->GetMediaURLRequestContext(),
787            storage_partition_impl_->GetAppCacheService(),
788            storage_partition_impl_->GetQuotaManager(),
789            storage_partition_impl_->GetFileSystemContext(),
790            storage_partition_impl_->GetDatabaseTracker(),
791            storage_partition_impl_->GetIndexedDBContext(),
792            storage_partition_impl_->GetServiceWorkerContext()),
793        message_port_message_filter_));
794  } else {
795    AddFilter(new WorkerMessageFilter(
796        GetID(),
797        resource_context,
798        WorkerStoragePartition(
799            storage_partition_impl_->GetURLRequestContext(),
800            storage_partition_impl_->GetMediaURLRequestContext(),
801            storage_partition_impl_->GetAppCacheService(),
802            storage_partition_impl_->GetQuotaManager(),
803            storage_partition_impl_->GetFileSystemContext(),
804            storage_partition_impl_->GetDatabaseTracker(),
805            storage_partition_impl_->GetIndexedDBContext(),
806            storage_partition_impl_->GetServiceWorkerContext()),
807        message_port_message_filter_));
808  }
809
810#if defined(ENABLE_WEBRTC)
811  AddFilter(new P2PSocketDispatcherHost(
812      resource_context,
813      browser_context->GetRequestContextForRenderProcess(GetID())));
814#endif
815
816  AddFilter(new TraceMessageFilter());
817  AddFilter(new ResolveProxyMsgHelper(
818      browser_context->GetRequestContextForRenderProcess(GetID())));
819  AddFilter(new QuotaDispatcherHost(
820      GetID(),
821      storage_partition_impl_->GetQuotaManager(),
822      GetContentClient()->browser()->CreateQuotaPermissionContext()));
823  AddFilter(new GamepadBrowserMessageFilter());
824  AddFilter(new DeviceMotionMessageFilter());
825  AddFilter(new DeviceOrientationMessageFilter());
826  AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
827  AddFilter(new HistogramMessageFilter());
828#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
829  if (CommandLine::ForCurrentProcess()->HasSwitch(
830      switches::kEnableMemoryBenchmarking))
831    AddFilter(new MemoryBenchmarkMessageFilter());
832#endif
833  AddFilter(new VibrationMessageFilter());
834  screen_orientation_dispatcher_host_ = new ScreenOrientationDispatcherHost();
835  AddFilter(screen_orientation_dispatcher_host_);
836}
837
838int RenderProcessHostImpl::GetNextRoutingID() {
839  return widget_helper_->GetNextRoutingID();
840}
841
842
843void RenderProcessHostImpl::ResumeDeferredNavigation(
844    const GlobalRequestID& request_id) {
845  widget_helper_->ResumeDeferredNavigation(request_id);
846}
847
848void RenderProcessHostImpl::NotifyTimezoneChange() {
849  Send(new ViewMsg_TimezoneChange());
850}
851
852void RenderProcessHostImpl::AddRoute(
853    int32 routing_id,
854    IPC::Listener* listener) {
855  listeners_.AddWithID(listener, routing_id);
856}
857
858void RenderProcessHostImpl::RemoveRoute(int32 routing_id) {
859  DCHECK(listeners_.Lookup(routing_id) != NULL);
860  listeners_.Remove(routing_id);
861
862#if defined(OS_WIN)
863  // Dump the handle table if handle auditing is enabled.
864  const CommandLine& browser_command_line =
865      *CommandLine::ForCurrentProcess();
866  if (browser_command_line.HasSwitch(switches::kAuditHandles) ||
867      browser_command_line.HasSwitch(switches::kAuditAllHandles)) {
868    DumpHandles();
869
870    // We wait to close the channels until the child process has finished
871    // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone.
872    return;
873  }
874#endif
875  // Keep the one renderer thread around forever in single process mode.
876  if (!run_renderer_in_process())
877    Cleanup();
878}
879
880void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) {
881  observers_.AddObserver(observer);
882}
883
884void RenderProcessHostImpl::RemoveObserver(
885    RenderProcessHostObserver* observer) {
886  observers_.RemoveObserver(observer);
887}
888
889bool RenderProcessHostImpl::WaitForBackingStoreMsg(
890    int render_widget_id,
891    const base::TimeDelta& max_delay,
892    IPC::Message* msg) {
893  // The post task to this thread with the process id could be in queue, and we
894  // don't want to dispatch a message before then since it will need the handle.
895  if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
896    return false;
897
898  return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
899                                                max_delay, msg);
900}
901
902void RenderProcessHostImpl::ReceivedBadMessage() {
903  CommandLine* command_line = CommandLine::ForCurrentProcess();
904  if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
905    return;
906
907  if (run_renderer_in_process()) {
908    // In single process mode it is better if we don't suicide but just
909    // crash.
910    CHECK(false);
911  }
912  // We kill the renderer but don't include a NOTREACHED, because we want the
913  // browser to try to survive when it gets illegal messages from the renderer.
914  base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE,
915                    false);
916}
917
918void RenderProcessHostImpl::WidgetRestored() {
919  // Verify we were properly backgrounded.
920  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
921  visible_widgets_++;
922  SetBackgrounded(false);
923}
924
925void RenderProcessHostImpl::WidgetHidden() {
926  // On startup, the browser will call Hide
927  if (backgrounded_)
928    return;
929
930  DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
931  visible_widgets_--;
932  DCHECK_GE(visible_widgets_, 0);
933  if (visible_widgets_ == 0) {
934    DCHECK(!backgrounded_);
935    SetBackgrounded(true);
936  }
937}
938
939int RenderProcessHostImpl::VisibleWidgetCount() const {
940  return visible_widgets_;
941}
942
943bool RenderProcessHostImpl::IsGuest() const {
944  return is_guest_;
945}
946
947StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
948  return storage_partition_impl_;
949}
950
951static void AppendGpuCommandLineFlags(CommandLine* command_line) {
952  if (content::IsThreadedCompositingEnabled())
953    command_line->AppendSwitch(switches::kEnableThreadedCompositing);
954
955  if (content::IsDelegatedRendererEnabled())
956    command_line->AppendSwitch(switches::kEnableDelegatedRenderer);
957
958  if (content::IsImplSidePaintingEnabled())
959    command_line->AppendSwitch(switches::kEnableImplSidePainting);
960
961  // Appending disable-gpu-feature switches due to software rendering list.
962  GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
963  DCHECK(gpu_data_manager);
964  gpu_data_manager->AppendRendererCommandLine(command_line);
965}
966
967void RenderProcessHostImpl::AppendRendererCommandLine(
968    CommandLine* command_line) const {
969  // Pass the process type first, so it shows first in process listings.
970  command_line->AppendSwitchASCII(switches::kProcessType,
971                                  switches::kRendererProcess);
972
973  // Now send any options from our own command line we want to propagate.
974  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
975  PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
976
977  // Pass on the browser locale.
978  const std::string locale =
979      GetContentClient()->browser()->GetApplicationLocale();
980  command_line->AppendSwitchASCII(switches::kLang, locale);
981
982  // If we run base::FieldTrials, we want to pass to their state to the
983  // renderer so that it can act in accordance with each state, or record
984  // histograms relating to the base::FieldTrial states.
985  std::string field_trial_states;
986  base::FieldTrialList::StatesToString(&field_trial_states);
987  if (!field_trial_states.empty()) {
988    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
989                                    field_trial_states);
990  }
991
992  GetContentClient()->browser()->AppendExtraCommandLineSwitches(
993      command_line, GetID());
994
995  if (content::IsPinchToZoomEnabled())
996    command_line->AppendSwitch(switches::kEnablePinch);
997
998  AppendGpuCommandLineFlags(command_line);
999}
1000
1001void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
1002    const CommandLine& browser_cmd,
1003    CommandLine* renderer_cmd) const {
1004  // Propagate the following switches to the renderer command line (along
1005  // with any associated values) if present in the browser command line.
1006  static const char* const kSwitchNames[] = {
1007    switches::kAllowLoopbackInPeerConnection,
1008    switches::kAudioBufferSize,
1009    switches::kAuditAllHandles,
1010    switches::kAuditHandles,
1011    switches::kBlinkPlatformLogChannels,
1012    switches::kBlockCrossSiteDocuments,
1013    switches::kDefaultTileWidth,
1014    switches::kDefaultTileHeight,
1015    switches::kDisable3DAPIs,
1016    switches::kDisableAcceleratedCompositing,
1017    switches::kDisableAcceleratedFixedRootBackground,
1018    switches::kDisableAcceleratedVideoDecode,
1019    switches::kDisableApplicationCache,
1020    switches::kDisableBreakpad,
1021    switches::kDisableCompositingForFixedPosition,
1022    switches::kDisableCompositingForTransition,
1023    switches::kDisableDatabases,
1024    switches::kDisableDelegatedRenderer,
1025    switches::kDisableDesktopNotifications,
1026    switches::kDisableDirectNPAPIRequests,
1027    switches::kDisableFileSystem,
1028    switches::kDisableFiltersOverIPC,
1029    switches::kDisableGpu,
1030    switches::kDisableGpuCompositing,
1031    switches::kDisableGpuRasterization,
1032    switches::kDisableGpuVsync,
1033    switches::kDisableHistogramCustomizer,
1034    switches::kDisableImplSidePainting,
1035    switches::kDisableLCDText,
1036    switches::kDisableLayerSquashing,
1037    switches::kDisableLocalStorage,
1038    switches::kDisableLogging,
1039    switches::kDisableMapImage,
1040    switches::kDisableOverlayScrollbar,
1041    switches::kDisablePinch,
1042    switches::kDisablePrefixedEncryptedMedia,
1043    switches::kDisableRepaintAfterLayout,
1044    switches::kDisableSeccompFilterSandbox,
1045    switches::kDisableSessionStorage,
1046    switches::kDisableSharedWorkers,
1047    switches::kDisableSpeechInput,
1048    switches::kDisableThreadedCompositing,
1049    switches::kDisableTouchAdjustment,
1050    switches::kDisableTouchDragDrop,
1051    switches::kDisableTouchEditing,
1052    switches::kDisableUniversalAcceleratedOverflowScroll,
1053    switches::kDisableUnprefixedMediaSource,
1054    switches::kDisableWebKitMediaSource,
1055    switches::kDomAutomationController,
1056    switches::kEnableAcceleratedFixedRootBackground,
1057    switches::kEnableAcceleratedOverflowScroll,
1058    switches::kEnableAccessibilityLogging,
1059    switches::kEnableADTSStreamParser,
1060    switches::kEnableBeginFrameScheduling,
1061    switches::kEnableBleedingEdgeRenderingFastPaths,
1062    switches::kEnableBrowserPluginForAllViewTypes,
1063    switches::kEnableCompositingForFixedPosition,
1064    switches::kEnableCompositingForTransition,
1065    switches::kEnableDeferredImageDecoding,
1066    switches::kEnableDelegatedRenderer,
1067    switches::kEnableEncryptedMedia,
1068    switches::kEnableExperimentalCanvasFeatures,
1069    switches::kEnableExperimentalWebPlatformFeatures,
1070    switches::kEnableExperimentalWebSocket,
1071    switches::kEnableFastTextAutosizing,
1072    switches::kEnableGPUClientLogging,
1073    switches::kEnableGpuClientTracing,
1074    switches::kEnableGpuRasterization,
1075    switches::kEnableGPUServiceLogging,
1076    switches::kEnableHighDpiCompositingForFixedPosition,
1077    switches::kEnableHTMLImports,
1078    switches::kEnableImplSidePainting,
1079    switches::kEnableInbandTextTracks,
1080    switches::kEnableLCDText,
1081    switches::kEnableLayerSquashing,
1082    switches::kEnableLogging,
1083    switches::kEnableMP3StreamParser,
1084    switches::kEnableMapImage,
1085    switches::kEnableMemoryBenchmarking,
1086    switches::kEnableOverlayFullscreenVideo,
1087    switches::kEnableOverlayScrollbar,
1088    switches::kEnableOverscrollNotifications,
1089    switches::kEnablePinch,
1090    switches::kEnablePreparsedJsCaching,
1091    switches::kEnableRepaintAfterLayout,
1092    switches::kEnableServiceWorker,
1093    switches::kEnableSkiaBenchmarking,
1094    switches::kEnableSoftwareCompositing,
1095    switches::kEnableSpeechSynthesis,
1096    switches::kEnableStatsTable,
1097    switches::kEnableStrictSiteIsolation,
1098    switches::kEnableTargetedStyleRecalc,
1099    switches::kEnableThreadedCompositing,
1100    switches::kEnableUniversalAcceleratedOverflowScroll,
1101    switches::kEnableTouchDragDrop,
1102    switches::kEnableTouchEditing,
1103    switches::kEnableViewport,
1104    switches::kEnableViewportMeta,
1105    switches::kMainFrameResizesAreOrientationChanges,
1106    switches::kEnableVtune,
1107    switches::kEnableWebAnimationsSVG,
1108    switches::kEnableWebGLDraftExtensions,
1109    switches::kEnableWebMIDI,
1110    switches::kForceDeviceScaleFactor,
1111    switches::kForceGpuRasterization,
1112    switches::kFullMemoryCrashReport,
1113    switches::kJavaScriptFlags,
1114    switches::kLoggingLevel,
1115    switches::kMaxUntiledLayerWidth,
1116    switches::kMaxUntiledLayerHeight,
1117    switches::kMemoryMetrics,
1118    switches::kNoReferrers,
1119    switches::kNoSandbox,
1120    switches::kNumRasterThreads,
1121    switches::kPpapiInProcess,
1122    switches::kProfilerTiming,
1123    switches::kReduceSecurityForTesting,
1124    switches::kRegisterPepperPlugins,
1125    switches::kRendererAssertTest,
1126    switches::kRendererStartupDialog,
1127    switches::kShowPaintRects,
1128    switches::kSitePerProcess,
1129    switches::kStatsCollectionController,
1130    switches::kTestSandbox,
1131    switches::kTestType,
1132    switches::kTouchEvents,
1133    switches::kTraceToConsole,
1134    switches::kUseDiscardableMemory,
1135    // This flag needs to be propagated to the renderer process for
1136    // --in-process-webgl.
1137    switches::kUseGL,
1138    switches::kUseMobileUserAgent,
1139    switches::kV,
1140    switches::kVideoThreads,
1141    switches::kVModule,
1142    switches::kWebGLCommandBufferSizeKb,
1143    // Please keep these in alphabetical order. Compositor switches here should
1144    // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
1145    cc::switches::kCompositeToMailbox,
1146    cc::switches::kDisableCompositedAntialiasing,
1147    cc::switches::kDisableCompositorTouchHitTesting,
1148    cc::switches::kDisableMainFrameBeforeActivation,
1149    cc::switches::kDisableMainFrameBeforeDraw,
1150    cc::switches::kDisableThreadedAnimation,
1151    cc::switches::kEnableGpuBenchmarking,
1152    cc::switches::kEnablePinchVirtualViewport,
1153    cc::switches::kEnableMainFrameBeforeActivation,
1154    cc::switches::kEnableTopControlsPositionCalculation,
1155    cc::switches::kMaxTilesForInterestArea,
1156    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
1157    cc::switches::kShowCompositedLayerBorders,
1158    cc::switches::kShowFPSCounter,
1159    cc::switches::kShowLayerAnimationBounds,
1160    cc::switches::kShowNonOccludingRects,
1161    cc::switches::kShowOccludingRects,
1162    cc::switches::kShowPropertyChangedRects,
1163    cc::switches::kShowReplicaScreenSpaceRects,
1164    cc::switches::kShowScreenSpaceRects,
1165    cc::switches::kShowSurfaceDamageRects,
1166    cc::switches::kSlowDownRasterScaleFactor,
1167    cc::switches::kStrictLayerPropertyChangeChecking,
1168    cc::switches::kTopControlsHeight,
1169    cc::switches::kTopControlsHideThreshold,
1170    cc::switches::kTopControlsShowThreshold,
1171#if defined(ENABLE_PLUGINS)
1172    switches::kEnablePepperTesting,
1173#endif
1174#if defined(ENABLE_WEBRTC)
1175    switches::kEnableAudioTrackProcessing,
1176    switches::kDisableDeviceEnumeration,
1177    switches::kDisableWebRtcHWDecoding,
1178    switches::kDisableWebRtcHWEncoding,
1179    switches::kEnableWebRtcAecRecordings,
1180    switches::kEnableWebRtcHWVp8Encoding,
1181    switches::kEnableWebRtcTcpServerSocket,
1182#endif
1183#if defined(OS_ANDROID)
1184    switches::kDisableGestureRequirementForMediaPlayback,
1185    switches::kDisableLowEndDeviceMode,
1186    switches::kDisableWebRTC,
1187    switches::kEnableLowEndDeviceMode,
1188    switches::kEnableSpeechRecognition,
1189    switches::kMediaDrmEnableNonCompositing,
1190    switches::kNetworkCountryIso,
1191#endif
1192#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
1193    switches::kEnableWebAudio,
1194#else
1195    // Need to be able to disable webaudio on other platforms where it
1196    // is enabled by default.
1197    switches::kDisableWebAudio,
1198#endif
1199#if defined(OS_MACOSX)
1200    // Allow this to be set when invoking the browser and relayed along.
1201    switches::kEnableSandboxLogging,
1202#endif
1203#if defined(OS_POSIX)
1204    switches::kChildCleanExit,
1205#endif
1206#if defined(OS_WIN)
1207    switches::kEnableDirectWrite,
1208    switches::kEnableHighResolutionTime,
1209    switches::kHighDPISupport,
1210#endif
1211  };
1212  renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
1213                                 arraysize(kSwitchNames));
1214
1215  if (browser_cmd.HasSwitch(switches::kTraceStartup) &&
1216      BrowserMainLoop::GetInstance()->is_tracing_startup()) {
1217    // Pass kTraceStartup switch to renderer only if startup tracing has not
1218    // finished.
1219    renderer_cmd->AppendSwitchASCII(
1220        switches::kTraceStartup,
1221        browser_cmd.GetSwitchValueASCII(switches::kTraceStartup));
1222  }
1223
1224  // Disable databases in incognito mode.
1225  if (GetBrowserContext()->IsOffTheRecord() &&
1226      !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
1227    renderer_cmd->AppendSwitch(switches::kDisableDatabases);
1228#if defined(OS_ANDROID)
1229    renderer_cmd->AppendSwitch(switches::kDisableMediaHistoryLogging);
1230#endif
1231  }
1232
1233  // Enforce the extra command line flags for impl-side painting.
1234  if (IsImplSidePaintingEnabled() &&
1235      !browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding))
1236    renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding);
1237}
1238
1239base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
1240  if (run_renderer_in_process())
1241    return base::Process::Current().handle();
1242
1243  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
1244    return base::kNullProcessHandle;
1245
1246  return child_process_launcher_->GetHandle();
1247}
1248
1249bool RenderProcessHostImpl::FastShutdownIfPossible() {
1250  if (run_renderer_in_process())
1251    return false;  // Single process mode never shutdown the renderer.
1252
1253  if (!GetContentClient()->browser()->IsFastShutdownPossible())
1254    return false;
1255
1256  if (!child_process_launcher_.get() ||
1257      child_process_launcher_->IsStarting() ||
1258      !GetHandle())
1259    return false;  // Render process hasn't started or is probably crashed.
1260
1261  // Test if there's an unload listener.
1262  // NOTE: It's possible that an onunload listener may be installed
1263  // while we're shutting down, so there's a small race here.  Given that
1264  // the window is small, it's unlikely that the web page has much
1265  // state that will be lost by not calling its unload handlers properly.
1266  if (!SuddenTerminationAllowed())
1267    return false;
1268
1269  if (worker_ref_count_ != 0)
1270    return false;
1271
1272  // Set this before ProcessDied() so observers can tell if the render process
1273  // died due to fast shutdown versus another cause.
1274  fast_shutdown_started_ = true;
1275
1276  ProcessDied(false /* already_dead */);
1277  return true;
1278}
1279
1280void RenderProcessHostImpl::DumpHandles() {
1281#if defined(OS_WIN)
1282  Send(new ChildProcessMsg_DumpHandles());
1283  return;
1284#endif
1285
1286  NOTIMPLEMENTED();
1287}
1288
1289// This is a platform specific function for mapping a transport DIB given its id
1290TransportDIB* RenderProcessHostImpl::MapTransportDIB(
1291    TransportDIB::Id dib_id) {
1292#if defined(OS_WIN)
1293  // On Windows we need to duplicate the handle from the remote process
1294  HANDLE section;
1295  DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), &section,
1296                  FILE_MAP_READ | FILE_MAP_WRITE,
1297                  FALSE, 0);
1298  return TransportDIB::Map(section);
1299#elif defined(TOOLKIT_GTK)
1300  return TransportDIB::Map(dib_id.shmkey);
1301#elif defined(OS_ANDROID)
1302  return TransportDIB::Map(dib_id);
1303#else
1304  // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
1305  // for each.
1306  return widget_helper_->MapTransportDIB(dib_id);
1307#endif
1308}
1309
1310TransportDIB* RenderProcessHostImpl::GetTransportDIB(
1311    TransportDIB::Id dib_id) {
1312  if (!TransportDIB::is_valid_id(dib_id))
1313    return NULL;
1314
1315  const std::map<TransportDIB::Id, TransportDIB*>::iterator
1316      i = cached_dibs_.find(dib_id);
1317  if (i != cached_dibs_.end()) {
1318    cached_dibs_cleaner_.Reset();
1319    return i->second;
1320  }
1321
1322  TransportDIB* dib = MapTransportDIB(dib_id);
1323  if (!dib)
1324    return NULL;
1325
1326  if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
1327    // Clean a single entry from the cache
1328    std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
1329    size_t smallest_size = std::numeric_limits<size_t>::max();
1330
1331    for (std::map<TransportDIB::Id, TransportDIB*>::iterator
1332         i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
1333      if (i->second->size() <= smallest_size) {
1334        smallest_iterator = i;
1335        smallest_size = i->second->size();
1336      }
1337    }
1338
1339#if defined(TOOLKIT_GTK)
1340    smallest_iterator->second->Detach();
1341#else
1342    delete smallest_iterator->second;
1343#endif
1344    cached_dibs_.erase(smallest_iterator);
1345  }
1346
1347  cached_dibs_[dib_id] = dib;
1348  cached_dibs_cleaner_.Reset();
1349  return dib;
1350}
1351
1352void RenderProcessHostImpl::ClearTransportDIBCache() {
1353#if defined(TOOLKIT_GTK)
1354  std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib =
1355      cached_dibs_.begin();
1356  for (; dib != cached_dibs_.end(); ++dib)
1357    dib->second->Detach();
1358#else
1359  STLDeleteContainerPairSecondPointers(
1360      cached_dibs_.begin(), cached_dibs_.end());
1361#endif
1362  cached_dibs_.clear();
1363}
1364
1365bool RenderProcessHostImpl::Send(IPC::Message* msg) {
1366  TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send");
1367  if (!channel_) {
1368    if (!is_initialized_) {
1369      queued_messages_.push(msg);
1370      return true;
1371    } else {
1372      delete msg;
1373      return false;
1374    }
1375  }
1376
1377  if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
1378    queued_messages_.push(msg);
1379    return true;
1380  }
1381
1382  return channel_->Send(msg);
1383}
1384
1385bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
1386  // If we're about to be deleted, or have initiated the fast shutdown sequence,
1387  // we ignore incoming messages.
1388
1389  if (deleting_soon_ || fast_shutdown_started_)
1390    return false;
1391
1392  mark_child_process_activity_time();
1393  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
1394    // Dispatch control messages.
1395    bool msg_is_ok = true;
1396    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1397      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
1398                          OnShutdownRequest)
1399      IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone,
1400                          OnDumpHandlesDone)
1401      IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
1402                          SuddenTerminationChanged)
1403      IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
1404                          OnUserMetricsRecordAction)
1405      IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
1406      // Adding single handlers for your service here is fine, but once your
1407      // service needs more than one handler, please extract them into a new
1408      // message filter and add that filter to CreateMessageFilters().
1409    IPC_END_MESSAGE_MAP_EX()
1410
1411    if (!msg_is_ok) {
1412      // The message had a handler, but its de-serialization failed.
1413      // We consider this a capital crime. Kill the renderer if we have one.
1414      LOG(ERROR) << "bad message " << msg.type() << " terminating renderer.";
1415      RecordAction(base::UserMetricsAction("BadMessageTerminate_BRPH"));
1416      ReceivedBadMessage();
1417    }
1418    return true;
1419  }
1420
1421  // Dispatch incoming messages to the appropriate IPC::Listener.
1422  IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
1423  if (!listener) {
1424    if (msg.is_sync()) {
1425      // The listener has gone away, so we must respond or else the caller will
1426      // hang waiting for a reply.
1427      IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
1428      reply->set_reply_error();
1429      Send(reply);
1430    }
1431
1432    // If this is a SwapBuffers, we need to ack it if we're not going to handle
1433    // it so that the GPU process doesn't get stuck in unscheduled state.
1434    bool msg_is_ok = true;
1435    IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok)
1436      IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
1437                          OnCompositorSurfaceBuffersSwappedNoHost)
1438    IPC_END_MESSAGE_MAP_EX()
1439    return true;
1440  }
1441  return listener->OnMessageReceived(msg);
1442}
1443
1444void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) {
1445#if defined(IPC_MESSAGE_LOG_ENABLED)
1446  Send(new ChildProcessMsg_SetIPCLoggingEnabled(
1447      IPC::Logging::GetInstance()->Enabled()));
1448#endif
1449
1450  tracked_objects::ThreadData::Status status =
1451      tracked_objects::ThreadData::status();
1452  Send(new ChildProcessMsg_SetProfilerStatus(status));
1453}
1454
1455void RenderProcessHostImpl::OnChannelError() {
1456  ProcessDied(true /* already_dead */);
1457}
1458
1459BrowserContext* RenderProcessHostImpl::GetBrowserContext() const {
1460  return browser_context_;
1461}
1462
1463bool RenderProcessHostImpl::InSameStoragePartition(
1464    StoragePartition* partition) const {
1465  return storage_partition_impl_ == partition;
1466}
1467
1468int RenderProcessHostImpl::GetID() const {
1469  return id_;
1470}
1471
1472bool RenderProcessHostImpl::HasConnection() const {
1473  return channel_.get() != NULL;
1474}
1475
1476void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1477  ignore_input_events_ = ignore_input_events;
1478}
1479
1480bool RenderProcessHostImpl::IgnoreInputEvents() const {
1481  return ignore_input_events_;
1482}
1483
1484void RenderProcessHostImpl::Cleanup() {
1485  // If within_process_died_observer_ is true, one of our observers performed an
1486  // action that caused us to die (e.g. http://crbug.com/339504). Therefore,
1487  // delay the destruction until all of the observer callbacks have been made,
1488  // and guarantee that the RenderProcessHostDestroyed observer callback is
1489  // always the last callback fired.
1490  if (within_process_died_observer_) {
1491    delayed_cleanup_needed_ = true;
1492    return;
1493  }
1494  delayed_cleanup_needed_ = false;
1495
1496  // When there are no other owners of this object, we can delete ourselves.
1497  if (listeners_.IsEmpty() && worker_ref_count_ == 0) {
1498    // We cannot clean up twice; if this fails, there is an issue with our
1499    // control flow.
1500    DCHECK(!deleting_soon_);
1501
1502    DCHECK_EQ(0, pending_views_);
1503    FOR_EACH_OBSERVER(RenderProcessHostObserver,
1504                      observers_,
1505                      RenderProcessHostDestroyed(this));
1506    NotificationService::current()->Notify(
1507        NOTIFICATION_RENDERER_PROCESS_TERMINATED,
1508        Source<RenderProcessHost>(this),
1509        NotificationService::NoDetails());
1510
1511#ifndef NDEBUG
1512    is_self_deleted_ = true;
1513#endif
1514    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1515    deleting_soon_ = true;
1516    // It's important not to wait for the DeleteTask to delete the channel
1517    // proxy. Kill it off now. That way, in case the profile is going away, the
1518    // rest of the objects attached to this RenderProcessHost start going
1519    // away first, since deleting the channel proxy will post a
1520    // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread.
1521    channel_.reset();
1522    gpu_message_filter_ = NULL;
1523    message_port_message_filter_ = NULL;
1524    geolocation_dispatcher_host_ = NULL;
1525    screen_orientation_dispatcher_host_ = NULL;
1526
1527    // Remove ourself from the list of renderer processes so that we can't be
1528    // reused in between now and when the Delete task runs.
1529    UnregisterHost(GetID());
1530  }
1531}
1532
1533void RenderProcessHostImpl::AddPendingView() {
1534  pending_views_++;
1535}
1536
1537void RenderProcessHostImpl::RemovePendingView() {
1538  DCHECK(pending_views_);
1539  pending_views_--;
1540}
1541
1542void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
1543  sudden_termination_allowed_ = enabled;
1544}
1545
1546bool RenderProcessHostImpl::SuddenTerminationAllowed() const {
1547  return sudden_termination_allowed_;
1548}
1549
1550base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const {
1551  return base::TimeTicks::Now() - child_process_activity_time_;
1552}
1553
1554void RenderProcessHostImpl::ResumeRequestsForView(int route_id) {
1555  widget_helper_->ResumeRequestsForView(route_id);
1556}
1557
1558void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) {
1559  FilterURL(this, empty_allowed, url);
1560}
1561
1562#if defined(ENABLE_WEBRTC)
1563void RenderProcessHostImpl::EnableAecDump(const base::FilePath& file) {
1564  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1565  BrowserThread::PostTaskAndReplyWithResult(
1566      BrowserThread::FILE, FROM_HERE,
1567      base::Bind(&CreateAecDumpFileForProcess, file, GetHandle()),
1568      base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer,
1569                 weak_factory_.GetWeakPtr()));
1570}
1571
1572void RenderProcessHostImpl::DisableAecDump() {
1573  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1574  // Posting on the FILE thread and then replying back on the UI thread is only
1575  // for avoiding races between enable and disable. Nothing is done on the FILE
1576  // thread.
1577  BrowserThread::PostTaskAndReply(
1578      BrowserThread::FILE, FROM_HERE,
1579      base::Bind(&DisableAecDumpOnFileThread),
1580      base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer,
1581                 weak_factory_.GetWeakPtr()));
1582}
1583
1584void RenderProcessHostImpl::SetWebRtcLogMessageCallback(
1585    base::Callback<void(const std::string&)> callback) {
1586  webrtc_log_message_callback_ = callback;
1587}
1588#endif
1589
1590IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
1591  return channel_.get();
1592}
1593
1594void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
1595  channel_->AddFilter(filter->GetFilter());
1596}
1597
1598bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) {
1599  if (static_cast<size_t>(GetActiveViewCount()) == count)
1600    return FastShutdownIfPossible();
1601  return false;
1602}
1603
1604bool RenderProcessHostImpl::FastShutdownStarted() const {
1605  return fast_shutdown_started_;
1606}
1607
1608// static
1609void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
1610  g_all_hosts.Get().AddWithID(host, host_id);
1611}
1612
1613// static
1614void RenderProcessHostImpl::UnregisterHost(int host_id) {
1615  RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id);
1616  if (!host)
1617    return;
1618
1619  g_all_hosts.Get().Remove(host_id);
1620
1621  // Look up the map of site to process for the given browser_context,
1622  // in case we need to remove this process from it.  It will be registered
1623  // under any sites it rendered that use process-per-site mode.
1624  SiteProcessMap* map =
1625      GetSiteProcessMapForBrowserContext(host->GetBrowserContext());
1626  map->RemoveProcess(host);
1627}
1628
1629// static
1630void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph,
1631                                      bool empty_allowed,
1632                                      GURL* url) {
1633  ChildProcessSecurityPolicyImpl* policy =
1634      ChildProcessSecurityPolicyImpl::GetInstance();
1635
1636  if (empty_allowed && url->is_empty())
1637    return;
1638
1639  // The browser process should never hear the swappedout:// URL from any
1640  // of the renderer's messages.  Check for this in debug builds, but don't
1641  // let it crash a release browser.
1642  DCHECK(GURL(kSwappedOutURL) != *url);
1643
1644  if (!url->is_valid()) {
1645    // Have to use about:blank for the denied case, instead of an empty GURL.
1646    // This is because the browser treats navigation to an empty GURL as a
1647    // navigation to the home page. This is often a privileged page
1648    // (chrome://newtab/) which is exactly what we don't want.
1649    *url = GURL(kAboutBlankURL);
1650    RecordAction(base::UserMetricsAction("FilterURLTermiate_Invalid"));
1651    return;
1652  }
1653
1654  if (url->SchemeIs(kAboutScheme)) {
1655    // The renderer treats all URLs in the about: scheme as being about:blank.
1656    // Canonicalize about: URLs to about:blank.
1657    *url = GURL(kAboutBlankURL);
1658    RecordAction(base::UserMetricsAction("FilterURLTermiate_About"));
1659  }
1660
1661  // Do not allow browser plugin guests to navigate to non-web URLs, since they
1662  // cannot swap processes or grant bindings.
1663  bool non_web_url_in_guest = rph->IsGuest() &&
1664      !(url->is_valid() && policy->IsWebSafeScheme(url->scheme()));
1665
1666  if (non_web_url_in_guest || !policy->CanRequestURL(rph->GetID(), *url)) {
1667    // If this renderer is not permitted to request this URL, we invalidate the
1668    // URL.  This prevents us from storing the blocked URL and becoming confused
1669    // later.
1670    VLOG(1) << "Blocked URL " << url->spec();
1671    *url = GURL(kAboutBlankURL);
1672    RecordAction(base::UserMetricsAction("FilterURLTermiate_Blocked"));
1673  }
1674}
1675
1676// static
1677bool RenderProcessHostImpl::IsSuitableHost(
1678    RenderProcessHost* host,
1679    BrowserContext* browser_context,
1680    const GURL& site_url) {
1681  if (run_renderer_in_process())
1682    return true;
1683
1684  if (host->GetBrowserContext() != browser_context)
1685    return false;
1686
1687  // Do not allow sharing of guest hosts. This is to prevent bugs where guest
1688  // and non-guest storage gets mixed. In the future, we might consider enabling
1689  // the sharing of guests, in this case this check should be removed and
1690  // InSameStoragePartition should handle the possible sharing.
1691  if (host->IsGuest())
1692    return false;
1693
1694  // Check whether the given host and the intended site_url will be using the
1695  // same StoragePartition, since a RenderProcessHost can only support a single
1696  // StoragePartition.  This is relevant for packaged apps and isolated sites.
1697  StoragePartition* dest_partition =
1698      BrowserContext::GetStoragePartitionForSite(browser_context, site_url);
1699  if (!host->InSameStoragePartition(dest_partition))
1700    return false;
1701
1702  if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1703          host->GetID()) !=
1704      WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL(
1705          browser_context, site_url)) {
1706    return false;
1707  }
1708
1709  return GetContentClient()->browser()->IsSuitableHost(host, site_url);
1710}
1711
1712// static
1713bool RenderProcessHost::run_renderer_in_process() {
1714  return g_run_renderer_in_process_;
1715}
1716
1717// static
1718void RenderProcessHost::SetRunRendererInProcess(bool value) {
1719  g_run_renderer_in_process_ = value;
1720
1721  CommandLine* command_line = CommandLine::ForCurrentProcess();
1722  if (value) {
1723    if (!command_line->HasSwitch(switches::kLang)) {
1724      // Modify the current process' command line to include the browser locale,
1725      // as the renderer expects this flag to be set.
1726      const std::string locale =
1727          GetContentClient()->browser()->GetApplicationLocale();
1728      command_line->AppendSwitchASCII(switches::kLang, locale);
1729    }
1730    // TODO(piman): we should really send configuration through bools rather
1731    // than by parsing strings, i.e. sending an IPC rather than command line
1732    // args. crbug.com/314909
1733    AppendGpuCommandLineFlags(command_line);
1734  }
1735}
1736
1737// static
1738RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
1739  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1740  return iterator(g_all_hosts.Pointer());
1741}
1742
1743// static
1744RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
1745  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1746  return g_all_hosts.Get().Lookup(render_process_id);
1747}
1748
1749// static
1750bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
1751    BrowserContext* browser_context, const GURL& url) {
1752  // Experimental:
1753  // If --enable-strict-site-isolation or --site-per-process is enabled, do not
1754  // try to reuse renderer processes when over the limit.  (We could allow pages
1755  // from the same site to share, if we knew what the given process was
1756  // dedicated to.  Allowing no sharing is simpler for now.)  This may cause
1757  // resource exhaustion issues if too many sites are open at once.
1758  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1759  if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
1760      command_line.HasSwitch(switches::kSitePerProcess))
1761    return false;
1762
1763  if (run_renderer_in_process())
1764    return true;
1765
1766  // NOTE: Sometimes it's necessary to create more render processes than
1767  //       GetMaxRendererProcessCount(), for instance when we want to create
1768  //       a renderer process for a browser context that has no existing
1769  //       renderers. This is OK in moderation, since the
1770  //       GetMaxRendererProcessCount() is conservative.
1771  if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount())
1772    return true;
1773
1774  return GetContentClient()->browser()->
1775      ShouldTryToUseExistingProcessHost(browser_context, url);
1776}
1777
1778// static
1779RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
1780    BrowserContext* browser_context,
1781    const GURL& site_url) {
1782  // First figure out which existing renderers we can use.
1783  std::vector<RenderProcessHost*> suitable_renderers;
1784  suitable_renderers.reserve(g_all_hosts.Get().size());
1785
1786  iterator iter(AllHostsIterator());
1787  while (!iter.IsAtEnd()) {
1788    if (RenderProcessHostImpl::IsSuitableHost(
1789            iter.GetCurrentValue(),
1790            browser_context, site_url))
1791      suitable_renderers.push_back(iter.GetCurrentValue());
1792
1793    iter.Advance();
1794  }
1795
1796  // Now pick a random suitable renderer, if we have any.
1797  if (!suitable_renderers.empty()) {
1798    int suitable_count = static_cast<int>(suitable_renderers.size());
1799    int random_index = base::RandInt(0, suitable_count - 1);
1800    return suitable_renderers[random_index];
1801  }
1802
1803  return NULL;
1804}
1805
1806// static
1807bool RenderProcessHost::ShouldUseProcessPerSite(
1808    BrowserContext* browser_context,
1809    const GURL& url) {
1810  // Returns true if we should use the process-per-site model.  This will be
1811  // the case if the --process-per-site switch is specified, or in
1812  // process-per-site-instance for particular sites (e.g., WebUI).
1813  // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
1814  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1815  if (command_line.HasSwitch(switches::kProcessPerSite))
1816    return true;
1817
1818  // We want to consolidate particular sites like WebUI even when we are using
1819  // the process-per-tab or process-per-site-instance models.
1820  // Note: DevTools pages have WebUI type but should not reuse the same host.
1821  if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
1822          browser_context, url) &&
1823      !url.SchemeIs(kChromeDevToolsScheme)) {
1824    return true;
1825  }
1826
1827  // Otherwise let the content client decide, defaulting to false.
1828  return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context,
1829                                                                url);
1830}
1831
1832// static
1833RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite(
1834    BrowserContext* browser_context,
1835    const GURL& url) {
1836  // Look up the map of site to process for the given browser_context.
1837  SiteProcessMap* map =
1838      GetSiteProcessMapForBrowserContext(browser_context);
1839
1840  // See if we have an existing process with appropriate bindings for this site.
1841  // If not, the caller should create a new process and register it.
1842  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1843      .possibly_invalid_spec();
1844  RenderProcessHost* host = map->FindProcess(site);
1845  if (host && !IsSuitableHost(host, browser_context, url)) {
1846    // The registered process does not have an appropriate set of bindings for
1847    // the url.  Remove it from the map so we can register a better one.
1848    RecordAction(
1849        base::UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
1850    map->RemoveProcess(host);
1851    host = NULL;
1852  }
1853
1854  return host;
1855}
1856
1857void RenderProcessHostImpl::RegisterProcessHostForSite(
1858    BrowserContext* browser_context,
1859    RenderProcessHost* process,
1860    const GURL& url) {
1861  // Look up the map of site to process for the given browser_context.
1862  SiteProcessMap* map =
1863      GetSiteProcessMapForBrowserContext(browser_context);
1864
1865  // Only register valid, non-empty sites.  Empty or invalid sites will not
1866  // use process-per-site mode.  We cannot check whether the process has
1867  // appropriate bindings here, because the bindings have not yet been granted.
1868  std::string site = SiteInstance::GetSiteForURL(browser_context, url)
1869      .possibly_invalid_spec();
1870  if (!site.empty())
1871    map->RegisterProcess(site, process);
1872}
1873
1874void RenderProcessHostImpl::ProcessDied(bool already_dead) {
1875  // Our child process has died.  If we didn't expect it, it's a crash.
1876  // In any case, we need to let everyone know it's gone.
1877  // The OnChannelError notification can fire multiple times due to nested sync
1878  // calls to a renderer. If we don't have a valid channel here it means we
1879  // already handled the error.
1880
1881  // It should not be possible for us to be called re-entrantly.
1882  DCHECK(!within_process_died_observer_);
1883
1884  // It should not be possible for a process death notification to come in while
1885  // we are dying.
1886  DCHECK(!deleting_soon_);
1887
1888  // child_process_launcher_ can be NULL in single process mode or if fast
1889  // termination happened.
1890  int exit_code = 0;
1891  base::TerminationStatus status =
1892      child_process_launcher_.get() ?
1893      child_process_launcher_->GetChildTerminationStatus(already_dead,
1894                                                         &exit_code) :
1895      base::TERMINATION_STATUS_NORMAL_TERMINATION;
1896
1897  RendererClosedDetails details(GetHandle(), status, exit_code);
1898  within_process_died_observer_ = true;
1899  NotificationService::current()->Notify(
1900      NOTIFICATION_RENDERER_PROCESS_CLOSED,
1901      Source<RenderProcessHost>(this),
1902      Details<RendererClosedDetails>(&details));
1903  FOR_EACH_OBSERVER(RenderProcessHostObserver,
1904                    observers_,
1905                    RenderProcessExited(this, GetHandle(), status, exit_code));
1906  within_process_died_observer_ = false;
1907
1908  child_process_launcher_.reset();
1909  channel_.reset();
1910  gpu_message_filter_ = NULL;
1911  message_port_message_filter_ = NULL;
1912  geolocation_dispatcher_host_ = NULL;
1913  screen_orientation_dispatcher_host_ = NULL;
1914
1915  IDMap<IPC::Listener>::iterator iter(&listeners_);
1916  while (!iter.IsAtEnd()) {
1917    iter.GetCurrentValue()->OnMessageReceived(
1918        ViewHostMsg_RenderProcessGone(iter.GetCurrentKey(),
1919                                      static_cast<int>(status),
1920                                      exit_code));
1921    iter.Advance();
1922  }
1923
1924  ClearTransportDIBCache();
1925
1926  // It's possible that one of the calls out to the observers might have caused
1927  // this object to be no longer needed.
1928  if (delayed_cleanup_needed_)
1929    Cleanup();
1930
1931  // This object is not deleted at this point and might be reused later.
1932  // TODO(darin): clean this up
1933}
1934
1935int RenderProcessHostImpl::GetActiveViewCount() {
1936  int num_active_views = 0;
1937  scoped_ptr<RenderWidgetHostIterator> widgets(
1938      RenderWidgetHost::GetRenderWidgetHosts());
1939  while (RenderWidgetHost* widget = widgets->GetNextHost()) {
1940    // Count only RenderWidgetHosts in this process.
1941    if (widget->GetProcess()->GetID() == GetID())
1942      num_active_views++;
1943  }
1944  return num_active_views;
1945}
1946
1947// Frame subscription API for this class is for accelerated composited path
1948// only. These calls are redirected to GpuMessageFilter.
1949void RenderProcessHostImpl::BeginFrameSubscription(
1950    int route_id,
1951    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1952  if (!gpu_message_filter_)
1953    return;
1954  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1955      &GpuMessageFilter::BeginFrameSubscription,
1956      gpu_message_filter_,
1957      route_id, base::Passed(&subscriber)));
1958}
1959
1960void RenderProcessHostImpl::EndFrameSubscription(int route_id) {
1961  if (!gpu_message_filter_)
1962    return;
1963  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
1964      &GpuMessageFilter::EndFrameSubscription,
1965      gpu_message_filter_,
1966      route_id));
1967}
1968
1969#if defined(ENABLE_WEBRTC)
1970void RenderProcessHostImpl::WebRtcLogMessage(const std::string& message) {
1971  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1972  if (!webrtc_log_message_callback_.is_null())
1973    webrtc_log_message_callback_.Run(message);
1974}
1975#endif
1976
1977scoped_refptr<ScreenOrientationDispatcherHost>
1978RenderProcessHostImpl::screen_orientation_dispatcher_host() const {
1979  return make_scoped_refptr(screen_orientation_dispatcher_host_);
1980}
1981
1982void RenderProcessHostImpl::OnShutdownRequest() {
1983  // Don't shut down if there are active RenderViews, or if there are pending
1984  // RenderViews being swapped back in.
1985  // In single process mode, we never shutdown the renderer.
1986  int num_active_views = GetActiveViewCount();
1987  if (pending_views_ || num_active_views > 0 || run_renderer_in_process())
1988    return;
1989
1990  // Notify any contents that might have swapped out renderers from this
1991  // process. They should not attempt to swap them back in.
1992  NotificationService::current()->Notify(
1993      NOTIFICATION_RENDERER_PROCESS_CLOSING,
1994      Source<RenderProcessHost>(this),
1995      NotificationService::NoDetails());
1996
1997  Send(new ChildProcessMsg_Shutdown());
1998}
1999
2000void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
2001  SetSuddenTerminationAllowed(enabled);
2002}
2003
2004void RenderProcessHostImpl::OnDumpHandlesDone() {
2005  Cleanup();
2006}
2007
2008void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
2009  // Note: we always set the backgrounded_ value.  If the process is NULL
2010  // (and hence hasn't been created yet), we will set the process priority
2011  // later when we create the process.
2012  backgrounded_ = backgrounded;
2013  if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
2014    return;
2015
2016#if defined(OS_WIN)
2017  // The cbstext.dll loads as a global GetMessage hook in the browser process
2018  // and intercepts/unintercepts the kernel32 API SetPriorityClass in a
2019  // background thread. If the UI thread invokes this API just when it is
2020  // intercepted the stack is messed up on return from the interceptor
2021  // which causes random crashes in the browser process. Our hack for now
2022  // is to not invoke the SetPriorityClass API if the dll is loaded.
2023  if (GetModuleHandle(L"cbstext.dll"))
2024    return;
2025#endif  // OS_WIN
2026
2027  child_process_launcher_->SetProcessBackgrounded(backgrounded);
2028}
2029
2030void RenderProcessHostImpl::OnProcessLaunched() {
2031  // No point doing anything, since this object will be destructed soon.  We
2032  // especially don't want to send the RENDERER_PROCESS_CREATED notification,
2033  // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to
2034  // properly cleanup.
2035  if (deleting_soon_)
2036    return;
2037
2038  if (child_process_launcher_) {
2039    if (!child_process_launcher_->GetHandle()) {
2040      OnChannelError();
2041      return;
2042    }
2043
2044    child_process_launcher_->SetProcessBackgrounded(backgrounded_);
2045  }
2046
2047  // NOTE: This needs to be before sending queued messages because
2048  // ExtensionService uses this notification to initialize the renderer process
2049  // with state that must be there before any JavaScript executes.
2050  //
2051  // The queued messages contain such things as "navigate". If this notification
2052  // was after, we can end up executing JavaScript before the initialization
2053  // happens.
2054  NotificationService::current()->Notify(
2055      NOTIFICATION_RENDERER_PROCESS_CREATED,
2056      Source<RenderProcessHost>(this),
2057      NotificationService::NoDetails());
2058
2059  while (!queued_messages_.empty()) {
2060    Send(queued_messages_.front());
2061    queued_messages_.pop();
2062  }
2063
2064#if defined(ENABLE_WEBRTC)
2065  if (WebRTCInternals::GetInstance()->aec_dump_enabled())
2066    EnableAecDump(WebRTCInternals::GetInstance()->aec_dump_file_path());
2067#endif
2068}
2069
2070scoped_refptr<AudioRendererHost>
2071RenderProcessHostImpl::audio_renderer_host() const {
2072  return audio_renderer_host_;
2073}
2074
2075void RenderProcessHostImpl::OnUserMetricsRecordAction(
2076    const std::string& action) {
2077  RecordComputedAction(action);
2078}
2079
2080void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
2081  MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
2082}
2083
2084void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
2085      const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
2086  TRACE_EVENT0("renderer_host",
2087               "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
2088  if (!ui::LatencyInfo::Verify(params.latency_info,
2089                               "ViewHostMsg_CompositorSurfaceBuffersSwapped"))
2090    return;
2091  AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
2092  ack_params.sync_point = 0;
2093  RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
2094                                                 params.gpu_process_host_id,
2095                                                 ack_params);
2096}
2097
2098void RenderProcessHostImpl::OnGpuSwitching() {
2099  // We are updating all widgets including swapped out ones.
2100  scoped_ptr<RenderWidgetHostIterator> widgets(
2101      RenderWidgetHostImpl::GetAllRenderWidgetHosts());
2102  while (RenderWidgetHost* widget = widgets->GetNextHost()) {
2103    if (!widget->IsRenderView())
2104      continue;
2105
2106    // Skip widgets in other processes.
2107    if (widget->GetProcess()->GetID() != GetID())
2108      continue;
2109
2110    RenderViewHost* rvh = RenderViewHost::From(widget);
2111    rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
2112  }
2113}
2114
2115#if defined(ENABLE_WEBRTC)
2116void RenderProcessHostImpl::SendAecDumpFileToRenderer(
2117    IPC::PlatformFileForTransit file_for_transit) {
2118  if (file_for_transit == IPC::InvalidPlatformFileForTransit())
2119    return;
2120  Send(new MediaStreamMsg_EnableAecDump(file_for_transit));
2121}
2122
2123void RenderProcessHostImpl::SendDisableAecDumpToRenderer() {
2124  Send(new MediaStreamMsg_DisableAecDump());
2125}
2126#endif
2127
2128void RenderProcessHostImpl::IncrementWorkerRefCount() {
2129  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2130  ++worker_ref_count_;
2131}
2132
2133void RenderProcessHostImpl::DecrementWorkerRefCount() {
2134  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2135  DCHECK_GT(worker_ref_count_, 0);
2136  --worker_ref_count_;
2137  if (worker_ref_count_ == 0)
2138    Cleanup();
2139}
2140
2141}  // namespace content
2142