| Index: components/search_engines/desktop_search_utils.cc
 | 
| diff --git a/components/search_engines/desktop_search_utils.cc b/components/search_engines/desktop_search_utils.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..f3d106b79320db9599aa081cdafef97f5709ff37
 | 
| --- /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);
 | 
| +}
 | 
| 
 |