Add finch config param for cronet and Chrome to retry QUIC connection on the alternate network before handshake.

The feature will be controlled by "retry_on_alternate_network_before_handshake".

Bug: 790547
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;master.tryserver.chromium.android:android_cronet_tester
Change-Id: I5812083fe317f996313adce49f9bbd1d14b22f37
Reviewed-on: https://chromium-review.googlesource.com/1242038
Reviewed-by: Misha Efimov <[email protected]>
Reviewed-by: Ryan Hamilton <[email protected]>
Commit-Queue: Misha Efimov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#594386}
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index 59f2ecf..ac54aaa 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -74,6 +74,8 @@
     "max_migrations_to_non_default_network_on_path_degrading";
 const char kQuicUserAgentId[] = "user_agent_id";
 const char kQuicMigrateSessionsEarlyV2[] = "migrate_sessions_early_v2";
+const char kQuicRetryOnAlternateNetworkBeforeHandshake[] =
+    "retry_on_alternate_network_before_handshake";
 const char kQuicDisableBidirectionalStreams[] =
     "quic_disable_bidirectional_streams";
 const char kQuicRaceCertVerification[] = "race_cert_verification";
@@ -433,6 +435,14 @@
             quic_migrate_sessions_early_v2;
       }
 
+      bool quic_retry_on_alternate_network_before_handshake = false;
+      if (quic_args->GetBoolean(
+              kQuicRetryOnAlternateNetworkBeforeHandshake,
+              &quic_retry_on_alternate_network_before_handshake)) {
+        session_params->quic_retry_on_alternate_network_before_handshake =
+            quic_retry_on_alternate_network_before_handshake;
+      }
+
       bool quic_disable_bidirectional_streams = false;
       if (quic_args->GetBoolean(kQuicDisableBidirectionalStreams,
                                 &quic_disable_bidirectional_streams)) {
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc
index 05bb0e5..53c7de1c 100644
--- a/components/cronet/url_request_context_config_unittest.cc
+++ b/components/cronet/url_request_context_config_unittest.cc
@@ -203,6 +203,7 @@
   EXPECT_FALSE(params->quic_allow_server_migration);
   EXPECT_FALSE(params->quic_migrate_sessions_on_network_change_v2);
   EXPECT_FALSE(params->quic_migrate_sessions_early_v2);
+  EXPECT_FALSE(params->quic_retry_on_alternate_network_before_handshake);
 
   // Check race_cert_verification.
   EXPECT_TRUE(params->quic_race_cert_verification);
@@ -545,6 +546,7 @@
       // JSON encoded experimental options.
       "{\"QUIC\":{\"migrate_sessions_on_network_change_v2\":true,"
       "\"migrate_sessions_early_v2\":true,"
+      "\"retry_on_alternate_network_before_handshake\":true,"
       "\"max_time_on_non_default_network_seconds\":10,"
       "\"max_migrations_to_non_default_network_on_write_error\":3,"
       "\"max_migrations_to_non_default_network_on_path_degrading\":4}}",
@@ -570,6 +572,7 @@
 
   EXPECT_TRUE(params->quic_migrate_sessions_on_network_change_v2);
   EXPECT_TRUE(params->quic_migrate_sessions_early_v2);
+  EXPECT_TRUE(params->quic_retry_on_alternate_network_before_handshake);
   EXPECT_EQ(base::TimeDelta::FromSeconds(10),
             params->quic_max_time_on_non_default_network);
   EXPECT_EQ(3,
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc
index fffb2fa..0832147 100644
--- a/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -315,6 +315,14 @@
       "true");
 }
 
+bool ShouldQuicRetryOnAlternateNetworkBeforeHandshake(
+    const VariationParameters& quic_trial_params) {
+  return base::LowerCaseEqualsASCII(
+      GetVariationParam(quic_trial_params,
+                        "retry_on_alternate_network_before_handshake"),
+      "true");
+}
+
 bool ShouldQuicGoawayOnPathDegrading(
     const VariationParameters& quic_trial_params) {
   return base::LowerCaseEqualsASCII(
@@ -461,6 +469,8 @@
         ShouldQuicMigrateSessionsOnNetworkChangeV2(quic_trial_params);
     params->quic_migrate_sessions_early_v2 =
         ShouldQuicMigrateSessionsEarlyV2(quic_trial_params);
+    params->quic_retry_on_alternate_network_before_handshake =
+        ShouldQuicRetryOnAlternateNetworkBeforeHandshake(quic_trial_params);
     params->quic_go_away_on_path_degrading =
         ShouldQuicGoawayOnPathDegrading(quic_trial_params);
     int max_time_on_non_default_network_seconds =
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index 89c9f46d..d2848e7f 100644
--- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -118,6 +118,7 @@
   EXPECT_FALSE(params_.quic_estimate_initial_rtt);
   EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change_v2);
   EXPECT_FALSE(params_.quic_migrate_sessions_early_v2);
+  EXPECT_FALSE(params_.quic_retry_on_alternate_network_before_handshake);
   EXPECT_FALSE(params_.quic_go_away_on_path_degrading);
   EXPECT_FALSE(params_.quic_allow_server_migration);
   EXPECT_TRUE(params_.quic_host_whitelist.empty());
@@ -348,6 +349,18 @@
 }
 
 TEST_F(NetworkSessionConfiguratorTest,
+       QuicRetryOnAlternateNetworkBeforeHandshakeFromFieldTrialParams) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["retry_on_alternate_network_before_handshake"] = "true";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_TRUE(params_.quic_retry_on_alternate_network_before_handshake);
+}
+
+TEST_F(NetworkSessionConfiguratorTest,
        QuicGoawayOnPathDegradingFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["go_away_on_path_degrading"] = "true";