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