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