From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Sun, 8 Jul 2018 22:42:04 +0200
Subject: Add flag to configure maximum connections per host

With the introduction of this flag it is possible to increase the maximum
allowed connections per host; this can however be detrimental to devices
with limited CPU/memory resources and it is disabled by default.
---
 chrome/browser/about_flags.cc                           |  8 ++++++++
 chrome/browser/flag_descriptions.cc                     |  4 ++++
 chrome/browser/flag_descriptions.h                      |  3 +++
 .../common/network_features.cc                          |  3 +++
 .../common/network_features.h                           |  4 ++++
 .../common/network_switch_list.h                        |  4 ++++
 net/socket/client_socket_pool_manager.cc                | 17 +++++++++++++++++
 7 files changed, 43 insertions(+)

diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -740,6 +740,11 @@ const FeatureEntry::Choice kForceEffectiveConnectionTypeChoices[] = {
      net::kEffectiveConnectionType4G},
 };
 
+const FeatureEntry::Choice kMaxConnectionsPerHostChoices[] = {
+    {features::kMaxConnectionsPerHostChoiceDefault, "", ""},
+    {features::kMaxConnectionsPerHostChoice15, switches::kMaxConnectionsPerHost, "15"},
+};
+
 // Ensure that all effective connection types returned by Network Quality
 // Estimator (NQE) are also exposed via flags.
 static_assert(net::EFFECTIVE_CONNECTION_TYPE_LAST + 2 ==
@@ -2292,6 +2297,9 @@ const FeatureEntry kFeatureEntries[] = {
      flag_descriptions::kWebrtcH264WithOpenh264FfmpegDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(content::kWebRtcH264WithOpenH264FFmpeg)},
 #endif  // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+    {"max-connections-per-host", flag_descriptions::kMaxConnectionsPerHostName,
+     flag_descriptions::kMaxConnectionsPerHostDescription, kOsAll,
+     MULTI_VALUE_TYPE(kMaxConnectionsPerHostChoices)},
 #if defined(OS_ANDROID)
     {"offlining-recent-pages", flag_descriptions::kOffliningRecentPagesName,
      flag_descriptions::kOffliningRecentPagesDescription, kOsAndroid,
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1245,6 +1245,10 @@ const char kLookalikeUrlNavigationSuggestionsDescription[] =
 const char kMarkHttpAsName[] = "Mark non-secure origins as non-secure";
 const char kMarkHttpAsDescription[] = "Change the UI treatment for HTTP pages";
 
+const char kMaxConnectionsPerHostName[] = "Maximum connections per host";
+const char kMaxConnectionsPerHostDescription[] =
+     "Customize maximum allowed connections per host.";
+
 const char kMediaRouterCastAllowAllIPsName[] =
     "Connect to Cast devices on all IP addresses";
 const char kMediaRouterCastAllowAllIPsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -748,6 +748,9 @@ extern const char kMarkHttpAsWarning[];
 extern const char kMarkHttpAsWarningAndDangerousOnFormEdits[];
 extern const char kMarkHttpAsWarningAndDangerousOnPasswordsAndCreditCards[];
 
+extern const char kMaxConnectionsPerHostName[];
+extern const char kMaxConnectionsPerHostDescription[];
+
 extern const char kMediaRouterCastAllowAllIPsName[];
 extern const char kMediaRouterCastAllowAllIPsDescription[];
 
diff --git a/components/network_session_configurator/common/network_features.cc b/components/network_session_configurator/common/network_features.cc
--- a/components/network_session_configurator/common/network_features.cc
+++ b/components/network_session_configurator/common/network_features.cc
@@ -8,6 +8,9 @@
 
 namespace features {
 
+const char kMaxConnectionsPerHostChoiceDefault[] = "6",
+                 kMaxConnectionsPerHostChoice15[] = "15";
+
 const char kDnsOverHttpsChoiceDefault[] = "Disabled",
                  kDnsOverHttpsChoiceGoogle[] = "Google",
                  kDnsOverHttpsChoiceCloudflare[] = "Cloudflare",
diff --git a/components/network_session_configurator/common/network_features.h b/components/network_session_configurator/common/network_features.h
--- a/components/network_session_configurator/common/network_features.h
+++ b/components/network_session_configurator/common/network_features.h
@@ -10,6 +10,10 @@
 
 namespace features {
 
+NETWORK_SESSION_CONFIGURATOR_EXPORT extern const char kMaxConnectionsPerHostChoiceDefault[],
+                 kMaxConnectionsPerHostChoice6[],
+                 kMaxConnectionsPerHostChoice15[];
+
 // DNS over HTTPS server endpoint choices
 // (https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-12.txt).
 NETWORK_SESSION_CONFIGURATOR_EXPORT extern const base::Feature kDnsOverHttps;
diff --git a/components/network_session_configurator/common/network_switch_list.h b/components/network_session_configurator/common/network_switch_list.h
--- a/components/network_session_configurator/common/network_switch_list.h
+++ b/components/network_session_configurator/common/network_switch_list.h
@@ -21,6 +21,10 @@ NETWORK_SWITCH(kEnableUserAlternateProtocolPorts,
 
 // Enables the QUIC protocol.  This is a temporary testing flag.
 NETWORK_SWITCH(kEnableQuic, "enable-quic")
+// Allows specifying a higher number of maximum connections per host
+// (15 instead of 6, mirroring the value Mozilla uses).
+NETWORK_SWITCH(kMaxConnectionsPerHost, "max-connections-per-host")
+
 
 // Ignores certificate-related errors.
 NETWORK_SWITCH(kIgnoreCertificateErrors, "ignore-certificate-errors")
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -22,6 +22,10 @@
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/ssl/ssl_config.h"
+#include "components/network_session_configurator/common/network_switches.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
 
 namespace net {
 
@@ -285,6 +289,19 @@ void ClientSocketPoolManager::set_max_sockets_per_pool(
 int ClientSocketPoolManager::max_sockets_per_group(
     HttpNetworkSession::SocketPoolType pool_type) {
   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
+
+  if (pool_type == HttpNetworkSession::NORMAL_SOCKET_POOL) {
+      int maxConnectionsPerHost = 0;
+      auto value = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kMaxConnectionsPerHost);
+      if (!value.empty() && !base::StringToInt(value, &maxConnectionsPerHost)) {
+        LOG(DFATAL) << "--" << switches::kMaxConnectionsPerHost << " only accepts integers as arguments (\"" << value << "\" is invalid)";
+      }
+      if (maxConnectionsPerHost != 0) {
+        return maxConnectionsPerHost;
+      }
+      // fallthrough for default value
+  }
+
   return g_max_sockets_per_group[pool_type];
 }
 
-- 
2.11.0

