summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host/render_process_host.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/renderer_host/render_process_host.cc')
-rw-r--r--chrome/browser/renderer_host/render_process_host.cc197
1 files changed, 197 insertions, 0 deletions
diff --git a/chrome/browser/renderer_host/render_process_host.cc b/chrome/browser/renderer_host/render_process_host.cc
new file mode 100644
index 0000000..959252e
--- /dev/null
+++ b/chrome/browser/renderer_host/render_process_host.cc
@@ -0,0 +1,197 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/render_process_host.h"
+
+#include "base/rand_util.h"
+#include "base/sys_info.h"
+#include "chrome/browser/child_process_security_policy.h"
+#include "chrome/common/child_process_info.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/notification_service.h"
+
+namespace {
+
+size_t max_renderer_count_override = 0;
+
+size_t GetMaxRendererProcessCount() {
+ if (max_renderer_count_override)
+ return max_renderer_count_override;
+
+ // Defines the maximum number of renderer processes according to the
+ // amount of installed memory as reported by the OS. The table
+ // values are calculated by assuming that you want the renderers to
+ // use half of the installed ram and assuming that each tab uses
+ // ~40MB, however the curve is not linear but piecewise linear with
+ // interleaved slopes of 3 and 2.
+ // If you modify this table you need to adjust browser\browser_uitest.cc
+ // to match the expected number of processes.
+
+ static const size_t kMaxRenderersByRamTier[] = {
+ 3, // less than 256MB
+ 6, // 256MB
+ 9, // 512MB
+ 12, // 768MB
+ 14, // 1024MB
+ 18, // 1280MB
+ 20, // 1536MB
+ 22, // 1792MB
+ 24, // 2048MB
+ 26, // 2304MB
+ 29, // 2560MB
+ 32, // 2816MB
+ 35, // 3072MB
+ 38, // 3328MB
+ 40 // 3584MB
+ };
+
+ static size_t max_count = 0;
+ if (!max_count) {
+ size_t memory_tier = base::SysInfo::AmountOfPhysicalMemoryMB() / 256;
+ if (memory_tier >= arraysize(kMaxRenderersByRamTier))
+ max_count = chrome::kMaxRendererProcessCount;
+ else
+ max_count = kMaxRenderersByRamTier[memory_tier];
+ }
+ return max_count;
+}
+
+// Returns true if the given host is suitable for launching a new view
+// associated with the given profile.
+static bool IsSuitableHost(RenderProcessHost* host, Profile* profile,
+ RenderProcessHost::Type type) {
+ if (host->profile() != profile)
+ return false;
+
+ RenderProcessHost::Type host_type = RenderProcessHost::TYPE_NORMAL;
+ if (ChildProcessSecurityPolicy::GetInstance()->HasDOMUIBindings(host->id()))
+ host_type = RenderProcessHost::TYPE_DOMUI;
+ if (ChildProcessSecurityPolicy::GetInstance()->
+ HasExtensionBindings(host->id()))
+ host_type = RenderProcessHost::TYPE_EXTENSION;
+
+ return host_type == type;
+}
+
+// the global list of all renderer processes
+IDMap<RenderProcessHost> all_hosts;
+
+} // namespace
+
+// static
+bool RenderProcessHost::run_renderer_in_process_ = false;
+
+// static
+void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
+ max_renderer_count_override = count;
+}
+
+RenderProcessHost::RenderProcessHost(Profile* profile)
+ : max_page_id_(-1),
+ fast_shutdown_started_(false),
+ id_(ChildProcessInfo::GenerateChildProcessUniqueId()),
+ profile_(profile),
+ sudden_termination_allowed_(true),
+ ignore_input_events_(false) {
+ all_hosts.AddWithID(this, id());
+ all_hosts.set_check_on_null_data(true);
+ // Initialize |child_process_activity_time_| to a reasonable value.
+ mark_child_process_activity_time();
+}
+
+RenderProcessHost::~RenderProcessHost() {
+ // In unit tests, Release() might not have been called.
+ if (all_hosts.Lookup(id()))
+ all_hosts.Remove(id());
+}
+
+void RenderProcessHost::Attach(IPC::Channel::Listener* listener,
+ int routing_id) {
+ listeners_.AddWithID(listener, routing_id);
+}
+
+void RenderProcessHost::Release(int listener_id) {
+ DCHECK(listeners_.Lookup(listener_id) != NULL);
+ listeners_.Remove(listener_id);
+
+ // Make sure that all associated resource requests are stopped.
+ CancelResourceRequests(listener_id);
+
+ // When no other owners of this object, we can delete ourselves
+ if (listeners_.IsEmpty()) {
+ NotificationService::current()->Notify(
+ NotificationType::RENDERER_PROCESS_TERMINATED,
+ Source<RenderProcessHost>(this), NotificationService::NoDetails());
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+
+ // Remove ourself from the list of renderer processes so that we can't be
+ // reused in between now and when the Delete task runs.
+ all_hosts.Remove(id());
+ }
+}
+
+void RenderProcessHost::ReportExpectingClose(int32 listener_id) {
+ listeners_expecting_close_.insert(listener_id);
+}
+
+void RenderProcessHost::UpdateMaxPageID(int32 page_id) {
+ if (page_id > max_page_id_)
+ max_page_id_ = page_id;
+}
+
+bool RenderProcessHost::FastShutdownForPageCount(size_t count) {
+ if (listeners_.size() == count)
+ return FastShutdownIfPossible();
+ return false;
+}
+
+// static
+RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
+ return iterator(&all_hosts);
+}
+
+// static
+RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
+ return all_hosts.Lookup(render_process_id);
+}
+
+// static
+bool RenderProcessHost::ShouldTryToUseExistingProcessHost() {
+ size_t renderer_process_count = all_hosts.size();
+
+ // NOTE: Sometimes it's necessary to create more render processes than
+ // GetMaxRendererProcessCount(), for instance when we want to create
+ // a renderer process for a profile that has no existing renderers.
+ // This is OK in moderation, since the GetMaxRendererProcessCount()
+ // is conservative.
+
+ return run_renderer_in_process() ||
+ (renderer_process_count >= GetMaxRendererProcessCount());
+}
+
+// static
+RenderProcessHost* RenderProcessHost::GetExistingProcessHost(Profile* profile,
+ Type type) {
+ // First figure out which existing renderers we can use.
+ std::vector<RenderProcessHost*> suitable_renderers;
+ suitable_renderers.reserve(all_hosts.size());
+
+ iterator iter(AllHostsIterator());
+ while (!iter.IsAtEnd()) {
+ if (run_renderer_in_process() ||
+ IsSuitableHost(iter.GetCurrentValue(), profile, type))
+ suitable_renderers.push_back(iter.GetCurrentValue());
+
+ iter.Advance();
+ }
+
+ // Now pick a random suitable renderer, if we have any.
+ if (!suitable_renderers.empty()) {
+ int suitable_count = static_cast<int>(suitable_renderers.size());
+ int random_index = base::RandInt(0, suitable_count - 1);
+ return suitable_renderers[random_index];
+ }
+
+ return NULL;
+}