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