| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "content/browser/renderer_host/render_process_host.h" | 5 #include "content/browser/renderer_host/render_process_host.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/lazy_instance.h" |
| 8 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 9 #include "base/sys_info.h" | 10 #include "base/sys_info.h" |
| 10 #include "content/browser/browser_main.h" | 11 #include "content/browser/browser_main.h" |
| 11 #include "content/browser/child_process_security_policy.h" | 12 #include "content/browser/child_process_security_policy.h" |
| 12 #include "content/browser/webui/web_ui_factory.h" | 13 #include "content/browser/webui/web_ui_factory.h" |
| 13 #include "content/common/child_process_info.h" | 14 #include "content/common/child_process_info.h" |
| 14 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/browser/content_browser_client.h" | 16 #include "content/public/browser/content_browser_client.h" |
| 16 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
| 17 #include "content/public/browser/notification_types.h" | 18 #include "content/public/browser/notification_types.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 return false; | 76 return false; |
| 76 | 77 |
| 77 if (ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(host->id()) != | 78 if (ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(host->id()) != |
| 78 content::WebUIFactory::Get()->HasWebUIScheme(site_url)) | 79 content::WebUIFactory::Get()->HasWebUIScheme(site_url)) |
| 79 return false; | 80 return false; |
| 80 | 81 |
| 81 return content::GetContentClient()->browser()->IsSuitableHost(host, site_url); | 82 return content::GetContentClient()->browser()->IsSuitableHost(host, site_url); |
| 82 } | 83 } |
| 83 | 84 |
| 84 // the global list of all renderer processes | 85 // the global list of all renderer processes |
| 85 IDMap<RenderProcessHost> all_hosts; | 86 base::LazyInstance<IDMap<RenderProcessHost>, |
| 87 base::LeakyLazyInstanceTraits<IDMap<RenderProcessHost> > > |
| 88 g_all_hosts(base::LINKER_INITIALIZED); |
| 86 | 89 |
| 87 } // namespace | 90 } // namespace |
| 88 | 91 |
| 89 // static | 92 // static |
| 90 bool RenderProcessHost::run_renderer_in_process_ = false; | 93 bool RenderProcessHost::run_renderer_in_process_ = false; |
| 91 | 94 |
| 92 // static | 95 // static |
| 93 void RenderProcessHost::SetMaxRendererProcessCountForTest(size_t count) { | 96 void RenderProcessHost::SetMaxRendererProcessCountForTest(size_t count) { |
| 94 max_renderer_count_override = count; | 97 max_renderer_count_override = count; |
| 95 } | 98 } |
| 96 | 99 |
| 97 RenderProcessHost::RenderProcessHost(content::BrowserContext* browser_context) | 100 RenderProcessHost::RenderProcessHost(content::BrowserContext* browser_context) |
| 98 : max_page_id_(-1), | 101 : max_page_id_(-1), |
| 99 fast_shutdown_started_(false), | 102 fast_shutdown_started_(false), |
| 100 deleting_soon_(false), | 103 deleting_soon_(false), |
| 101 pending_views_(0), | 104 pending_views_(0), |
| 102 id_(ChildProcessInfo::GenerateChildProcessUniqueId()), | 105 id_(ChildProcessInfo::GenerateChildProcessUniqueId()), |
| 103 browser_context_(browser_context), | 106 browser_context_(browser_context), |
| 104 sudden_termination_allowed_(true), | 107 sudden_termination_allowed_(true), |
| 105 ignore_input_events_(false) { | 108 ignore_input_events_(false) { |
| 106 CHECK(!content::ExitedMainMessageLoop()); | 109 CHECK(!content::ExitedMainMessageLoop()); |
| 107 all_hosts.AddWithID(this, id()); | 110 g_all_hosts.Get().AddWithID(this, id()); |
| 108 all_hosts.set_check_on_null_data(true); | 111 g_all_hosts.Get().set_check_on_null_data(true); |
| 109 // Initialize |child_process_activity_time_| to a reasonable value. | 112 // Initialize |child_process_activity_time_| to a reasonable value. |
| 110 mark_child_process_activity_time(); | 113 mark_child_process_activity_time(); |
| 111 } | 114 } |
| 112 | 115 |
| 113 RenderProcessHost::~RenderProcessHost() { | 116 RenderProcessHost::~RenderProcessHost() { |
| 114 // In unit tests, Release() might not have been called. | 117 // In unit tests, Release() might not have been called. |
| 115 if (all_hosts.Lookup(id())) | 118 if (g_all_hosts.Get().Lookup(id())) |
| 116 all_hosts.Remove(id()); | 119 g_all_hosts.Get().Remove(id()); |
| 117 } | 120 } |
| 118 | 121 |
| 119 bool RenderProcessHost::HasConnection() const { | 122 bool RenderProcessHost::HasConnection() const { |
| 120 return channel_.get() != NULL; | 123 return channel_.get() != NULL; |
| 121 } | 124 } |
| 122 | 125 |
| 123 void RenderProcessHost::Attach(IPC::Channel::Listener* listener, | 126 void RenderProcessHost::Attach(IPC::Channel::Listener* listener, |
| 124 int routing_id) { | 127 int routing_id) { |
| 125 listeners_.AddWithID(listener, routing_id); | 128 listeners_.AddWithID(listener, routing_id); |
| 126 } | 129 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 deleting_soon_ = true; | 162 deleting_soon_ = true; |
| 160 // It's important not to wait for the DeleteTask to delete the channel | 163 // It's important not to wait for the DeleteTask to delete the channel |
| 161 // proxy. Kill it off now. That way, in case the profile is going away, the | 164 // proxy. Kill it off now. That way, in case the profile is going away, the |
| 162 // rest of the objects attached to this RenderProcessHost start going | 165 // rest of the objects attached to this RenderProcessHost start going |
| 163 // away first, since deleting the channel proxy will post a | 166 // away first, since deleting the channel proxy will post a |
| 164 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. | 167 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. |
| 165 channel_.reset(); | 168 channel_.reset(); |
| 166 | 169 |
| 167 // Remove ourself from the list of renderer processes so that we can't be | 170 // Remove ourself from the list of renderer processes so that we can't be |
| 168 // reused in between now and when the Delete task runs. | 171 // reused in between now and when the Delete task runs. |
| 169 all_hosts.Remove(id()); | 172 g_all_hosts.Get().Remove(id()); |
| 170 } | 173 } |
| 171 } | 174 } |
| 172 | 175 |
| 173 void RenderProcessHost::ReportExpectingClose(int32 listener_id) { | 176 void RenderProcessHost::ReportExpectingClose(int32 listener_id) { |
| 174 listeners_expecting_close_.insert(listener_id); | 177 listeners_expecting_close_.insert(listener_id); |
| 175 } | 178 } |
| 176 | 179 |
| 177 void RenderProcessHost::AddPendingView() { | 180 void RenderProcessHost::AddPendingView() { |
| 178 pending_views_++; | 181 pending_views_++; |
| 179 } | 182 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 190 | 193 |
| 191 bool RenderProcessHost::FastShutdownForPageCount(size_t count) { | 194 bool RenderProcessHost::FastShutdownForPageCount(size_t count) { |
| 192 if (listeners_.size() == count) | 195 if (listeners_.size() == count) |
| 193 return FastShutdownIfPossible(); | 196 return FastShutdownIfPossible(); |
| 194 return false; | 197 return false; |
| 195 } | 198 } |
| 196 | 199 |
| 197 // static | 200 // static |
| 198 RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { | 201 RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { |
| 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 200 return iterator(&all_hosts); | 203 return iterator(g_all_hosts.Pointer()); |
| 201 } | 204 } |
| 202 | 205 |
| 203 // static | 206 // static |
| 204 RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { | 207 RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { |
| 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 206 return all_hosts.Lookup(render_process_id); | 209 return g_all_hosts.Get().Lookup(render_process_id); |
| 207 } | 210 } |
| 208 | 211 |
| 209 // static | 212 // static |
| 210 bool RenderProcessHost::ShouldTryToUseExistingProcessHost() { | 213 bool RenderProcessHost::ShouldTryToUseExistingProcessHost() { |
| 211 size_t renderer_process_count = all_hosts.size(); | 214 size_t renderer_process_count = g_all_hosts.Get().size(); |
| 212 | 215 |
| 213 // NOTE: Sometimes it's necessary to create more render processes than | 216 // NOTE: Sometimes it's necessary to create more render processes than |
| 214 // GetMaxRendererProcessCount(), for instance when we want to create | 217 // GetMaxRendererProcessCount(), for instance when we want to create |
| 215 // a renderer process for a browser context that has no existing | 218 // a renderer process for a browser context that has no existing |
| 216 // renderers. This is OK in moderation, since the | 219 // renderers. This is OK in moderation, since the |
| 217 // GetMaxRendererProcessCount() is conservative. | 220 // GetMaxRendererProcessCount() is conservative. |
| 218 | 221 |
| 219 return run_renderer_in_process() || | 222 return run_renderer_in_process() || |
| 220 (renderer_process_count >= GetMaxRendererProcessCount()); | 223 (renderer_process_count >= GetMaxRendererProcessCount()); |
| 221 } | 224 } |
| 222 | 225 |
| 223 // static | 226 // static |
| 224 RenderProcessHost* RenderProcessHost::GetExistingProcessHost( | 227 RenderProcessHost* RenderProcessHost::GetExistingProcessHost( |
| 225 content::BrowserContext* browser_context, | 228 content::BrowserContext* browser_context, |
| 226 const GURL& site_url) { | 229 const GURL& site_url) { |
| 227 // First figure out which existing renderers we can use. | 230 // First figure out which existing renderers we can use. |
| 228 std::vector<RenderProcessHost*> suitable_renderers; | 231 std::vector<RenderProcessHost*> suitable_renderers; |
| 229 suitable_renderers.reserve(all_hosts.size()); | 232 suitable_renderers.reserve(g_all_hosts.Get().size()); |
| 230 | 233 |
| 231 iterator iter(AllHostsIterator()); | 234 iterator iter(AllHostsIterator()); |
| 232 while (!iter.IsAtEnd()) { | 235 while (!iter.IsAtEnd()) { |
| 233 if (run_renderer_in_process() || | 236 if (run_renderer_in_process() || |
| 234 IsSuitableHost(iter.GetCurrentValue(), browser_context, site_url)) | 237 IsSuitableHost(iter.GetCurrentValue(), browser_context, site_url)) |
| 235 suitable_renderers.push_back(iter.GetCurrentValue()); | 238 suitable_renderers.push_back(iter.GetCurrentValue()); |
| 236 | 239 |
| 237 iter.Advance(); | 240 iter.Advance(); |
| 238 } | 241 } |
| 239 | 242 |
| 240 // Now pick a random suitable renderer, if we have any. | 243 // Now pick a random suitable renderer, if we have any. |
| 241 if (!suitable_renderers.empty()) { | 244 if (!suitable_renderers.empty()) { |
| 242 int suitable_count = static_cast<int>(suitable_renderers.size()); | 245 int suitable_count = static_cast<int>(suitable_renderers.size()); |
| 243 int random_index = base::RandInt(0, suitable_count - 1); | 246 int random_index = base::RandInt(0, suitable_count - 1); |
| 244 return suitable_renderers[random_index]; | 247 return suitable_renderers[random_index]; |
| 245 } | 248 } |
| 246 | 249 |
| 247 return NULL; | 250 return NULL; |
| 248 } | 251 } |
| OLD | NEW |