Implement the Windows desktop search redirection feature.

With this CL, Windows desktop searches are redirected to the default
search engine when the DesktopSearchRedirection feature is enabled.
The first time that a desktop search is redirected, an infobar is
shown to inform the user of the redirection.

BUG=539963

Review URL: https://codereview.chromium.org/1598553003

Cr-Commit-Position: refs/heads/master@{#373049}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2bde5cb..e5a7d31 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6391,11 +6391,11 @@
         Enables synchronizing WiFi network settings across devices. When enabled, the WiFi credential datatype is registered with Chrome Sync, and WiFi credentials are synchronized subject to user preferences. (See also, chrome://settings/syncSetup.)
       </message>
       <if expr="is_win">
-        <message name="IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_DESCRIPTION" desc="Description for the flag to enable a preference that allows redirection of Windows desktop searches to the default search engine.">
-          Enables a preference that allows redirection of Windows desktop searches to the default search engine.
+        <message name="IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_DESCRIPTION" desc="Description for the flag to enable redirection of Windows desktop searches to the default search engine.">
+          Enables redirection of Windows desktop searches to the default search engine.
         </message>
-        <message name="IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_NAME" desc="Title for the flag to enable a preference that allows redirection of Windows desktop searches to the default search engine.">
-          Windows desktop search redirection preference
+        <message name="IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_NAME" desc="Title for the flag to enable redirection of Windows desktop searches to the default search engine.">
+          Windows desktop search redirection
         </message>
       </if>
       <message name="IDS_FLAGS_SYNC_SANDBOX_NAME" desc="Name for the flag that causes Chrome to use the sandbox (testing) server for Sync.">
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 84d3ac39..d05d6dc 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -81,7 +81,7 @@
 #endif
 
 #if defined(OS_WIN)
-#include "components/search_engines/desktop_search_win.h"
+#include "components/search_engines/desktop_search_utils.h"
 #endif  // defined(OS_WIN)
 
 #if defined(ENABLE_APP_LIST)
@@ -2058,7 +2058,7 @@
      IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_NAME,
      IDS_FLAGS_WINDOWS_DESKTOP_SEARCH_REDIRECTION_DESCRIPTION,
      kOsWin,
-     FEATURE_VALUE_TYPE(kWindowsDesktopSearchRedirectionFeature)},
+     FEATURE_VALUE_TYPE(kDesktopSearchRedirectionFeature)},
 #endif  // defined(OS_WIN)
     {"force-ui-direction",
      IDS_FLAGS_FORCE_UI_DIRECTION_NAME,
diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc
index c644cd8d..361ae76 100644
--- a/chrome/browser/search_engines/template_url_service_factory.cc
+++ b/chrome/browser/search_engines/template_url_service_factory.cc
@@ -20,13 +20,10 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/default_search_manager.h"
+#include "components/search_engines/desktop_search_utils.h"
 #include "components/search_engines/search_engines_pref_names.h"
 #include "components/search_engines/template_url_service.h"
 
-#if defined(OS_WIN)
-#include "components/search_engines/desktop_search_win.h"
-#endif  // defined(OS_WIN)
-
 #if defined(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
 #endif
@@ -84,9 +81,7 @@
     user_prefs::PrefRegistrySyncable* registry) {
   DefaultSearchManager::RegisterProfilePrefs(registry);
   TemplateURLService::RegisterProfilePrefs(registry);
-#if defined(OS_WIN)
-  RegisterWindowsDesktopSearchRedirectionPref(registry);
-#endif
+  RegisterDesktopSearchRedirectionPref(registry);
 }
 
 content::BrowserContext* TemplateURLServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index ace525e..a911bd5 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -98,7 +98,7 @@
 
 #if defined(OS_WIN)
 #include "chrome/browser/metrics/jumplist_metrics_win.h"
-#include "components/search_engines/desktop_search_win.h"
+#include "components/search_engines/desktop_search_utils.h"
 #endif
 
 #if defined(ENABLE_PRINT_PREVIEW)
@@ -307,8 +307,8 @@
 
 StartupBrowserCreator::StartupBrowserCreator()
     : is_default_browser_dialog_suppressed_(false),
-      show_main_browser_window_(true) {
-}
+      show_main_browser_window_(true),
+      show_desktop_search_redirection_infobar_(false) {}
 
 StartupBrowserCreator::~StartupBrowserCreator() {}
 
@@ -372,7 +372,8 @@
   if (!silent_launch) {
     StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
     const std::vector<GURL> urls_to_launch =
-        GetURLsFromCommandLine(command_line, cur_dir, profile);
+        GetURLsFromCommandLine(command_line, cur_dir, profile,
+                               &show_desktop_search_redirection_infobar_);
     chrome::HostDesktopType host_desktop_type =
         chrome::HOST_DESKTOP_TYPE_NATIVE;
 
@@ -531,7 +532,11 @@
 std::vector<GURL> StartupBrowserCreator::GetURLsFromCommandLine(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
-    Profile* profile) {
+    Profile* profile,
+    bool* show_desktop_search_redirection_infobar) {
+  DCHECK(profile);
+  DCHECK(show_desktop_search_redirection_infobar);
+
   std::vector<GURL> urls;
 
   const base::CommandLine::StringVector& params = command_line.GetArgs();
@@ -558,23 +563,14 @@
     GURL url = GURL(param.MaybeAsASCII());
 
 #if defined(OS_WIN)
-    TemplateURLService* template_url_service =
-        TemplateURLServiceFactory::GetForProfile(profile);
-    DCHECK(template_url_service);
-    base::string16 search_terms;
-    if (DetectWindowsDesktopSearch(
-            url, template_url_service->search_terms_data(), &search_terms)) {
-      base::RecordAction(base::UserMetricsAction("DesktopSearch"));
-
-      if (ShouldRedirectWindowsDesktopSearchToDefaultSearchEngine(
-            profile->GetPrefs())) {
-        const GURL search_url(GetDefaultSearchURLForSearchTerms(
-            template_url_service, search_terms));
-        if (search_url.is_valid()) {
-          urls.push_back(search_url);
-          continue;
-        }
-      }
+    // Replace desktop search URL by a default search engine URL if needed.
+    // Ignore cases where there are multiple command line arguments, because
+    // desktop search never passes multiple URLs to the browser.
+    if (params.size() == 1) {
+      *show_desktop_search_redirection_infobar =
+          ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded(
+              profile->GetPrefs(),
+              TemplateURLServiceFactory::GetForProfile(profile), &url);
     }
 #endif  // defined(OS_WIN)
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator.h b/chrome/browser/ui/startup/startup_browser_creator.h
index 7f0f4e3c..b426ae4 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.h
+++ b/chrome/browser/ui/startup/startup_browser_creator.h
@@ -99,6 +99,10 @@
     return show_main_browser_window_;
   }
 
+  bool show_desktop_search_redirection_infobar() const {
+    return show_desktop_search_redirection_infobar_;
+  }
+
   // For faking that no profiles have been launched yet.
   static void ClearLaunchedProfilesForTesting();
 
@@ -133,8 +137,6 @@
                            ReadingWasRestartedAfterRestart);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, UpdateWithTwoProfiles);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, LastUsedProfileActivated);
-  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorWinTest,
-                           GetURLsFromCommandLineWithDesktopSearchURL);
 
   bool ProcessCmdLineImpl(const base::CommandLine& command_line,
                           const base::FilePath& cur_dir,
@@ -142,12 +144,16 @@
                           Profile* last_used_profile,
                           const Profiles& last_opened_profiles);
 
-  // Returns the list of URLs to open from the command line. The returned
-  // vector is empty if the user didn't specify any URLs on the command line.
+  // Returns the list of URLs to open from the command line. The returned vector
+  // is empty if the user didn't specify any URLs on the command line.
+  // |show_search_redirection_infobar| is set to true if an infobar should be
+  // shown to inform the user that a desktop search has been redirected to the
+  // default search engine.
   static std::vector<GURL> GetURLsFromCommandLine(
       const base::CommandLine& command_line,
       const base::FilePath& cur_dir,
-      Profile* profile);
+      Profile* profile,
+      bool* show_desktop_search_redirection_infobar);
 
   // This function performs command-line handling and is invoked only after
   // start up (for example when we get a start request for another process).
@@ -182,6 +188,10 @@
   // created. Default is true.
   bool show_main_browser_window_;
 
+  // Whether an infobar should be shown to inform the user that a desktop search
+  // has been redirected to the default search engine.
+  bool show_desktop_search_redirection_infobar_;
+
   // True if we have already read and reset the preference kWasRestarted. (A
   // member variable instead of a static variable inside WasRestarted because
   // of testing.)
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 6312873..89b94e7 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -109,6 +109,10 @@
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
 #include "chrome/browser/apps/app_launch_for_metro_restart_win.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "components/search_engines/desktop_search_redirection_infobar_delegate.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_service.h"
 #endif
 
 #if defined(ENABLE_RLZ)
@@ -831,6 +835,21 @@
       }
     }
 #endif
+
+#if defined(OS_WIN)
+    if (browser_creator_ &&
+        browser_creator_->show_desktop_search_redirection_infobar()) {
+      DesktopSearchRedirectionInfobarDelegate::Show(
+          InfoBarService::FromWebContents(
+              browser->tab_strip_model()->GetActiveWebContents()),
+          TemplateURLServiceFactory::GetForProfile(profile_)
+              ->GetDefaultSearchProvider()
+              ->AdjustedShortNameForLocaleDirection(),
+          base::Bind(&chrome::ShowSettingsSubPage, base::Unretained(browser),
+                     chrome::kSearchEnginesSubPage),
+          profile_->GetPrefs());
+    }
+#endif  // defined(OS_WIN)
   }
 }
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_win_unittest.cc b/chrome/browser/ui/startup/startup_browser_creator_win_unittest.cc
deleted file mode 100644
index 624b878..0000000
--- a/chrome/browser/ui/startup/startup_browser_creator_win_unittest.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2015 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/ui/startup/startup_browser_creator.h"
-
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/search_engines/template_url_service_factory_test_util.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/prefs/pref_service.h"
-#include "components/search_engines/desktop_search_win.h"
-#include "components/search_engines/util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-class StartupBrowserCreatorWinTest : public testing::Test {
- public:
-  StartupBrowserCreatorWinTest() {}
-
- protected:
-  void SetWindowsDesktopSearchFeatureEnabled(bool enabled) {
-    base::FeatureList::ClearInstanceForTesting();
-    scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    if (enabled) {
-      feature_list->InitializeFromCommandLine(
-          kWindowsDesktopSearchRedirectionFeature.name, std::string());
-    }
-    base::FeatureList::SetInstance(std::move(feature_list));
-  }
-
- private:
-  content::TestBrowserThreadBundle thread_bundle_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorWinTest);
-};
-
-TEST_F(StartupBrowserCreatorWinTest,
-       GetURLsFromCommandLineWithDesktopSearchURL) {
-  const char kDesktopSearchURL[] =
-      "https://www.bing.com/search?q=keyword&form=WNSGPH";
-
-  TestingProfile profile;
-  TemplateURLServiceFactoryTestUtil template_url_service_factory_test_util(
-      &profile);
-
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendArg(kDesktopSearchURL);
-
-  // Expected vectors of URLs.
-  const std::vector<GURL> desktop_search_url_vector({GURL(kDesktopSearchURL)});
-  const std::vector<GURL> default_search_url_vector(
-      {GetDefaultSearchURLForSearchTerms(
-          TemplateURLServiceFactory::GetForProfile(&profile), L"keyword")});
-
-  // Preference unset, feature enabled.
-  SetWindowsDesktopSearchFeatureEnabled(true);
-  EXPECT_EQ(desktop_search_url_vector,
-            StartupBrowserCreator::GetURLsFromCommandLine(
-                command_line, base::FilePath(), &profile));
-
-  // Preference set to disabled, feature enabled.
-  profile.GetPrefs()->SetBoolean(prefs::kWindowsDesktopSearchRedirectionPref,
-                                 false);
-  SetWindowsDesktopSearchFeatureEnabled(true);
-  EXPECT_EQ(desktop_search_url_vector,
-            StartupBrowserCreator::GetURLsFromCommandLine(
-                command_line, base::FilePath(), &profile));
-
-  // Preference set to enabled, feature enabled.
-  profile.GetPrefs()->SetBoolean(prefs::kWindowsDesktopSearchRedirectionPref,
-                                 true);
-  SetWindowsDesktopSearchFeatureEnabled(true);
-  EXPECT_EQ(default_search_url_vector,
-            StartupBrowserCreator::GetURLsFromCommandLine(
-                command_line, base::FilePath(), &profile));
-
-  // Preference set to enabled, feature disabled.
-  profile.GetPrefs()->SetBoolean(prefs::kWindowsDesktopSearchRedirectionPref,
-                                 true);
-  SetWindowsDesktopSearchFeatureEnabled(false);
-  EXPECT_EQ(desktop_search_url_vector,
-            StartupBrowserCreator::GetURLsFromCommandLine(
-                command_line, base::FilePath(), &profile));
-}
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 6ccc60e..4ed90b59 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -268,7 +268,6 @@
       'browser/ui/passwords/password_bubble_experiment_unittest.cc',
       'browser/ui/passwords/password_manager_presenter_unittest.cc',
       'browser/ui/search_engines/keyword_editor_controller_unittest.cc',
-      'browser/ui/startup/startup_browser_creator_win_unittest.cc',
       'browser/ui/sync/profile_signin_confirmation_helper_unittest.cc',
       'browser/ui/sync/sync_promo_ui_unittest.cc',
       'browser/ui/tests/ui_gfx_image_unittest.cc',
diff --git a/components/components_strings.grd b/components/components_strings.grd
index d00786b..1ad4c7a 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -198,6 +198,7 @@
       <part file="password_manager_strings.grdp" />
       <part file="pdf_strings.grdp" />
       <part file="policy_strings.grdp" />
+      <part file="search_engines_strings.grdp" />
       <part file="security_interstitials_strings.grdp" />
       <part file="ssl_errors_strings.grdp" />
       <part file="sync_ui_strings.grdp" />
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index b36a03e..e58595b 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -661,7 +661,7 @@
     'search_engines_unittest_sources': [
       'search_engines/default_search_manager_unittest.cc',
       'search_engines/default_search_pref_migration_unittest.cc',
-      'search_engines/desktop_search_win_unittest.cc',
+      'search_engines/desktop_search_utils_unittest.cc',
       'search_engines/keyword_table_unittest.cc',
       'search_engines/search_engine_data_type_controller_unittest.cc',
       'search_engines/search_host_to_urls_map_unittest.cc',
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index a33cf618..326b316 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -129,6 +129,7 @@
     UPGRADE_INFOBAR_DELEGATE = 59,
     CHROME_WINDOW_ERROR = 60,
     CONFIRM_DANGEROUS_DOWNLOAD = 61,
+    DESKTOP_SEARCH_REDIRECTION_INFOBAR_DELEGATE = 62,
   };
 
   // Describes navigation events, used to decide whether infobars should be
diff --git a/components/search_engines.gypi b/components/search_engines.gypi
index 1205392..00574bd 100644
--- a/components/search_engines.gypi
+++ b/components/search_engines.gypi
@@ -19,11 +19,13 @@
         '../url/url.gyp:url_lib',
         'component_metrics_proto',
         'components_strings.gyp:components_strings',
+        'components.gyp:infobars_core',
         'google_core_browser',
         'history_core_browser',
         'keyed_service_core',
         'policy',
         'pref_registry',
+        'prefs/prefs.gyp:prefs',
         'rappor',
         'search_engines/prepopulated_engines.gyp:prepopulated_engines',
         'sync_driver',
@@ -44,8 +46,10 @@
         'search_engines/default_search_policy_handler.h',
         'search_engines/default_search_pref_migration.cc',
         'search_engines/default_search_pref_migration.h',
-        'search_engines/desktop_search_win.cc',
-        'search_engines/desktop_search_win.h',
+        'search_engines/desktop_search_redirection_infobar_delegate.cc',
+        'search_engines/desktop_search_redirection_infobar_delegate.h',
+        'search_engines/desktop_search_utils.cc',
+        'search_engines/desktop_search_utils.h',
         'search_engines/keyword_table.cc',
         'search_engines/keyword_table.h',
         'search_engines/keyword_web_data_service.cc',
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn
index 08b81789..09343ed 100644
--- a/components/search_engines/BUILD.gn
+++ b/components/search_engines/BUILD.gn
@@ -11,8 +11,10 @@
     "default_search_manager.h",
     "default_search_pref_migration.cc",
     "default_search_pref_migration.h",
-    "desktop_search_win.cc",
-    "desktop_search_win.h",
+    "desktop_search_redirection_infobar_delegate.cc",
+    "desktop_search_redirection_infobar_delegate.h",
+    "desktop_search_utils.cc",
+    "desktop_search_utils.h",
     "keyword_table.cc",
     "keyword_table.h",
     "keyword_web_data_service.cc",
@@ -65,6 +67,7 @@
     # omnibox/browser target, but should ideally be fixed, then this
     # dependency added:
     #"//components/omnibox/browser",
+    "//components/infobars/core",
     "//components/pref_registry",
     "//components/prefs",
     "//components/rappor",
@@ -116,7 +119,7 @@
   sources = [
     "default_search_manager_unittest.cc",
     "default_search_pref_migration_unittest.cc",
-    "desktop_search_win_unittest.cc",
+    "desktop_search_utils_unittest.cc",
     "keyword_table_unittest.cc",
     "search_engine_data_type_controller_unittest.cc",
     "search_host_to_urls_map_unittest.cc",
@@ -131,7 +134,9 @@
     "//base",
     "//components/google/core/browser",
     "//components/pref_registry:test_support",
+    "//components/prefs",
     "//components/sync_driver:test_support",
+    "//components/syncable_prefs:test_support",
     "//components/webdata/common",
     "//sql",
     "//sync:test_support_sync_api",
diff --git a/components/search_engines/DEPS b/components/search_engines/DEPS
index 3fe9684..6ed289a 100644
--- a/components/search_engines/DEPS
+++ b/components/search_engines/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/google/core",
   "+components/history/core",
+  "+components/infobars/core",
   "+components/keyed_service/core",
   "+components/metrics/proto",
   # TODO(mpearson): for experiment; remove after crbug.com/488901 is launched.
@@ -10,6 +11,7 @@
   "+components/prefs",
   "+components/rappor",
   "+components/sync_driver",
+  "+components/syncable_prefs/testing_pref_service_syncable.h",
   "+components/url_formatter",
   "+components/webdata",
   "+google_apis",
diff --git a/components/search_engines/desktop_search_redirection_infobar_delegate.cc b/components/search_engines/desktop_search_redirection_infobar_delegate.cc
new file mode 100644
index 0000000..736cce5
--- /dev/null
+++ b/components/search_engines/desktop_search_redirection_infobar_delegate.cc
@@ -0,0 +1,115 @@
+// Copyright 2016 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 "components/search_engines/desktop_search_redirection_infobar_delegate.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/prefs/pref_service.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_delegate.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "components/search_engines/desktop_search_utils.h"
+#include "grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/window_open_disposition.h"
+
+namespace {
+
+// Values for the Search.DesktopSearch.RedirectionInfobarCloseAction histogram.
+enum DesktopSearchRedirectionInfobarCloseAction {
+  DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_MANAGE_SEARCH_SETTINGS = 0,
+  DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_DISMISS = 1,
+  DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_IGNORE = 2,
+  DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_MAX
+};
+
+void RecordDesktopSearchInfobarCloseActionHistogram(
+    DesktopSearchRedirectionInfobarCloseAction action) {
+  DCHECK_LT(action, DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_MAX);
+  UMA_HISTOGRAM_ENUMERATION(
+      "Search.DesktopSearch.RedirectionInfobarCloseAction", action,
+      DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_MAX);
+}
+
+}  // namespace
+
+void DesktopSearchRedirectionInfobarDelegate::Show(
+    infobars::InfoBarManager* infobar_manager,
+    const base::string16& default_search_engine_name,
+    const base::Closure& manage_search_settings_callback,
+    PrefService* pref_service) {
+  DCHECK(infobar_manager);
+  infobar_manager->AddInfoBar(
+      infobar_manager->CreateConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
+          new DesktopSearchRedirectionInfobarDelegate(
+              default_search_engine_name, manage_search_settings_callback))));
+  pref_service->SetBoolean(prefs::kDesktopSearchRedirectionInfobarShownPref,
+                           true);
+  base::RecordAction(
+      base::UserMetricsAction("DesktopSearchRedirectionInfoBar_Shown"));
+}
+
+DesktopSearchRedirectionInfobarDelegate::
+    DesktopSearchRedirectionInfobarDelegate(
+        const base::string16& default_search_engine_name,
+        const base::Closure& manage_search_settings_callback)
+    : default_search_engine_name_(default_search_engine_name),
+      manage_search_settings_callback_(manage_search_settings_callback),
+      closed_by_user_(false) {}
+
+DesktopSearchRedirectionInfobarDelegate::
+    ~DesktopSearchRedirectionInfobarDelegate() {
+  if (!closed_by_user_) {
+    base::RecordAction(
+        base::UserMetricsAction("DesktopSearchRedirectionInfoBar_Ignore"));
+    RecordDesktopSearchInfobarCloseActionHistogram(
+        DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_IGNORE);
+  }
+}
+
+infobars::InfoBarDelegate::InfoBarIdentifier
+DesktopSearchRedirectionInfobarDelegate::GetIdentifier() const {
+  return DESKTOP_SEARCH_REDIRECTION_INFOBAR_DELEGATE;
+}
+
+void DesktopSearchRedirectionInfobarDelegate::InfoBarDismissed() {
+  base::RecordAction(
+      base::UserMetricsAction("DesktopSearchRedirectionInfoBar_Dismiss"));
+  RecordDesktopSearchInfobarCloseActionHistogram(
+      DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_DISMISS);
+  closed_by_user_ = true;
+}
+
+base::string16 DesktopSearchRedirectionInfobarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(
+      IDS_DESKTOP_SEARCH_REDIRECTION_INFOBAR_MESSAGE,
+      default_search_engine_name_);
+}
+
+int DesktopSearchRedirectionInfobarDelegate::GetButtons() const {
+  return BUTTON_OK;
+}
+
+base::string16 DesktopSearchRedirectionInfobarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16(
+      IDS_DESKTOP_SEARCH_REDIRECTION_INFOBAR_BUTTON);
+}
+
+bool DesktopSearchRedirectionInfobarDelegate::Accept() {
+  base::RecordAction(base::UserMetricsAction(
+      "DesktopSearchRedirectionInfoBar_ManageSearchSettings"));
+  manage_search_settings_callback_.Run();
+
+  // Close the infobar.
+  RecordDesktopSearchInfobarCloseActionHistogram(
+      DESKTOP_SEARCH_REDIRECTION_INFOBAR_CLOSE_ACTION_MANAGE_SEARCH_SETTINGS);
+  closed_by_user_ = true;
+  return true;
+}
diff --git a/components/search_engines/desktop_search_redirection_infobar_delegate.h b/components/search_engines/desktop_search_redirection_infobar_delegate.h
new file mode 100644
index 0000000..bccb77a7
--- /dev/null
+++ b/components/search_engines/desktop_search_redirection_infobar_delegate.h
@@ -0,0 +1,56 @@
+// Copyright 2016 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.
+
+#ifndef COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_INFOBAR_DELEGATE_H_
+#define COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_INFOBAR_DELEGATE_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+
+class PrefService;
+
+namespace infobars {
+class InfoBarManager;
+}  // namespace infobars
+
+// Informs the user that a desktop search has been redirected to the default
+// search engine.
+class DesktopSearchRedirectionInfobarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  // Creates a search redirection infobar and delegate and adds the infobar to
+  // |infobar_manager|.  Records in |pref_service| that such an infobar was
+  // shown. |default_search_engine_name| is the name of the default search
+  // engine. |manage_search_settings_callback| should open the search settings
+  // page.
+  static void Show(infobars::InfoBarManager* infobar_manager,
+                   const base::string16& default_search_engine_name,
+                   const base::Closure& manage_search_settings_callback,
+                   PrefService* pref_service);
+
+ private:
+  DesktopSearchRedirectionInfobarDelegate(
+      const base::string16& default_search_engine_name,
+      const base::Closure& manage_search_settings_callback);
+  ~DesktopSearchRedirectionInfobarDelegate() override;
+
+  // ConfirmInfoBarDelegate:
+  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  void InfoBarDismissed() override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
+  base::string16 GetButtonLabel(InfoBarButton button) const override;
+  bool Accept() override;
+
+  base::string16 default_search_engine_name_;
+  base::Closure manage_search_settings_callback_;
+
+  // True when the infobar has been closed explicitly by the user.
+  bool closed_by_user_;
+
+  DISALLOW_COPY_AND_ASSIGN(DesktopSearchRedirectionInfobarDelegate);
+};
+
+#endif  // COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_INFOBAR_DELEGATE_H_
diff --git a/components/search_engines/desktop_search_utils.cc b/components/search_engines/desktop_search_utils.cc
new file mode 100644
index 0000000..f3d106b7
--- /dev/null
+++ b/components/search_engines/desktop_search_utils.cc
@@ -0,0 +1,138 @@
+// Copyright 2016 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 "components/search_engines/desktop_search_utils.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_util.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/search_engines/prepopulated_engines.h"
+#include "components/search_engines/template_url_prepopulate_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_engines/util.h"
+#include "net/base/url_util.h"
+
+namespace {
+
+// Values for the Search.DesktopSearch.URLAction histogram.
+enum DesktopSearchURLAction {
+  DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_FEATURE_DISABLED = 0,
+  DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_DEFAULT_SEARCH_IS_BING = 1,
+  DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_INVALID_SEARCH_ENGINE = 2,
+  DESKTOP_SEARCH_URL_ACTION_REDIRECTION = 3,
+  DESKTOP_SEARCH_URL_ACTION_MAX
+};
+
+void RecordDesktopSearchURLAction(DesktopSearchURLAction action) {
+  DCHECK_LT(action, DESKTOP_SEARCH_URL_ACTION_MAX);
+  UMA_HISTOGRAM_ENUMERATION("Search.DesktopSearch.URLAction", action,
+                            DESKTOP_SEARCH_URL_ACTION_MAX);
+}
+
+// Detects whether a |url| comes from a desktop search. If so, puts the search
+// terms in |search_terms| and returns true.
+bool DetectDesktopSearch(const GURL& url,
+                         const SearchTermsData& search_terms_data,
+                         base::string16* search_terms) {
+  DCHECK(search_terms);
+  search_terms->clear();
+
+  scoped_ptr<TemplateURLData> template_url_data =
+      TemplateURLPrepopulateData::MakeTemplateURLDataFromPrepopulatedEngine(
+          TemplateURLPrepopulateData::bing);
+  TemplateURL template_url(*template_url_data);
+  if (!template_url.ExtractSearchTermsFromURL(url, search_terms_data,
+                                              search_terms))
+    return false;
+
+  // Query parameter that tells the source of a Bing search URL, and values
+  // associated with desktop search.
+  const char kBingSourceQueryKey[] = "form";
+  const char kBingSourceDesktopText[] = "WNSGPH";
+  const char kBingSourceDesktopVoice[] = "WNSBOX";
+  for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
+    // Use a case-insensitive comparison because the key is sometimes in capital
+    // letters.
+    if (base::EqualsCaseInsensitiveASCII(it.GetKey(), kBingSourceQueryKey)) {
+      const std::string source = it.GetValue();
+      if (source == kBingSourceDesktopText || source == kBingSourceDesktopVoice)
+        return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace
+
+namespace prefs {
+const char kDesktopSearchRedirectionInfobarShownPref[] =
+    "desktop_search_redirection_infobar_shown";
+}  // namespace prefs
+
+const base::Feature kDesktopSearchRedirectionFeature{
+    "DesktopSearchRedirection", base::FEATURE_DISABLED_BY_DEFAULT};
+
+void RegisterDesktopSearchRedirectionPref(
+    user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterBooleanPref(
+      prefs::kDesktopSearchRedirectionInfobarShownPref, false);
+}
+
+bool ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded(
+    const PrefService* pref_service,
+    TemplateURLService* template_url_service,
+    GURL* url) {
+  DCHECK(pref_service);
+  DCHECK(template_url_service);
+  DCHECK(url);
+
+  // Check if |url| is a desktop search.
+  base::string16 search_terms;
+  if (!DetectDesktopSearch(*url, template_url_service->search_terms_data(),
+                           &search_terms))
+    return false;
+
+  // Record that the user searched from the desktop.
+  base::RecordAction(base::UserMetricsAction("DesktopSearch"));
+
+  // Check if the redirection feature is enabled.
+  if (!base::FeatureList::IsEnabled(kDesktopSearchRedirectionFeature)) {
+    RecordDesktopSearchURLAction(
+        DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_FEATURE_DISABLED);
+    return false;
+  }
+
+  // Check if the default search engine is Bing.
+  const TemplateURL* default_search_engine =
+      template_url_service->GetDefaultSearchProvider();
+  if (default_search_engine &&
+      TemplateURLPrepopulateData::GetEngineType(
+          *default_search_engine, template_url_service->search_terms_data()) ==
+          SEARCH_ENGINE_BING) {
+    RecordDesktopSearchURLAction(
+        DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_DEFAULT_SEARCH_IS_BING);
+    return false;
+  }
+
+  // Replace |url| by a default search engine URL.
+  GURL search_url(
+      GetDefaultSearchURLForSearchTerms(template_url_service, search_terms));
+  if (!search_url.is_valid()) {
+    RecordDesktopSearchURLAction(
+        DESKTOP_SEARCH_URL_ACTION_NO_REDIRECTION_INVALID_SEARCH_ENGINE);
+    return false;
+  }
+
+  RecordDesktopSearchURLAction(DESKTOP_SEARCH_URL_ACTION_REDIRECTION);
+
+  url->Swap(&search_url);
+  return !pref_service->GetBoolean(
+      prefs::kDesktopSearchRedirectionInfobarShownPref);
+}
diff --git a/components/search_engines/desktop_search_utils.h b/components/search_engines/desktop_search_utils.h
new file mode 100644
index 0000000..773ff7f
--- /dev/null
+++ b/components/search_engines/desktop_search_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2016 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.
+
+#ifndef COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_UTILS_H_
+#define COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_UTILS_H_
+
+#include "base/feature_list.h"
+#include "base/strings/string16.h"
+#include "url/gurl.h"
+
+class PrefService;
+class TemplateURLService;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace prefs {
+// Name of the preference keeping track of whether the desktop search
+// redirection infobar has been shown.
+extern const char kDesktopSearchRedirectionInfobarShownPref[];
+}
+
+// Desktop search redirection feature. This is exposed in the header file so
+// that it can be referenced from about_flags.cc.
+extern const base::Feature kDesktopSearchRedirectionFeature;
+
+// Registers the preference keeping track of whether the desktop search
+// redirection infobar has been shown.
+void RegisterDesktopSearchRedirectionPref(
+    user_prefs::PrefRegistrySyncable* registry);
+
+// Replaces |url| by a default search engine URL if:
+// - |url| is a desktop search URL.
+// - The desktop search redirection feature is enabled.
+// - The default search engine is not Bing.
+// Returns true if an infobar should be shown to tell the user about the
+// redirection.
+bool ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded(
+    const PrefService* pref_service,
+    TemplateURLService* template_url_service,
+    GURL* url);
+
+#endif  // COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_UTILS_H_
diff --git a/components/search_engines/desktop_search_utils_unittest.cc b/components/search_engines/desktop_search_utils_unittest.cc
new file mode 100644
index 0000000..b59f930c
--- /dev/null
+++ b/components/search_engines/desktop_search_utils_unittest.cc
@@ -0,0 +1,151 @@
+// Copyright 2016 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 "components/search_engines/desktop_search_utils.h"
+
+#include <string>
+
+#include "base/feature_list.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/prefs/pref_service.h"
+#include "components/search_engines/prepopulated_engines.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_prepopulate_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_engines/util.h"
+#include "components/syncable_prefs/testing_pref_service_syncable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+struct ReplaceDesktopSearchURLTestData {
+  // Value of the |url| argument of
+  // ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded on input.
+  const char* input_arg;
+
+  // Expected value of the |url| argument of
+  // ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded on output.
+  const char* expected_output_arg;
+};
+
+struct ShouldReplaceDesktopSearchURLTestData {
+  bool feature_enabled;
+  bool default_search_engine_is_bing;
+  const GURL* expected_output_arg;
+};
+
+}  // namespace
+
+class DesktopSearchUtilsTest : public testing::Test {
+ public:
+  DesktopSearchUtilsTest() : template_url_service_(nullptr, 0) {
+    RegisterDesktopSearchRedirectionPref(prefs_.registry());
+  }
+
+ protected:
+  void SetFeatureEnabled(bool enabled) {
+    base::FeatureList::ClearInstanceForTesting();
+    scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    if (enabled) {
+      feature_list->InitializeFromCommandLine(
+          kDesktopSearchRedirectionFeature.name, std::string());
+    }
+    base::FeatureList::SetInstance(std::move(feature_list));
+  }
+
+  void SetDefaultSearchEngine(
+      const TemplateURLPrepopulateData::PrepopulatedEngine
+          default_search_engine) {
+    scoped_ptr<TemplateURLData> template_url_data =
+        TemplateURLPrepopulateData::MakeTemplateURLDataFromPrepopulatedEngine(
+            default_search_engine);
+    TemplateURL template_url(*template_url_data);
+    template_url_service_.SetUserSelectedDefaultSearchProvider(&template_url);
+  }
+
+  TemplateURLService template_url_service_;
+  syncable_prefs::TestingPrefServiceSyncable prefs_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DesktopSearchUtilsTest);
+};
+
+// Checks that ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded correctly
+// replaces the URL it receives when the desktop search redirection feature is
+// enabled and the default search engine is not Bing.
+TEST_F(DesktopSearchUtilsTest, ReplaceDesktopSearchURL) {
+  const std::string default_search_url_keyword(
+      GetDefaultSearchURLForSearchTerms(&template_url_service_,
+                                        base::WideToUTF16(L"keyword"))
+          .spec());
+  const std::string default_search_url_special_chars(
+      GetDefaultSearchURLForSearchTerms(&template_url_service_,
+                                        base::WideToUTF16(L"\xE8 \xE9"))
+          .spec());
+
+  const ReplaceDesktopSearchURLTestData test_data[] = {
+      {"https://www.google.com/", "https://www.google.com/"},
+      {"https://www.bing.com/search/", "https://www.bing.com/search/"},
+      {"https://www.bing.com/search?q=keyword&form=QBLH",
+       "https://www.bing.com/search?q=keyword&form=QBLH"},
+      {"https://www.bing.com/search?q=keyword&form=WNSGPH",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?q=keyword&form=WNSBOX",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?q=keyword&FORM=WNSGPH",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?q=keyword&FORM=WNSBOX",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?form=WNSGPH&q=keyword",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?q=keyword&form=WNSGPH&other=stuff",
+       default_search_url_keyword.c_str()},
+      {"https://www.bing.com/search?q=%C3%A8+%C3%A9&form=WNSGPH",
+       default_search_url_special_chars.c_str()},
+  };
+
+  SetFeatureEnabled(true);
+
+  for (const auto& test : test_data) {
+    GURL url(test.input_arg);
+    ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded(
+        &prefs_, &template_url_service_, &url);
+    EXPECT_EQ(test.expected_output_arg, url.spec());
+  }
+}
+
+// Checks that ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded doesn't
+// change the URL it receives when the desktop search redirection feature is
+// disabled or when the default search engine is Bing.
+TEST_F(DesktopSearchUtilsTest, ShouldReplaceDesktopSearchURL) {
+  SetDefaultSearchEngine(TemplateURLPrepopulateData::google);
+  const GURL desktop_search_url(
+      "https://www.bing.com/search?q=keyword&form=WNSGPH");
+  const GURL default_search_url(GetDefaultSearchURLForSearchTerms(
+      &template_url_service_, base::WideToUTF16(L"keyword")));
+
+  const ShouldReplaceDesktopSearchURLTestData test_data[] = {
+      {false, false, &desktop_search_url},
+      {true, false, &default_search_url},
+      {false, true, &desktop_search_url},
+      {true, true, &desktop_search_url},
+  };
+
+  for (const auto& test : test_data) {
+    SetFeatureEnabled(test.feature_enabled);
+    SetDefaultSearchEngine(test.default_search_engine_is_bing
+                               ? TemplateURLPrepopulateData::bing
+                               : TemplateURLPrepopulateData::google);
+
+    // Check whether the desktop search URL is replaced.
+    GURL url(desktop_search_url);
+    ReplaceDesktopSearchURLWithDefaultSearchURLIfNeeded(
+        &prefs_, &template_url_service_, &url);
+    EXPECT_EQ(*test.expected_output_arg, url);
+  }
+}
diff --git a/components/search_engines/desktop_search_win.cc b/components/search_engines/desktop_search_win.cc
deleted file mode 100644
index d741c93..0000000
--- a/components/search_engines/desktop_search_win.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2015 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 "components/search_engines/desktop_search_win.h"
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
-#include "components/search_engines/prepopulated_engines.h"
-#include "components/search_engines/template_url.h"
-#include "components/search_engines/template_url_prepopulate_data.h"
-#include "net/base/url_util.h"
-
-namespace prefs {
-const char kWindowsDesktopSearchRedirectionPref[] =
-    "windows_desktop_search_redirection";
-}  // namespace prefs
-
-const base::Feature kWindowsDesktopSearchRedirectionFeature = {
-    "WindowsDesktopSearchRedirection", base::FEATURE_DISABLED_BY_DEFAULT
-};
-
-void RegisterWindowsDesktopSearchRedirectionPref(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterBooleanPref(prefs::kWindowsDesktopSearchRedirectionPref,
-                                false);
-}
-
-bool ShouldRedirectWindowsDesktopSearchToDefaultSearchEngine(
-    PrefService* pref_service) {
-  DCHECK(pref_service);
-  return base::FeatureList::IsEnabled(
-             kWindowsDesktopSearchRedirectionFeature) &&
-         pref_service->GetBoolean(prefs::kWindowsDesktopSearchRedirectionPref);
-}
-
-bool DetectWindowsDesktopSearch(const GURL& url,
-                                const SearchTermsData& search_terms_data,
-                                base::string16* search_terms) {
-  DCHECK(search_terms);
-
-  scoped_ptr<TemplateURLData> template_url_data =
-      TemplateURLPrepopulateData::MakeTemplateURLDataFromPrepopulatedEngine(
-          TemplateURLPrepopulateData::bing);
-  TemplateURL template_url(*template_url_data);
-
-  if (!template_url.ExtractSearchTermsFromURL(url, search_terms_data,
-                                              search_terms))
-    return false;
-
-  // Query parameter that tells the source of a Bing search URL, and values
-  // associated with Windows desktop search.
-  const char kBingSourceQueryKey[] = "form";
-  const char kBingSourceDesktopText[] = "WNSGPH";
-  const char kBingSourceDesktopVoice[] = "WNSBOX";
-
-  for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
-    // Use a case-insensitive comparison because the key is sometimes in capital
-    // letters.
-    if (base::EqualsCaseInsensitiveASCII(it.GetKey(), kBingSourceQueryKey)) {
-      const std::string source = it.GetValue();
-      if (source == kBingSourceDesktopText || source == kBingSourceDesktopVoice)
-        return true;
-    }
-  }
-
-  search_terms->clear();
-  return false;
-}
diff --git a/components/search_engines/desktop_search_win.h b/components/search_engines/desktop_search_win.h
deleted file mode 100644
index 162e95f2..0000000
--- a/components/search_engines/desktop_search_win.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_WIN_H_
-#define COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_WIN_H_
-
-#include "base/feature_list.h"
-#include "base/strings/string16.h"
-
-class GURL;
-class PrefService;
-class SearchTermsData;
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-namespace prefs {
-// Name of the Windows desktop search redirection preference.
-extern const char kWindowsDesktopSearchRedirectionPref[];
-}
-
-// Windows desktop search redirection feature. This is exposed in the header
-// file so that it can be referenced from about_flags.cc.
-extern const base::Feature kWindowsDesktopSearchRedirectionFeature;
-
-// Registers the Windows desktop search redirection preference into |registry|.
-void RegisterWindowsDesktopSearchRedirectionPref(
-    user_prefs::PrefRegistrySyncable* registry);
-
-// Indicates whether Windows desktop searches should be redirected to the
-// default search engine. This is only true when both the preference and the
-// feature are enabled. The preference value is read from |pref_service|.
-bool ShouldRedirectWindowsDesktopSearchToDefaultSearchEngine(
-    PrefService* pref_service);
-
-// Detects whether a URL comes from a Windows Desktop search. If so, puts the
-// search terms in |search_terms| and returns true.
-bool DetectWindowsDesktopSearch(const GURL& url,
-                                const SearchTermsData& search_terms_data,
-                                base::string16* search_terms);
-
-#endif  // COMPONENTS_SEARCH_ENGINES_DESKTOP_SEARCH_WIN_H_
diff --git a/components/search_engines/desktop_search_win_unittest.cc b/components/search_engines/desktop_search_win_unittest.cc
deleted file mode 100644
index 6556cd8..0000000
--- a/components/search_engines/desktop_search_win_unittest.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 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 "components/search_engines/desktop_search_win.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/search_engines/testing_search_terms_data.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace {
-struct DetectWindowsDesktopSearchTestData {
-  const char* url;
-  const wchar_t* expected_search_terms;
-};
-}  // namespace
-
-TEST(WindowsDesktopSearch, DetectWindowsDesktopSearch) {
-  const DetectWindowsDesktopSearchTestData test_data[] = {
-      {"https://www.google.com", L""},
-      {"https://www.bing.com/search", L""},
-      {"https://www.bing.com/search?q=keyword&form=QBLH", L""},
-      {"https://www.bing.com/search?q=keyword&form=WNSGPH", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&form=WNSBOX", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&FORM=WNSGPH", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&FORM=WNSBOX", L"keyword"},
-      {"https://www.bing.com/search?form=WNSGPH&q=keyword", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&form=WNSGPH&other=stuff",
-       L"keyword"},
-      {"https://www.bing.com/search?q=%C3%A8+%C3%A9&form=WNSGPH", L"\xE8 \xE9"},
-  };
-
-  for (size_t i = 0; i < arraysize(test_data); ++i) {
-    TestingSearchTermsData search_terms_data("https://www.google.com");
-    base::string16 search_terms;
-    bool is_desktop_search = DetectWindowsDesktopSearch(
-        GURL(test_data[i].url), search_terms_data, &search_terms);
-    const base::string16 expected_search_terms(
-        test_data[i].expected_search_terms);
-    EXPECT_EQ(!expected_search_terms.empty(), is_desktop_search);
-    EXPECT_EQ(expected_search_terms, search_terms);
-  }
-}
diff --git a/components/search_engines/detect_desktop_search_win_unittest.cc b/components/search_engines/detect_desktop_search_win_unittest.cc
deleted file mode 100644
index d1c6ecda..0000000
--- a/components/search_engines/detect_desktop_search_win_unittest.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 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 "components/search_engines/detect_desktop_search_win.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/search_engines/testing_search_terms_data.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace {
-struct DetectWindowsDesktopSearchTestData {
-  const char* url;
-  const wchar_t* expected_search_terms;
-};
-}  // namespace
-
-TEST(DetectWindowsDesktopSearch, DetectWindowsDesktopSearch) {
-  const DetectWindowsDesktopSearchTestData test_data[] = {
-      {"https://www.google.com", L""},
-      {"https://www.bing.com/search", L""},
-      {"https://www.bing.com/search?q=keyword&form=QBLH", L""},
-      {"https://www.bing.com/search?q=keyword&form=WNSGPH", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&form=WNSBOX", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&FORM=WNSGPH", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&FORM=WNSBOX", L"keyword"},
-      {"https://www.bing.com/search?form=WNSGPH&q=keyword", L"keyword"},
-      {"https://www.bing.com/search?q=keyword&form=WNSGPH&other=stuff",
-       L"keyword"},
-      {"https://www.bing.com/search?q=%C3%A8+%C3%A9&form=WNSGPH", L"\xE8 \xE9"},
-  };
-
-  for (size_t i = 0; i < arraysize(test_data); ++i) {
-    TestingSearchTermsData search_terms_data("https://www.google.com");
-    base::string16 search_terms;
-    bool is_desktop_search = DetectWindowsDesktopSearch(
-        GURL(test_data[i].url), search_terms_data, &search_terms);
-    const base::string16 expected_search_terms(
-        test_data[i].expected_search_terms);
-    EXPECT_EQ(!expected_search_terms.empty(), is_desktop_search);
-    EXPECT_EQ(expected_search_terms, search_terms);
-  }
-}
diff --git a/components/search_engines_strings.grdp b/components/search_engines_strings.grdp
new file mode 100644
index 0000000..9dbd127
--- /dev/null
+++ b/components/search_engines_strings.grdp
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <!-- Desktop search redirection strings. -->
+  <message name="IDS_DESKTOP_SEARCH_REDIRECTION_INFOBAR_MESSAGE" desc="Text shown in the infobar informing the user that a desktop search has been redirected to the default search engine.">
+    Desktop searches use your default search engine (<ph name="DEFAULT_SEARCH_ENGINE_NAME">$1<ex>Google</ex></ph>).
+  </message>
+  <message name="IDS_DESKTOP_SEARCH_REDIRECTION_INFOBAR_BUTTON" desc="Text of the button to go to the search engine settings page, in the infobar informing the user that a desktop search has been redirected to the default search engine.">
+    Manage search settings
+  </message>
+</grit-part>
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 253527f..d858488 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -2654,6 +2654,40 @@
   </description>
 </action>
 
+<action name="DesktopSearchRedirectionInfoBar_Dismiss">
+  <owner>[email protected]</owner>
+  <description>
+    Recorded when the user clicks on the dismiss button in the infobar
+    explaining that a desktop search has been redirected to the default search
+    engine.
+  </description>
+</action>
+
+<action name="DesktopSearchRedirectionInfoBar_Ignore">
+  <owner>[email protected]</owner>
+  <description>
+    Recorded when the infobar explaining that a desktop search has been
+    redirected to the default search engine is closed without user interaction.
+  </description>
+</action>
+
+<action name="DesktopSearchRedirectionInfoBar_ManageSearchSettings">
+  <owner>[email protected]</owner>
+  <description>
+    Recorded when the user clicks on the 'Manage search settings' button in the
+    infobar explaining that a desktop search has been redirected to the default
+    search engine.
+  </description>
+</action>
+
+<action name="DesktopSearchRedirectionInfoBar_Shown">
+  <owner>[email protected]</owner>
+  <description>
+    Recorded when the infobar explaining that a desktop search has been
+    redirected to the default search engine is shown.
+  </description>
+</action>
+
 <action name="Desktop_SwitchTask">
   <owner>[email protected]</owner>
   <owner>[email protected]</owner>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c859eda..7e2be3f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -44105,6 +44105,23 @@
   </summary>
 </histogram>
 
+<histogram name="Search.DesktopSearch.RedirectionInfobarCloseAction"
+    enum="DesktopSearchRedirectionInfobarCloseAction">
+  <owner>[email protected]</owner>
+  <summary>
+    The action performed by the user to close the infobar explaining that a
+    desktop search has been redirected to the default search engine.
+  </summary>
+</histogram>
+
+<histogram name="Search.DesktopSearch.URLAction" enum="DesktopSearchURLAction">
+  <owner>[email protected]</owner>
+  <summary>
+    The action performed when a desktop search URL is passed to the browser
+    through the command line.
+  </summary>
+</histogram>
+
 <histogram name="Search.MigratedPrefToDictionaryValue" enum="BooleanHit">
   <owner>[email protected]</owner>
   <summary>
@@ -60611,6 +60628,19 @@
   <int value="5" label="First window capture call failed."/>
 </enum>
 
+<enum name="DesktopSearchRedirectionInfobarCloseAction" type="int">
+  <int value="0" label="Clicked the 'Manage search settings' link"/>
+  <int value="1" label="Clicked the dismiss button"/>
+  <int value="2" label="InfoBar dismissed implicitly (no interaction)"/>
+</enum>
+
+<enum name="DesktopSearchURLAction" type="int">
+  <int value="0" label="No redirection - Feature disabled"/>
+  <int value="1" label="No redirection - Default search engine is Bing"/>
+  <int value="2" label="No redirection - Default search engine is invalid"/>
+  <int value="3" label="Redirection to the default search engine"/>
+</enum>
+
 <enum name="DeviceIdMismatch" type="int">
   <int value="0" label="BOTH_NONEMPTY"/>
   <int value="1" label="SYNC_EMPTY"/>
@@ -68435,6 +68465,7 @@
   <int value="59" label="UPGRADE_INFOBAR_DELEGATE"/>
   <int value="60" label="CHROME_WINDOW_ERROR"/>
   <int value="61" label="CONFIRM_DANGEROUS_DOWNLOAD"/>
+  <int value="62" label="WINDOWS_DESKTOP_SEARCH_INFOBAR_DELEGATE"/>
 </enum>
 
 <enum name="InfoBarResponse" type="int">