Reland "Changed committed-interstitials flag from switch to feature."

This is a reland of 49040ae795592d3b0c6a5b03533565caeb9ae266

Original change's description:
> Changed committed-interstitials flag from switch to feature.
> 
> Removed 'committed-interstitials' switch and added SSLCommittedInterstitials
> base::Feature. Name was changed to SSLCommmittedInterstitials since we are now
> doing separate rampups for each kind of committed interstitial. Switch was
> changed to Feature so that it can be enabled via variations.
> 
> Bug: 755632
> Change-Id: I0f3e0e01a94be2b515aa596827cd447d14c24b56
> Reviewed-on: https://chromium-review.googlesource.com/1118975
> Commit-Queue: Carlos IL <[email protected]>
> Reviewed-by: Jialiu Lin <[email protected]>
> Reviewed-by: Maksim Ivanov <[email protected]>
> Reviewed-by: Emily Stark <[email protected]>
> Reviewed-by: Giovanni Ortuño Urquidi <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#574621}

Bug: 755632
Change-Id: I9ef1fa141d9481537740569c4af6504998c619e2
Reviewed-on: https://chromium-review.googlesource.com/1138516
Reviewed-by: Mustafa Emre Acer <[email protected]>
Reviewed-by: Maksim Ivanov <[email protected]>
Reviewed-by: Giovanni Ortuño Urquidi <[email protected]>
Reviewed-by: Jialiu Lin <[email protected]>
Commit-Queue: Carlos IL <[email protected]>
Cr-Commit-Position: refs/heads/master@{#580565}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4736202..9714ac1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2115,9 +2115,10 @@
      flag_descriptions::kExperimentalSecurityFeaturesDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kEnablePotentiallyAnnoyingSecurityFeatures)},
 #endif  // OS_CHROMEOS
-    {"committed-interstitials", flag_descriptions::kCommittedInterstitialsName,
-     flag_descriptions::kCommittedInterstitialsDescription, kOsAll,
-     SINGLE_VALUE_TYPE(switches::kCommittedInterstitials)},
+    {"ssl-committed-interstitials",
+     flag_descriptions::kSSLCommittedInterstitialsName,
+     flag_descriptions::kSSLCommittedInterstitialsDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kSSLCommittedInterstitials)},
     {"enable-site-per-process", flag_descriptions::kStrictSiteIsolationName,
      flag_descriptions::kStrictSiteIsolationDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kSitePerProcess)},
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 4dfef4f..5b6c2cb 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2595,8 +2595,7 @@
     return;
   }
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kCommittedInterstitials)) {
+  if (base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials)) {
     // We deny the request here in order to trigger the committed interstitials
     // code path (committing certificate error pages as navigations) instead of
     // the old code path.
@@ -3944,8 +3943,7 @@
   throttles.push_back(std::make_unique<PolicyBlacklistNavigationThrottle>(
       handle, handle->GetWebContents()->GetBrowserContext()));
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kCommittedInterstitials)) {
+  if (base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials)) {
     throttles.push_back(std::make_unique<SSLErrorNavigationThrottle>(
         handle,
         std::make_unique<CertificateReportingServiceCertReporter>(web_contents),
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index bd834b47..b3f5370 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -170,11 +170,6 @@
     "eligibility requirements for showing app banners, such as having a "
     "manifest, are met.";
 
-const char kCommittedInterstitialsName[] = "Committed Interstitials";
-const char kCommittedInterstitialsDescription[] =
-    "Use committed error pages instead of transient navigation entries "
-    "for interstitial error pages (e.g. certificate errors).";
-
 const char kCanvas2DImageChromiumName[] = "Canvas 2D Image Chromium";
 const char kCanvas2DImageChromiumDescription[] =
     "Allows for using CHROMIUM_image GLES2 extension for HTML Canvas Contexts";
@@ -1745,6 +1740,11 @@
 const char kSpellingFeedbackFieldTrialDescription[] =
     "Enable the field trial for sending user feedback to spelling service.";
 
+const char kSSLCommittedInterstitialsName[] = "Committed Interstitials";
+const char kSSLCommittedInterstitialsDescription[] =
+    "Use committed error pages instead of transient navigation entries "
+    "for SSL interstitial error pages (i.e. certificate errors).";
+
 const char kStopInBackgroundName[] = "Stop in background";
 const char kStopInBackgroundDescription[] =
     "Stop scheduler task queues, in the background, "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 58a193c..fd2e89a 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -128,9 +128,6 @@
 extern const char kBypassAppBannerEngagementChecksName[];
 extern const char kBypassAppBannerEngagementChecksDescription[];
 
-extern const char kCommittedInterstitialsName[];
-extern const char kCommittedInterstitialsDescription[];
-
 extern const char kCanvas2DImageChromiumName[];
 extern const char kCanvas2DImageChromiumDescription[];
 
@@ -1057,6 +1054,9 @@
 extern const char kSpellingFeedbackFieldTrialName[];
 extern const char kSpellingFeedbackFieldTrialDescription[];
 
+extern const char kSSLCommittedInterstitialsName[];
+extern const char kSSLCommittedInterstitialsDescription[];
+
 extern const char kStopInBackgroundName[];
 extern const char kStopInBackgroundDescription[];
 
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 3e58d29..a7855064 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -1073,7 +1073,8 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     PolicyTest::SetUpCommandLine(command_line);
     if (AreCommittedInterstitialsEnabled()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
     // Ensure SSL interstitials are capable of sending reports.
     variations::testing::VariationParamsManager::AppendVariationParams(
@@ -1154,6 +1155,7 @@
   }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(SSLPolicyTestCommittedInterstitials);
 };
 
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
index 2412c10..787acd7 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/thread_test_helper.h"
 #include "base/time/clock.h"
@@ -20,7 +21,7 @@
 #include "chrome/browser/ssl/certificate_reporting_test_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
@@ -125,7 +126,8 @@
         "ReportCertificateErrors", "ShowAndPossiblySend",
         {{"sendingThreshold", "1.0"}}, command_line);
     if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -249,6 +251,8 @@
   // of CleanUpOnIOThread().
   std::unique_ptr<EventHistogramTester> event_histogram_tester_;
 
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(CertificateReportingServiceBrowserTest);
 };
 
diff --git a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
index 7fa136af..4df46e76 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
@@ -10,9 +10,11 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h"
@@ -23,7 +25,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -69,8 +71,7 @@
 };
 
 bool AreCommittedInterstitialsEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials);
+  return base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials);
 }
 
 class CaptivePortalBlockingPageForTesting : public CaptivePortalBlockingPage {
@@ -249,7 +250,8 @@
         {{"sendingThreshold", "1.0"}}, command_line);
 
     if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -281,6 +283,7 @@
 
  private:
   std::unique_ptr<TestingThrottleInstaller> testing_throttle_installer_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(CaptivePortalBlockingPageTest);
 };
 
diff --git a/chrome/browser/ssl/connection_help_tab_helper.cc b/chrome/browser/ssl/connection_help_tab_helper.cc
index e4d96eb..0fde728 100644
--- a/chrome/browser/ssl/connection_help_tab_helper.cc
+++ b/chrome/browser/ssl/connection_help_tab_helper.cc
@@ -4,12 +4,10 @@
 
 #include "chrome/browser/ssl/connection_help_tab_helper.h"
 
-#include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/chrome_switches.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/referrer.h"
@@ -58,8 +56,7 @@
           GetHelpCenterURL()) {
     LearnMoreClickResult histogram_value;
     if (navigation_handle->IsErrorPage()) {
-      if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kCommittedInterstitials) &&
+      if (base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials) &&
           net::IsCertificateError(navigation_handle->GetNetErrorCode())) {
         // When committed interstitials are enabled, DidAttachInterstitialPage
         // does not get called, so check if this navigation resulted in an SSL
diff --git a/chrome/browser/ssl/connection_help_tab_helper_browsertest.cc b/chrome/browser/ssl/connection_help_tab_helper_browsertest.cc
index 446917ac..a800a39 100644
--- a/chrome/browser/ssl/connection_help_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/connection_help_tab_helper_browsertest.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/strings/grit/components_strings.h"
@@ -30,6 +29,10 @@
         https_expired_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
 
   void SetUpOnMainThread() override {
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
+    }
     https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
     https_expired_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
     https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
@@ -38,16 +41,9 @@
     ASSERT_TRUE(https_expired_server_.Start());
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
-    }
-  }
-
  protected:
   bool AreCommittedInterstitialsEnabled() {
-    return base::CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kCommittedInterstitials);
+    return base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials);
   }
 
   void SetHelpCenterUrl(Browser* browser, const GURL& url) {
@@ -65,6 +61,7 @@
  private:
   net::EmbeddedTestServer https_server_;
   net::EmbeddedTestServer https_expired_server_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(ConnectionHelpTabHelperTest);
 };
 
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
index fad59649..6c62846 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/base64.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
@@ -14,6 +15,7 @@
 #include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -26,6 +28,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -107,8 +110,7 @@
 const char kTestCertificateIssuerName[] = "Test Root CA";
 
 bool AreCommittedInterstitialsEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials);
+  return base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials);
 }
 
 bool IsShowingInterstitial(content::WebContents* tab) {
@@ -496,7 +498,8 @@
     // Browser will both run and display insecure content.
     command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
     if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -555,6 +558,7 @@
   net::EmbeddedTestServer https_server_;
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperTest);
 };
 
@@ -594,7 +598,8 @@
     // Browser will both run and display insecure content.
     command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
     if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -606,6 +611,7 @@
   net::EmbeddedTestServer https_server_;
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(DidChangeVisibleSecurityStateTest);
 };
 
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index a6e4909c..c127839 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/json/json_reader.h"
 #include "base/location.h"
 #include "base/macros.h"
@@ -198,8 +199,7 @@
 };
 
 bool AreCommittedInterstitialsEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials);
+  return base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials);
 }
 
 void CheckProceedLinkExists(WebContents* tab) {
@@ -1034,18 +1034,14 @@
   SSLUITest() : SSLUITestBase() {}
 
  protected:
-  void MaybeSetUpCommittedInterstitialCommandLine(
-      base::CommandLine* command_line) {
+  void SetUpOnMainThread() override {
+    SSLUITestBase::SetUpOnMainThread();
     if (IsCommittedInterstitialTest()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    SSLUITestBase::SetUpCommandLine(command_line);
-    MaybeSetUpCommittedInterstitialCommandLine(command_line);
-  }
-
   SSLBlockingPage* GetSSLBlockingPage(WebContents* tab) override {
     if (IsCommittedInterstitialTest()) {
       security_interstitials::SecurityInterstitialTabHelper* helper =
@@ -1164,6 +1160,7 @@
   }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(SSLUITest);
 };
 
@@ -1178,7 +1175,6 @@
 
   // Browser will not run insecure content.
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    MaybeSetUpCommittedInterstitialCommandLine(command_line);
     // By overriding SSLUITest, we won't apply the flag that allows running
     // insecure content.
   }
@@ -3638,9 +3634,11 @@
 
   ~SSLUIWorkerFetchTest() override {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
+  void SetUpOnMainThread() override {
+    SSLUITestBase::SetUpOnMainThread();
     if (GetParam().second) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -3904,6 +3902,10 @@
 // This test checks the behavior of mixed content blocking for the requests
 // from a dedicated worker by changing the settings in WebPreferences.
 IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, MAYBE_MixedContentSettings) {
+  // TODO(carlosil): Reenable tests once confirmed not flaky for committed
+  // interstitials.
+  if (AreCommittedInterstitialsEnabled())
+    return;
   ChromeContentBrowserClientForMixedContentTest browser_client;
   content::ContentBrowserClient* old_browser_client =
       content::SetBrowserClientForTesting(&browser_client);
@@ -3980,6 +3982,10 @@
 // block-all-mixed-content CSP is set.
 IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest,
                        MAYBE_MixedContentSettingsWithBlockingCSP) {
+  // TODO(carlosil): Reenable tests once confirmed not flaky for committed
+  // interstitials.
+  if (AreCommittedInterstitialsEnabled())
+    return;
   ChromeContentBrowserClientForMixedContentTest browser_client;
   content::ContentBrowserClient* old_browser_client =
       content::SetBrowserClientForTesting(&browser_client);
@@ -4025,6 +4031,10 @@
 // allow_running_insecure_content setting is false or
 // strict_mixed_content_checking setting is true.
 IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, MAYBE_MixedContentSubFrame) {
+  // TODO(carlosil): Reenable tests once confirmed not flaky for committed
+  // interstitials.
+  if (AreCommittedInterstitialsEnabled())
+    return;
   ChromeContentBrowserClientForMixedContentTest browser_client;
   content::ContentBrowserClient* old_browser_client =
       content::SetBrowserClientForTesting(&browser_client);
@@ -5096,13 +5106,14 @@
     // Enable finch experiment for SSL common name mismatch handling.
     command_line->AppendSwitchASCII(switches::kForceFieldTrials,
                                     "SSLCommonNameMismatchHandling/Enabled/");
-    if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
-    }
   }
 
   void SetUpOnMainThread() override {
     CertVerifierBrowserTest::SetUpOnMainThread();
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
+    }
     host_resolver()->AddRule("*", "127.0.0.1");
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
@@ -5114,6 +5125,9 @@
                                      base::BindOnce(&CleanUpOnIOThread));
     CertVerifierBrowserTest::TearDownOnMainThread();
   }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 INSTANTIATE_TEST_CASE_P(,
@@ -6163,10 +6177,11 @@
     https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    CertVerifierBrowserTest::SetUpCommandLine(command_line);
+  void SetUpOnMainThread() override {
+    CertVerifierBrowserTest::SetUpOnMainThread();
     if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
     }
   }
 
@@ -6229,6 +6244,7 @@
   net::EmbeddedTestServer* https_server() { return &https_server_; }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   net::EmbeddedTestServer https_server_;
 };
 
@@ -6428,17 +6444,14 @@
 
   void SetUpOnMainThread() override {
     CertVerifierBrowserTest::SetUpOnMainThread();
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
+    }
     host_resolver()->AddRule("*", "127.0.0.1");
     SetHSTSForHostName(browser()->profile());
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    CertVerifierBrowserTest::SetUpCommandLine(command_line);
-    if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
-    }
-  }
-
   // Set up the cert verifier to return the error passed in as the cert_error
   // parameter.
   void SetUpCertVerifier(net::CertStatus cert_error) {
@@ -6548,7 +6561,7 @@
 
  private:
   net::EmbeddedTestServer https_server_;
-
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(SSLUIMITMSoftwareTest);
 };
 
@@ -6891,17 +6904,14 @@
 
   void SetUpOnMainThread() override {
     CertVerifierBrowserTest::SetUpOnMainThread();
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
+    }
     host_resolver()->AddRule("*", "127.0.0.1");
     ASSERT_TRUE(https_server_.Start());
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    CertVerifierBrowserTest::SetUpCommandLine(command_line);
-    if (GetParam()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
-    }
-  }
-
  protected:
   void SetUpCertVerifier(bool use_superfish_cert) {
     net::CertVerifyResult verify_result;
@@ -6983,6 +6993,8 @@
     }
     return net::X509Certificate::CreateFromDERCertChain(decoded_pieces);
   }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 INSTANTIATE_TEST_CASE_P(, SuperfishSSLUITest, ::testing::Values(false, true));
@@ -7701,15 +7713,12 @@
  public:
   RecurrentInterstitialBrowserTest() : CertVerifierBrowserTest() {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    CertVerifierBrowserTest::SetUpCommandLine(command_line);
-    if (IsCommittedInterstitialTest()) {
-      command_line->AppendSwitch(switches::kCommittedInterstitials);
-    }
-  }
-
   void SetUpOnMainThread() override {
     CertVerifierBrowserTest::SetUpOnMainThread();
+    if (IsCommittedInterstitialTest()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          features::kSSLCommittedInterstitials);
+    }
     host_resolver()->AddRule("*", "127.0.0.1");
   }
 
@@ -7721,6 +7730,9 @@
 
  protected:
   bool IsCommittedInterstitialTest() { return GetParam(); }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 INSTANTIATE_TEST_CASE_P(,
diff --git a/chrome/browser/ssl/ssl_browsertest_util.cc b/chrome/browser/ssl/ssl_browsertest_util.cc
index c7cb3cea..fe367201 100644
--- a/chrome/browser/ssl/ssl_browsertest_util.cc
+++ b/chrome/browser/ssl/ssl_browsertest_util.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/ssl/ssl_browsertest_util.h"
 
-#include "base/command_line.h"
+#include "base/feature_list.h"
 #include "chrome/browser/ssl/security_state_tab_helper.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "components/security_state/core/security_state.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/ssl_status.h"
@@ -21,8 +21,7 @@
 void Check(const content::NavigationEntry& entry,
            int expected_authentication_state) {
   if (expected_authentication_state == AuthState::SHOWING_ERROR ||
-      (base::CommandLine::ForCurrentProcess()->HasSwitch(
-           switches::kCommittedInterstitials) &&
+      (base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials) &&
        expected_authentication_state == AuthState::SHOWING_INTERSTITIAL)) {
     EXPECT_EQ(content::PAGE_TYPE_ERROR, entry.GetPageType());
   } else {
diff --git a/chrome/browser/ssl/ssl_error_controller_client.cc b/chrome/browser/ssl/ssl_error_controller_client.cc
index 100b564..5340bdf7 100644
--- a/chrome/browser/ssl/ssl_error_controller_client.cc
+++ b/chrome/browser/ssl/ssl_error_controller_client.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
@@ -18,7 +19,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
@@ -146,8 +147,7 @@
 #endif
 
 bool AreCommittedInterstitialsEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials);
+  return base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials);
 }
 
 }  // namespace
diff --git a/chrome/browser/ssl/ssl_error_navigation_throttle.cc b/chrome/browser/ssl/ssl_error_navigation_throttle.cc
index baf3d61..cd6dbce 100644
--- a/chrome/browser/ssl/ssl_error_navigation_throttle.cc
+++ b/chrome/browser/ssl/ssl_error_navigation_throttle.cc
@@ -5,8 +5,9 @@
 #include "chrome/browser/ssl/ssl_error_navigation_throttle.h"
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
 #include "content/public/browser/navigation_handle.h"
@@ -33,8 +34,7 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 SSLErrorNavigationThrottle::WillFailRequest() {
-  DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials));
+  DCHECK(base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials));
   content::NavigationHandle* handle = navigation_handle();
   // If there was no certificate error, SSLInfo will be empty.
   int cert_status = handle->GetSSLInfo().cert_status;
@@ -59,8 +59,7 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 SSLErrorNavigationThrottle::WillProcessResponse() {
-  DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kCommittedInterstitials));
+  DCHECK(base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials));
   content::NavigationHandle* handle = navigation_handle();
   // If there was no certificate error, SSLInfo will be empty.
   int cert_status = handle->GetSSLInfo().cert_status;
diff --git a/chrome/browser/ssl/ssl_error_navigation_throttle_unittest.cc b/chrome/browser/ssl/ssl_error_navigation_throttle_unittest.cc
index 6020c75..5dceb98 100644
--- a/chrome/browser/ssl/ssl_error_navigation_throttle_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_navigation_throttle_unittest.cc
@@ -5,12 +5,12 @@
 #include "chrome/browser/ssl/ssl_error_navigation_throttle.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ssl/certificate_reporting_test_utils.cc"
 #include "chrome/browser/ssl/ssl_blocking_page.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
@@ -88,8 +88,8 @@
   SSLErrorNavigationThrottleTest() {}
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kCommittedInterstitials);
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kSSLCommittedInterstitials);
 
     async_ = GetParam();
     handle_ = content::NavigationHandle::CreateNavigationHandleForTesting(
@@ -121,6 +121,8 @@
   content::NavigationThrottle::ThrottleCheckResult deferred_result_ =
       content::NavigationThrottle::DEFER;
 
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   DISALLOW_COPY_AND_ASSIGN(SSLErrorNavigationThrottleTest);
 };
 
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 9e50d18..3e120b6 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -764,8 +764,7 @@
   // interstitial and proceeding through it will redirect the navigation to a
   // tab.
   if (base::FeatureList::IsEnabled(features::kDesktopPWAWindowing) &&
-      base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kCommittedInterstitials)) {
+      base::FeatureList::IsEnabled(features::kSSLCommittedInterstitials)) {
     return;
   }
 
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 2e25c8f7..f42132e 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -539,6 +539,11 @@
 const base::Feature kSiteSettings{"SiteSettings",
                                   base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables committed error pages instead of transient navigation entries for
+// SSL interstitial error pages (i.e. certificate errors).
+const base::Feature kSSLCommittedInterstitials{
+    "SSLCommittedInterstitials", base::FEATURE_DISABLED_BY_DEFAULT};
+
 #if defined(OS_CHROMEOS)
 // Enables or disables the ability to add a Samba Share to the Files app
 const base::Feature kNativeSmb{"NativeSmb", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index f22cae0..2dd29b64 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -283,6 +283,8 @@
 extern const base::Feature kSitePerProcessOnlyForHighMemoryClients;
 extern const char kSitePerProcessOnlyForHighMemoryClientsParamName[];
 
+extern const base::Feature kSSLCommittedInterstitials;
+
 #if defined(OS_CHROMEOS)
 extern const base::Feature kNativeSmb;
 #endif
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 594cee4..dfeefb9 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -122,10 +122,6 @@
 // service or register proxy for autostart.
 const char kCloudPrintSetupProxy[]          = "cloud-print-setup-proxy";
 
-// Enables committed error pages instead of transient navigation entries for
-// interstitial error pages (e.g. certificate errors).
-const char kCommittedInterstitials[] = "committed-interstitials";
-
 // Comma-separated list of BrowserThreads that cause browser process to crash if
 // the given browser thread is not responsive. UI/IO are the BrowserThreads that
 // are supported.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 932fdc5..e99c8fa 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -54,7 +54,6 @@
 extern const char kCloudPrintPrintTicket[];
 extern const char kCloudPrintServiceProcess[];
 extern const char kCloudPrintSetupProxy[];
-extern const char kCommittedInterstitials[];
 extern const char kCrashOnHangThreads[];
 extern const char kCreateBrowserOnStartupForTests[];
 extern const char kCustomDevtoolsFrontend[];
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1cec71e..a916ae31 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -28002,6 +28002,7 @@
   <int value="-1334327410" label="ash-enable-touch-view-testing"/>
   <int value="-1332267458" label="RemoveNavigationHistory:enabled"/>
   <int value="-1327676774" label="disable-accelerated-mjpeg-decode"/>
+  <int value="-1326463296" label="SSLCommittedInterstitials:disabled"/>
   <int value="-1325887476" label="NewPrintPreview:enabled"/>
   <int value="-1322882747" label="disable-datasaver-prompt"/>
   <int value="-1319688939" label="ignore-gpu-blacklist"/>
@@ -29394,6 +29395,7 @@
   <int value="1571998166" label="DetectingHeavyPages:disabled"/>
   <int value="1579461102" label="MemoryCoordinator:disabled"/>
   <int value="1586022426" label="AutofillCreditCardAssist:enabled"/>
+  <int value="1587521886" label="SSLCommittedInterstitials:enabled"/>
   <int value="1589341623" label="disable-easy-unlock"/>
   <int value="1590278995"
       label="AutofillSendExperimentIdsInPaymentsRPCs:enabled"/>