OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Represents the browser side of the browser <--> renderer communication | 5 // Represents the browser side of the browser <--> renderer communication |
6 // channel. There will be one RenderProcessHost per renderer process. | 6 // channel. There will be one RenderProcessHost per renderer process. |
7 | 7 |
8 #include "content/browser/renderer_host/render_process_host_impl.h" | 8 #include "content/browser/renderer_host/render_process_host_impl.h" |
9 | 9 |
10 #if defined(OS_WIN) | 10 #if defined(OS_WIN) |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "base/lazy_instance.h" | 28 #include "base/lazy_instance.h" |
29 #include "base/logging.h" | 29 #include "base/logging.h" |
30 #include "base/metrics/field_trial.h" | 30 #include "base/metrics/field_trial.h" |
31 #include "base/metrics/histogram.h" | 31 #include "base/metrics/histogram.h" |
32 #include "base/path_service.h" | 32 #include "base/path_service.h" |
33 #include "base/platform_file.h" | 33 #include "base/platform_file.h" |
34 #include "base/process_util.h" | 34 #include "base/process_util.h" |
35 #include "base/rand_util.h" | 35 #include "base/rand_util.h" |
36 #include "base/stl_util.h" | 36 #include "base/stl_util.h" |
37 #include "base/string_util.h" | 37 #include "base/string_util.h" |
| 38 #include "base/supports_user_data.h" |
38 #include "base/sys_info.h" | 39 #include "base/sys_info.h" |
39 #include "base/threading/thread.h" | 40 #include "base/threading/thread.h" |
40 #include "base/threading/thread_restrictions.h" | 41 #include "base/threading/thread_restrictions.h" |
41 #include "base/tracked_objects.h" | 42 #include "base/tracked_objects.h" |
42 #include "content/browser/appcache/appcache_dispatcher_host.h" | 43 #include "content/browser/appcache/appcache_dispatcher_host.h" |
43 #include "content/browser/appcache/chrome_appcache_service.h" | 44 #include "content/browser/appcache/chrome_appcache_service.h" |
44 #include "content/browser/browser_main.h" | 45 #include "content/browser/browser_main.h" |
45 #include "content/browser/browser_main_loop.h" | 46 #include "content/browser/browser_main_loop.h" |
46 #include "content/browser/child_process_security_policy_impl.h" | 47 #include "content/browser/child_process_security_policy_impl.h" |
47 #include "content/browser/device_orientation/message_filter.h" | 48 #include "content/browser/device_orientation/message_filter.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 #include "content/browser/trace_message_filter.h" | 85 #include "content/browser/trace_message_filter.h" |
85 #include "content/browser/worker_host/worker_message_filter.h" | 86 #include "content/browser/worker_host/worker_message_filter.h" |
86 #include "content/common/child_process_host_impl.h" | 87 #include "content/common/child_process_host_impl.h" |
87 #include "content/common/child_process_messages.h" | 88 #include "content/common/child_process_messages.h" |
88 #include "content/common/gpu/gpu_messages.h" | 89 #include "content/common/gpu/gpu_messages.h" |
89 #include "content/common/resource_messages.h" | 90 #include "content/common/resource_messages.h" |
90 #include "content/common/view_messages.h" | 91 #include "content/common/view_messages.h" |
91 #include "content/public/browser/browser_context.h" | 92 #include "content/public/browser/browser_context.h" |
92 #include "content/public/browser/content_browser_client.h" | 93 #include "content/public/browser/content_browser_client.h" |
93 #include "content/public/browser/notification_service.h" | 94 #include "content/public/browser/notification_service.h" |
| 95 #include "content/public/browser/render_process_host_factory.h" |
94 #include "content/public/browser/resource_context.h" | 96 #include "content/public/browser/resource_context.h" |
95 #include "content/public/browser/user_metrics.h" | 97 #include "content/public/browser/user_metrics.h" |
96 #include "content/public/browser/web_ui_controller_factory.h" | 98 #include "content/public/browser/web_ui_controller_factory.h" |
97 #include "content/public/common/content_constants.h" | 99 #include "content/public/common/content_constants.h" |
98 #include "content/public/common/content_switches.h" | 100 #include "content/public/common/content_switches.h" |
99 #include "content/public/common/process_type.h" | 101 #include "content/public/common/process_type.h" |
100 #include "content/public/common/result_codes.h" | 102 #include "content/public/common/result_codes.h" |
101 #include "content/public/common/url_constants.h" | 103 #include "content/public/common/url_constants.h" |
102 #include "content/renderer/render_process_impl.h" | 104 #include "content/renderer/render_process_impl.h" |
103 #include "content/renderer/render_thread_impl.h" | 105 #include "content/renderer/render_thread_impl.h" |
(...skipping 11 matching lines...) Expand all Loading... |
115 | 117 |
116 #if defined(OS_WIN) | 118 #if defined(OS_WIN) |
117 #include "base/synchronization/waitable_event.h" | 119 #include "base/synchronization/waitable_event.h" |
118 #include "content/common/font_cache_dispatcher_win.h" | 120 #include "content/common/font_cache_dispatcher_win.h" |
119 #endif | 121 #endif |
120 | 122 |
121 #include "third_party/skia/include/core/SkBitmap.h" | 123 #include "third_party/skia/include/core/SkBitmap.h" |
122 | 124 |
123 extern bool g_exited_main_message_loop; | 125 extern bool g_exited_main_message_loop; |
124 | 126 |
| 127 static const char* kSiteProcessMapKeyName = "content_site_process_map"; |
| 128 |
125 namespace content { | 129 namespace content { |
126 | 130 |
127 // This class creates the IO thread for the renderer when running in | 131 // This class creates the IO thread for the renderer when running in |
128 // single-process mode. It's not used in multi-process mode. | 132 // single-process mode. It's not used in multi-process mode. |
129 class RendererMainThread : public base::Thread { | 133 class RendererMainThread : public base::Thread { |
130 public: | 134 public: |
131 explicit RendererMainThread(const std::string& channel_id) | 135 explicit RendererMainThread(const std::string& channel_id) |
132 : base::Thread("Chrome_InProcRendererThread"), | 136 : base::Thread("Chrome_InProcRendererThread"), |
133 channel_id_(channel_id), | 137 channel_id_(channel_id), |
134 render_process_(NULL) { | 138 render_process_(NULL) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 virtual ~RendererURLRequestContextSelector() {} | 205 virtual ~RendererURLRequestContextSelector() {} |
202 | 206 |
203 scoped_refptr<net::URLRequestContextGetter> request_context_; | 207 scoped_refptr<net::URLRequestContextGetter> request_context_; |
204 scoped_refptr<net::URLRequestContextGetter> media_request_context_; | 208 scoped_refptr<net::URLRequestContextGetter> media_request_context_; |
205 }; | 209 }; |
206 | 210 |
207 // the global list of all renderer processes | 211 // the global list of all renderer processes |
208 base::LazyInstance<IDMap<RenderProcessHost> >::Leaky | 212 base::LazyInstance<IDMap<RenderProcessHost> >::Leaky |
209 g_all_hosts = LAZY_INSTANCE_INITIALIZER; | 213 g_all_hosts = LAZY_INSTANCE_INITIALIZER; |
210 | 214 |
| 215 // Map of site to process, to ensure we only have one RenderProcessHost per |
| 216 // site in process-per-site mode. Each map is specific to a BrowserContext. |
| 217 class SiteProcessMap : public base::SupportsUserData::Data { |
| 218 public: |
| 219 typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap; |
| 220 SiteProcessMap() {} |
| 221 |
| 222 void RegisterProcess(std::string site, RenderProcessHost* process) { |
| 223 map_[site] = process; |
| 224 } |
| 225 |
| 226 RenderProcessHost* FindProcess(std::string site) { |
| 227 SiteToProcessMap::iterator i = map_.find(site); |
| 228 if (i != map_.end()) |
| 229 return i->second; |
| 230 return NULL; |
| 231 } |
| 232 |
| 233 void RemoveProcess(RenderProcessHost* host) { |
| 234 // Find all instances of this process in the map, then separately remove |
| 235 // them. |
| 236 std::set<std::string> sites; |
| 237 for (SiteToProcessMap::const_iterator i = map_.begin(); |
| 238 i != map_.end(); |
| 239 i++) { |
| 240 if (i->second == host) |
| 241 sites.insert(i->first); |
| 242 } |
| 243 for (std::set<std::string>::iterator i = sites.begin(); |
| 244 i != sites.end(); |
| 245 i++) { |
| 246 SiteToProcessMap::iterator iter = map_.find(*i); |
| 247 if (iter != map_.end()) { |
| 248 DCHECK_EQ(iter->second, host); |
| 249 map_.erase(iter); |
| 250 } |
| 251 } |
| 252 } |
| 253 |
| 254 private: |
| 255 SiteToProcessMap map_; |
| 256 }; |
| 257 |
| 258 // Find the SiteProcessMap specific to the given context. |
| 259 SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { |
| 260 DCHECK(context); |
| 261 SiteProcessMap* map = static_cast<SiteProcessMap*>( |
| 262 context->GetUserData(kSiteProcessMapKeyName)); |
| 263 if (!map) { |
| 264 map = new SiteProcessMap(); |
| 265 context->SetUserData(kSiteProcessMapKeyName, map); |
| 266 } |
| 267 return map; |
| 268 } |
| 269 |
211 } // namespace | 270 } // namespace |
212 | 271 |
213 // Stores the maximum number of renderer processes the content module can | 272 // Stores the maximum number of renderer processes the content module can |
214 // create. | 273 // create. |
215 static size_t g_max_renderer_count_override = 0; | 274 static size_t g_max_renderer_count_override = 0; |
216 | 275 |
217 // static | 276 // static |
218 size_t RenderProcessHost::GetMaxRendererProcessCount() { | 277 size_t RenderProcessHost::GetMaxRendererProcessCount() { |
219 if (g_max_renderer_count_override) | 278 if (g_max_renderer_count_override) |
220 return g_max_renderer_count_override; | 279 return g_max_renderer_count_override; |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 // It's important not to wait for the DeleteTask to delete the channel | 1123 // It's important not to wait for the DeleteTask to delete the channel |
1065 // proxy. Kill it off now. That way, in case the profile is going away, the | 1124 // proxy. Kill it off now. That way, in case the profile is going away, the |
1066 // rest of the objects attached to this RenderProcessHost start going | 1125 // rest of the objects attached to this RenderProcessHost start going |
1067 // away first, since deleting the channel proxy will post a | 1126 // away first, since deleting the channel proxy will post a |
1068 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. | 1127 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. |
1069 channel_.reset(); | 1128 channel_.reset(); |
1070 gpu_message_filter_ = NULL; | 1129 gpu_message_filter_ = NULL; |
1071 | 1130 |
1072 // Remove ourself from the list of renderer processes so that we can't be | 1131 // Remove ourself from the list of renderer processes so that we can't be |
1073 // reused in between now and when the Delete task runs. | 1132 // reused in between now and when the Delete task runs. |
1074 g_all_hosts.Get().Remove(GetID()); | 1133 UnregisterHost(GetID()); |
1075 } | 1134 } |
1076 } | 1135 } |
1077 | 1136 |
1078 void RenderProcessHostImpl::AddPendingView() { | 1137 void RenderProcessHostImpl::AddPendingView() { |
1079 pending_views_++; | 1138 pending_views_++; |
1080 } | 1139 } |
1081 | 1140 |
1082 void RenderProcessHostImpl::RemovePendingView() { | 1141 void RenderProcessHostImpl::RemovePendingView() { |
1083 DCHECK(pending_views_); | 1142 DCHECK(pending_views_); |
1084 pending_views_--; | 1143 pending_views_--; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 return fast_shutdown_started_; | 1183 return fast_shutdown_started_; |
1125 } | 1184 } |
1126 | 1185 |
1127 // static | 1186 // static |
1128 void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { | 1187 void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { |
1129 g_all_hosts.Get().AddWithID(host, host_id); | 1188 g_all_hosts.Get().AddWithID(host, host_id); |
1130 } | 1189 } |
1131 | 1190 |
1132 // static | 1191 // static |
1133 void RenderProcessHostImpl::UnregisterHost(int host_id) { | 1192 void RenderProcessHostImpl::UnregisterHost(int host_id) { |
1134 if (g_all_hosts.Get().Lookup(host_id)) | 1193 RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); |
1135 g_all_hosts.Get().Remove(host_id); | 1194 if (!host) |
| 1195 return; |
| 1196 |
| 1197 g_all_hosts.Get().Remove(host_id); |
| 1198 |
| 1199 // Look up the map of site to process for the given browser_context, |
| 1200 // in case we need to remove this process from it. It will be registered |
| 1201 // under any sites it rendered that use process-per-site mode. |
| 1202 SiteProcessMap* map = |
| 1203 GetSiteProcessMapForBrowserContext(host->GetBrowserContext()); |
| 1204 map->RemoveProcess(host); |
1136 } | 1205 } |
1137 | 1206 |
1138 // static | 1207 // static |
1139 bool RenderProcessHostImpl::IsSuitableHost( | 1208 bool RenderProcessHostImpl::IsSuitableHost( |
1140 RenderProcessHost* host, | 1209 RenderProcessHost* host, |
1141 BrowserContext* browser_context, | 1210 BrowserContext* browser_context, |
1142 const GURL& site_url) { | 1211 const GURL& site_url) { |
1143 if (run_renderer_in_process()) | 1212 if (run_renderer_in_process()) |
1144 return true; | 1213 return true; |
1145 | 1214 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 // Now pick a random suitable renderer, if we have any. | 1297 // Now pick a random suitable renderer, if we have any. |
1229 if (!suitable_renderers.empty()) { | 1298 if (!suitable_renderers.empty()) { |
1230 int suitable_count = static_cast<int>(suitable_renderers.size()); | 1299 int suitable_count = static_cast<int>(suitable_renderers.size()); |
1231 int random_index = base::RandInt(0, suitable_count - 1); | 1300 int random_index = base::RandInt(0, suitable_count - 1); |
1232 return suitable_renderers[random_index]; | 1301 return suitable_renderers[random_index]; |
1233 } | 1302 } |
1234 | 1303 |
1235 return NULL; | 1304 return NULL; |
1236 } | 1305 } |
1237 | 1306 |
| 1307 // static |
| 1308 bool RenderProcessHostImpl::ShouldUseProcessPerSite( |
| 1309 BrowserContext* browser_context, |
| 1310 const GURL& url) { |
| 1311 // Returns true if we should use the process-per-site model. This will be |
| 1312 // the case if the --process-per-site switch is specified, or in |
| 1313 // process-per-site-instance for particular sites (e.g., WebUI). |
| 1314 |
| 1315 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 1316 if (command_line.HasSwitch(switches::kProcessPerSite)) |
| 1317 return true; |
| 1318 |
| 1319 // We want to consolidate particular sites like WebUI when we are using |
| 1320 // process-per-tab or process-per-site-instance models. |
| 1321 // Note that --single-process is handled in ShouldTryToUseExistingProcessHost. |
| 1322 |
| 1323 if (content::GetContentClient()->browser()-> |
| 1324 ShouldUseProcessPerSite(browser_context, url)) { |
| 1325 return true; |
| 1326 } |
| 1327 |
| 1328 // DevTools pages have WebUI type but should not reuse the same host. |
| 1329 WebUIControllerFactory* factory = |
| 1330 content::GetContentClient()->browser()->GetWebUIControllerFactory(); |
| 1331 if (factory && |
| 1332 factory->UseWebUIForURL(browser_context, url) && |
| 1333 !url.SchemeIs(chrome::kChromeDevToolsScheme)) { |
| 1334 return true; |
| 1335 } |
| 1336 |
| 1337 // In all other cases, don't use process-per-site logic. |
| 1338 return false; |
| 1339 } |
| 1340 |
| 1341 // static |
| 1342 RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite( |
| 1343 BrowserContext* browser_context, |
| 1344 const GURL& url) { |
| 1345 // Look up the map of site to process for the given browser_context. |
| 1346 SiteProcessMap* map = |
| 1347 GetSiteProcessMapForBrowserContext(browser_context); |
| 1348 |
| 1349 // See if we have an existing process for this site. If not, the caller |
| 1350 // should create a new process and register it. |
| 1351 std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url) |
| 1352 .possibly_invalid_spec(); |
| 1353 return map->FindProcess(site); |
| 1354 } |
| 1355 |
| 1356 void RenderProcessHostImpl::RegisterProcessHostForSite( |
| 1357 BrowserContext* browser_context, |
| 1358 RenderProcessHost* process, |
| 1359 const GURL& url) { |
| 1360 // Look up the map of site to process for the given browser_context. |
| 1361 SiteProcessMap* map = |
| 1362 GetSiteProcessMapForBrowserContext(browser_context); |
| 1363 |
| 1364 // TODO(creis): Determine if it's better to allow registration of |
| 1365 // empty sites or not. For now, group anything from which we can't parse |
| 1366 // a site into the same process, when using --process-per-site. |
| 1367 std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url) |
| 1368 .possibly_invalid_spec(); |
| 1369 map->RegisterProcess(site, process); |
| 1370 } |
| 1371 |
1238 void RenderProcessHostImpl::ProcessDied(base::ProcessHandle handle, | 1372 void RenderProcessHostImpl::ProcessDied(base::ProcessHandle handle, |
1239 base::TerminationStatus status, | 1373 base::TerminationStatus status, |
1240 int exit_code, | 1374 int exit_code, |
1241 bool was_alive) { | 1375 bool was_alive) { |
1242 // Our child process has died. If we didn't expect it, it's a crash. | 1376 // Our child process has died. If we didn't expect it, it's a crash. |
1243 // In any case, we need to let everyone know it's gone. | 1377 // In any case, we need to let everyone know it's gone. |
1244 // The OnChannelError notification can fire multiple times due to nested sync | 1378 // The OnChannelError notification can fire multiple times due to nested sync |
1245 // calls to a renderer. If we don't have a valid channel here it means we | 1379 // calls to a renderer. If we don't have a valid channel here it means we |
1246 // already handled the error. | 1380 // already handled the error. |
1247 | 1381 |
1248 RendererClosedDetails details(handle, status, exit_code, was_alive); | 1382 RendererClosedDetails details(handle, status, exit_code, was_alive); |
1249 NotificationService::current()->Notify( | 1383 NotificationService::current()->Notify( |
1250 NOTIFICATION_RENDERER_PROCESS_CLOSED, | 1384 NOTIFICATION_RENDERER_PROCESS_CLOSED, |
1251 Source<RenderProcessHost>(this), | 1385 Source<RenderProcessHost>(this), |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 uint64 surface_handle, | 1525 uint64 surface_handle, |
1392 int32 route_id, | 1526 int32 route_id, |
1393 int32 gpu_process_host_id) { | 1527 int32 gpu_process_host_id) { |
1394 TRACE_EVENT0("renderer_host", | 1528 TRACE_EVENT0("renderer_host", |
1395 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost"); | 1529 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost"); |
1396 RenderWidgetHostImpl::AcknowledgeSwapBuffers(route_id, | 1530 RenderWidgetHostImpl::AcknowledgeSwapBuffers(route_id, |
1397 gpu_process_host_id); | 1531 gpu_process_host_id); |
1398 } | 1532 } |
1399 | 1533 |
1400 } // namespace content | 1534 } // namespace content |
OLD | NEW |