Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / autocomplete / history_url_provider.cc
index 037904d..407bc90 100644 (file)
@@ -15,9 +15,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "chrome/browser/autocomplete/autocomplete_match.h"
-#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
-#include "chrome/browser/autocomplete/autocomplete_result.h"
+#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/history/history_backend.h"
 #include "chrome/browser/history/history_database.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/history/in_memory_url_index_types.h"
 #include "chrome/browser/history/scored_history_match.h"
-#include "chrome/browser/omnibox/omnibox_field_trial.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/url_fixer_upper.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
+#include "components/bookmarks/browser/bookmark_utils.h"
+#include "components/metrics/proto/omnibox_input_type.pb.h"
+#include "components/omnibox/autocomplete_match.h"
+#include "components/omnibox/autocomplete_provider_listener.h"
+#include "components/omnibox/autocomplete_result.h"
+#include "components/omnibox/omnibox_field_trial.h"
+#include "components/omnibox/url_prefix.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/url_fixer/url_fixer.h"
+#include "content/public/browser/browser_thread.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
 
 namespace {
 
-// If |create_if_necessary| is true, ensures that |matches| contains an
-// entry for |info|, creating a new such entry if necessary (using
-// |input_location| and |match_in_scheme|).
-//
-// If |promote| is true, this also ensures the entry is the first element in
-// |matches|, moving or adding it to the front as appropriate.  When |promote|
-// is false, existing matches are left in place, and newly added matches are
-// placed at the back.
-//
-// It's OK to call this function with both |create_if_necessary| and
-// |promote| false, in which case we'll do nothing.
-//
-// Returns whether the match exists regardless if it was promoted/created.
-bool CreateOrPromoteMatch(const history::URLRow& info,
-                          size_t input_location,
-                          bool match_in_scheme,
-                          history::HistoryMatches* matches,
-                          bool create_if_necessary,
-                          bool promote) {
-  // |matches| may already have an entry for this.
-  for (history::HistoryMatches::iterator i(matches->begin());
-       i != matches->end(); ++i) {
-    if (i->url_info.url() == info.url()) {
-      // Rotate it to the front if the caller wishes.
-      if (promote)
-        std::rotate(matches->begin(), i, i + 1);
-      return true;
-    }
-  }
-
-  if (!create_if_necessary)
-    return false;
-
-  // No entry, so create one.
-  history::HistoryMatch match(info, input_location, match_in_scheme, true);
-  if (promote)
-    matches->push_front(match);
-  else
-    matches->push_back(match);
-
-  return true;
-}
-
-// Given the user's |input| and a |match| created from it, reduce the match's
-// URL to just a host.  If this host still matches the user input, return it.
-// Returns the empty string on failure.
-GURL ConvertToHostOnly(const history::HistoryMatch& match,
-                       const base::string16& input) {
-  // See if we should try to do host-only suggestions for this URL. Nonstandard
-  // schemes means there's no authority section, so suggesting the host name
-  // is useless. File URLs are standard, but host suggestion is not useful for
-  // them either.
-  const GURL& url = match.url_info.url();
-  if (!url.is_valid() || !url.IsStandard() || url.SchemeIsFile())
-    return GURL();
-
-  // Transform to a host-only match.  Bail if the host no longer matches the
-  // user input (e.g. because the user typed more than just a host).
-  GURL host = url.GetWithEmptyPath();
-  if ((host.spec().length() < (match.input_location + input.length())))
-    return GURL();  // User typing is longer than this host suggestion.
-
-  const base::string16 spec = base::UTF8ToUTF16(host.spec());
-  if (spec.compare(match.input_location, input.length(), input))
-    return GURL();  // User typing is no longer a prefix.
-
-  return host;
-}
-
 // Acts like the > operator for URLInfo classes.
 bool CompareHistoryMatch(const history::HistoryMatch& a,
                          const history::HistoryMatch& b) {
-  // A promoted match is better than non-promoted.
-  if (a.promoted != b.promoted)
-    return a.promoted;
-
   // A URL that has been typed at all is better than one that has never been
   // typed.  (Note "!"s on each side)
   if (!a.url_info.typed_count() != !b.url_info.typed_count())
@@ -179,20 +112,10 @@ void SortAndDedupMatches(history::HistoryMatches* matches) {
   }
 }
 
-// Extracts typed_count, visit_count, and last_visited time from the
-// URLRow and puts them in the additional info field of the |match|
-// for display in about:omnibox.
-void RecordAdditionalInfoFromUrlRow(const history::URLRow& info,
-                                    AutocompleteMatch* match) {
-  match->RecordAdditionalInfo("typed count", info.typed_count());
-  match->RecordAdditionalInfo("visit count", info.visit_count());
-  match->RecordAdditionalInfo("last visit", info.last_visit());
-}
-
 // Calculates a new relevance score applying half-life time decaying to |count|
-// using |time_since_last_visit| and |score_buckets|.
-// This function will never return a score higher than |undecayed_relevance|.
-// In other words, it can only demote the old score.
+// using |time_since_last_visit| and |score_buckets|.  This function will never
+// return a score higher than |undecayed_relevance|; in other words, it can only
+// demote the old score.
 double CalculateRelevanceUsingScoreBuckets(
     const HUPScoringParams::ScoreBuckets& score_buckets,
     const base::TimeDelta& time_since_last_visit,
@@ -220,6 +143,128 @@ double CalculateRelevanceUsingScoreBuckets(
       score_bucket->second : undecayed_relevance;
 }
 
+// Returns a new relevance score for the given |match| based on the
+// |old_relevance| score and |scoring_params|.  The new relevance score is
+// guaranteed to be less than or equal to |old_relevance|.  In other words, this
+// function can only demote a score, never boost it.  Returns |old_relevance| if
+// experimental scoring is disabled.
+int CalculateRelevanceScoreUsingScoringParams(
+    const history::HistoryMatch& match,
+    int old_relevance,
+    const HUPScoringParams& scoring_params) {
+  if (!scoring_params.experimental_scoring_enabled)
+    return old_relevance;
+
+  const base::TimeDelta time_since_last_visit =
+      base::Time::Now() - match.url_info.last_visit();
+
+  int relevance = CalculateRelevanceUsingScoreBuckets(
+      scoring_params.typed_count_buckets, time_since_last_visit, old_relevance,
+      match.url_info.typed_count());
+
+  // Additional demotion (on top of typed_count demotion) of URLs that were
+  // never typed.
+  if (match.url_info.typed_count() == 0) {
+    relevance = CalculateRelevanceUsingScoreBuckets(
+        scoring_params.visited_count_buckets, time_since_last_visit, relevance,
+        match.url_info.visit_count());
+  }
+
+  DCHECK_LE(relevance, old_relevance);
+  return relevance;
+}
+
+// Extracts typed_count, visit_count, and last_visited time from the URLRow and
+// puts them in the additional info field of the |match| for display in
+// about:omnibox.
+void RecordAdditionalInfoFromUrlRow(const history::URLRow& info,
+                                    AutocompleteMatch* match) {
+  match->RecordAdditionalInfo("typed count", info.typed_count());
+  match->RecordAdditionalInfo("visit count", info.visit_count());
+  match->RecordAdditionalInfo("last visit", info.last_visit());
+}
+
+// If |create_if_necessary| is true, ensures that |matches| contains an entry
+// for |info|, creating a new such entry if necessary (using |input_location|
+// and |match_in_scheme|).
+//
+// If |promote| is true, this also ensures the entry is the first element in
+// |matches|, moving or adding it to the front as appropriate.  When |promote|
+// is false, existing matches are left in place, and newly added matches are
+// placed at the back.
+//
+// It's OK to call this function with both |create_if_necessary| and |promote|
+// false, in which case we'll do nothing.
+//
+// Returns whether the match exists regardless if it was promoted/created.
+bool CreateOrPromoteMatch(const history::URLRow& info,
+                          size_t input_location,
+                          bool match_in_scheme,
+                          history::HistoryMatches* matches,
+                          bool create_if_necessary,
+                          bool promote) {
+  // |matches| may already have an entry for this.
+  for (history::HistoryMatches::iterator i(matches->begin());
+       i != matches->end(); ++i) {
+    if (i->url_info.url() == info.url()) {
+      // Rotate it to the front if the caller wishes.
+      if (promote)
+        std::rotate(matches->begin(), i, i + 1);
+      return true;
+    }
+  }
+
+  if (!create_if_necessary)
+    return false;
+
+  // No entry, so create one.
+  history::HistoryMatch match(info, input_location, match_in_scheme, true);
+  if (promote)
+    matches->push_front(match);
+  else
+    matches->push_back(match);
+
+  return true;
+}
+
+// Returns whether |match| is suitable for inline autocompletion.
+bool CanPromoteMatchForInlineAutocomplete(const history::HistoryMatch& match) {
+  // We can promote this match if it's been typed at least n times, where n == 1
+  // for "simple" (host-only) URLs and n == 2 for others.  We set a higher bar
+  // for these long URLs because it's less likely that users will want to visit
+  // them again.  Even though we don't increment the typed_count for pasted-in
+  // URLs, if the user manually edits the URL or types some long thing in by
+  // hand, we wouldn't want to immediately start autocompleting it.
+  return match.url_info.typed_count() &&
+      ((match.url_info.typed_count() > 1) || match.IsHostOnly());
+}
+
+// Given the user's |input| and a |match| created from it, reduce the match's
+// URL to just a host.  If this host still matches the user input, return it.
+// Returns the empty string on failure.
+GURL ConvertToHostOnly(const history::HistoryMatch& match,
+                       const base::string16& input) {
+  // See if we should try to do host-only suggestions for this URL. Nonstandard
+  // schemes means there's no authority section, so suggesting the host name
+  // is useless. File URLs are standard, but host suggestion is not useful for
+  // them either.
+  const GURL& url = match.url_info.url();
+  if (!url.is_valid() || !url.IsStandard() || url.SchemeIsFile())
+    return GURL();
+
+  // Transform to a host-only match.  Bail if the host no longer matches the
+  // user input (e.g. because the user typed more than just a host).
+  GURL host = url.GetWithEmptyPath();
+  if ((host.spec().length() < (match.input_location + input.length())))
+    return GURL();  // User typing is longer than this host suggestion.
+
+  const base::string16 spec = base::UTF8ToUTF16(host.spec());
+  if (spec.compare(match.input_location, input.length(), input))
+    return GURL();  // User typing is no longer a prefix.
+
+  return host;
+}
+
 }  // namespace
 
 // -----------------------------------------------------------------
@@ -237,21 +282,31 @@ class SearchTermsDataSnapshot : public SearchTermsData {
 
   virtual std::string GoogleBaseURLValue() const OVERRIDE;
   virtual std::string GetApplicationLocale() const OVERRIDE;
-  virtual base::string16 GetRlzParameterValue() const OVERRIDE;
+  virtual base::string16 GetRlzParameterValue(
+      bool from_app_list) const OVERRIDE;
   virtual std::string GetSearchClient() const OVERRIDE;
+  virtual bool EnableAnswersInSuggest() const OVERRIDE;
+  virtual bool IsShowingSearchTermsOnSearchResultsPages() const OVERRIDE;
+  virtual std::string InstantExtendedEnabledParam(
+      bool for_search) const OVERRIDE;
   virtual std::string ForceInstantResultsParam(
       bool for_prerender) const OVERRIDE;
-  virtual std::string InstantExtendedEnabledParam() const OVERRIDE;
   virtual std::string NTPIsThemedParam() const OVERRIDE;
+  virtual std::string GoogleImageSearchSource() const OVERRIDE;
 
  private:
   std::string google_base_url_value_;
   std::string application_locale_;
   base::string16 rlz_parameter_value_;
   std::string search_client_;
-  std::string force_instant_results_param_;
+  bool enable_answers_in_suggest_;
+  bool is_showing_search_terms_on_search_results_pages_;
   std::string instant_extended_enabled_param_;
+  std::string instant_extended_enabled_param_for_search_;
+  std::string force_instant_results_param_;
+  std::string force_instant_results_param_for_prerender_;
   std::string ntp_is_themed_param_;
+  std::string google_image_search_source_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchTermsDataSnapshot);
 };
@@ -260,13 +315,22 @@ SearchTermsDataSnapshot::SearchTermsDataSnapshot(
     const SearchTermsData& search_terms_data)
     : google_base_url_value_(search_terms_data.GoogleBaseURLValue()),
       application_locale_(search_terms_data.GetApplicationLocale()),
-      rlz_parameter_value_(search_terms_data.GetRlzParameterValue()),
+      rlz_parameter_value_(search_terms_data.GetRlzParameterValue(false)),
       search_client_(search_terms_data.GetSearchClient()),
+      enable_answers_in_suggest_(search_terms_data.EnableAnswersInSuggest()),
+      is_showing_search_terms_on_search_results_pages_(
+          search_terms_data.IsShowingSearchTermsOnSearchResultsPages()),
+      instant_extended_enabled_param_(
+          search_terms_data.InstantExtendedEnabledParam(false)),
+      instant_extended_enabled_param_for_search_(
+          search_terms_data.InstantExtendedEnabledParam(true)),
       force_instant_results_param_(
           search_terms_data.ForceInstantResultsParam(false)),
-      instant_extended_enabled_param_(
-          search_terms_data.InstantExtendedEnabledParam()),
-      ntp_is_themed_param_(search_terms_data.NTPIsThemedParam()) {}
+      force_instant_results_param_for_prerender_(
+          search_terms_data.ForceInstantResultsParam(true)),
+      ntp_is_themed_param_(search_terms_data.NTPIsThemedParam()),
+      google_image_search_source_(search_terms_data.GoogleImageSearchSource()) {
+}
 
 SearchTermsDataSnapshot::~SearchTermsDataSnapshot() {
 }
@@ -279,7 +343,8 @@ std::string SearchTermsDataSnapshot::GetApplicationLocale() const {
   return application_locale_;
 }
 
-base::string16 SearchTermsDataSnapshot::GetRlzParameterValue() const {
+base::string16 SearchTermsDataSnapshot::GetRlzParameterValue(
+    bool from_app_list) const {
   return rlz_parameter_value_;
 }
 
@@ -287,19 +352,34 @@ std::string SearchTermsDataSnapshot::GetSearchClient() const {
   return search_client_;
 }
 
-std::string SearchTermsDataSnapshot::ForceInstantResultsParam(
-    bool for_prerender) const {
-  return force_instant_results_param_;
+bool SearchTermsDataSnapshot::EnableAnswersInSuggest() const {
+  return enable_answers_in_suggest_;
 }
 
-std::string SearchTermsDataSnapshot::InstantExtendedEnabledParam() const {
-  return instant_extended_enabled_param_;
+bool SearchTermsDataSnapshot::IsShowingSearchTermsOnSearchResultsPages() const {
+  return is_showing_search_terms_on_search_results_pages_;
+}
+
+std::string SearchTermsDataSnapshot::InstantExtendedEnabledParam(
+    bool for_search) const {
+  return for_search ? instant_extended_enabled_param_ :
+      instant_extended_enabled_param_for_search_;
+}
+
+std::string SearchTermsDataSnapshot::ForceInstantResultsParam(
+    bool for_prerender) const {
+  return for_prerender ? force_instant_results_param_ :
+      force_instant_results_param_for_prerender_;
 }
 
 std::string SearchTermsDataSnapshot::NTPIsThemedParam() const {
   return ntp_is_themed_param_;
 }
 
+std::string SearchTermsDataSnapshot::GoogleImageSearchSource() const {
+  return google_image_search_source_;
+}
+
 // -----------------------------------------------------------------
 // HistoryURLProvider
 
@@ -351,7 +431,7 @@ HistoryURLProvider::VisitClassifier::VisitClassifier(
   // and because the history backend strips auth creds, we'll get a bogus exact
   // match below if the user has visited "site".
   if (!url.is_valid() ||
-      ((input.type() == AutocompleteInput::UNKNOWN) &&
+      ((input.type() == metrics::OmniboxInputType::UNKNOWN) &&
        input.parts().username.is_nonempty() &&
        !input.parts().password.is_nonempty() &&
        !input.parts().path.is_nonempty()))
@@ -373,6 +453,7 @@ HistoryURLProvider::VisitClassifier::VisitClassifier(
 HistoryURLProviderParams::HistoryURLProviderParams(
     const AutocompleteInput& input,
     bool trim_http,
+    const AutocompleteMatch& what_you_typed_match,
     const std::string& languages,
     TemplateURL* default_search_provider,
     const SearchTermsData& search_terms_data)
@@ -380,12 +461,13 @@ HistoryURLProviderParams::HistoryURLProviderParams(
       input(input),
       prevent_inline_autocomplete(input.prevent_inline_autocomplete()),
       trim_http(trim_http),
+      what_you_typed_match(what_you_typed_match),
       failed(false),
+      exact_suggestion_is_in_history(false),
+      promote_type(NEITHER),
       languages(languages),
-      dont_suggest_exact_input(false),
       default_search_provider(default_search_provider ?
-          new TemplateURL(default_search_provider->profile(),
-                          default_search_provider->data()) : NULL),
+          new TemplateURL(default_search_provider->data()) : NULL),
       search_terms_data(new SearchTermsDataSnapshot(search_terms_data)) {
 }
 
@@ -394,17 +476,9 @@ HistoryURLProviderParams::~HistoryURLProviderParams() {
 
 HistoryURLProvider::HistoryURLProvider(AutocompleteProviderListener* listener,
                                        Profile* profile)
-    : HistoryProvider(listener, profile,
-          AutocompleteProvider::TYPE_HISTORY_URL),
-      params_(NULL),
-      cull_redirects_(
-          !OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() ||
-          !OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup()),
-      create_shorter_match_(
-          !OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrial() ||
-          !OmniboxFieldTrial::
-              InHUPCreateShorterMatchFieldTrialExperimentGroup()),
-      search_url_database_(true) {
+    : HistoryProvider(profile, AutocompleteProvider::TYPE_HISTORY_URL),
+      listener_(listener),
+      params_(NULL) {
   // Initialize HUP scoring params based on the current experiment.
   OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params_);
 }
@@ -423,7 +497,92 @@ void HistoryURLProvider::Start(const AutocompleteInput& input,
   // Cancel any in-progress query.
   Stop(false);
 
-  RunAutocompletePasses(input, true);
+  matches_.clear();
+
+  if ((input.type() == metrics::OmniboxInputType::INVALID) ||
+      (input.type() == metrics::OmniboxInputType::FORCED_QUERY))
+    return;
+
+  // Do some fixup on the user input before matching against it, so we provide
+  // good results for local file paths, input with spaces, etc.
+  const FixupReturn fixup_return(FixupUserInput(input));
+  if (!fixup_return.first)
+    return;
+  url::Parsed parts;
+  url_fixer::SegmentURL(fixup_return.second, &parts);
+  AutocompleteInput fixed_up_input(input);
+  fixed_up_input.UpdateText(fixup_return.second, base::string16::npos, parts);
+
+  // Create a match for what the user typed.
+  const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text());
+  AutocompleteMatch what_you_typed_match(SuggestExactInput(
+      fixed_up_input.text(), fixed_up_input.canonicalized_url(), trim_http));
+  what_you_typed_match.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0);
+
+  // Add the WYT match as a fallback in case we can't get the history service or
+  // URL DB; otherwise, we'll replace this match lower down.  Don't do this for
+  // queries, though -- while we can sometimes mark up a match for them, it's
+  // not what the user wants, and just adds noise.
+  if (fixed_up_input.type() != metrics::OmniboxInputType::QUERY)
+    matches_.push_back(what_you_typed_match);
+
+  // We'll need the history service to run both passes, so try to obtain it.
+  if (!profile_)
+    return;
+  HistoryService* const history_service =
+      HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
+  if (!history_service)
+    return;
+
+  // Get the default search provider and search terms data now since we have to
+  // retrieve these on the UI thread, and the second pass runs on the history
+  // thread. |template_url_service| can be NULL when testing.
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile_);
+  TemplateURL* default_search_provider = template_url_service ?
+      template_url_service->GetDefaultSearchProvider() : NULL;
+  UIThreadSearchTermsData data(profile_);
+
+  // Create the data structure for the autocomplete passes.  We'll save this off
+  // onto the |params_| member for later deletion below if we need to run pass
+  // 2.
+  scoped_ptr<HistoryURLProviderParams> params(
+      new HistoryURLProviderParams(
+          fixed_up_input, trim_http, what_you_typed_match,
+          profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
+          default_search_provider, data));
+  // Note that we use the non-fixed-up input here, since fixup may strip
+  // trailing whitespace.
+  params->prevent_inline_autocomplete = PreventInlineAutocomplete(input);
+
+  // Pass 1: Get the in-memory URL database, and use it to find and promote
+  // the inline autocomplete match, if any.
+  history::URLDatabase* url_db = history_service->InMemoryDatabase();
+  // url_db can be NULL if it hasn't finished initializing (or failed to
+  // initialize).  In this case all we can do is fall back on the second
+  // pass.
+  //
+  // TODO(pkasting): We should just block here until this loads.  Any time
+  // someone unloads the history backend, we'll get inconsistent inline
+  // autocomplete behavior here.
+  if (url_db) {
+    DoAutocomplete(NULL, url_db, params.get());
+    matches_.clear();
+    PromoteMatchesIfNecessary(*params);
+    // NOTE: We don't reset |params| here since at least the |promote_type|
+    // field on it will be read by the second pass -- see comments in
+    // DoAutocomplete().
+  }
+
+  // Pass 2: Ask the history service to call us back on the history thread,
+  // where we can read the full on-disk DB.
+  if (input.want_asynchronous_matches()) {
+    done_ = false;
+    params_ = params.release();  // This object will be destroyed in
+                                 // QueryComplete() once we're done with it.
+    history_service->ScheduleAutocomplete(
+        base::Bind(&HistoryURLProvider::ExecuteWithDB, this, params_));
+  }
 }
 
 void HistoryURLProvider::Stop(bool clear_cached_results) {
@@ -437,6 +596,11 @@ AutocompleteMatch HistoryURLProvider::SuggestExactInput(
     const base::string16& text,
     const GURL& destination_url,
     bool trim_http) {
+  // The FormattedStringWithEquivalentMeaning() call below requires callers to
+  // be on the UI thread.
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
+      !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
+
   AutocompleteMatch match(this, 0, false,
                           AutocompleteMatchType::URL_WHAT_YOU_TYPED);
 
@@ -444,18 +608,17 @@ AutocompleteMatch HistoryURLProvider::SuggestExactInput(
     match.destination_url = destination_url;
 
     // Trim off "http://" if the user didn't type it.
-    // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to
-    // strip the scheme as we need to know the offset so we can adjust the
-    // |match_location| below.  StringForURLDisplay() and TrimHttpPrefix() have
-    // slightly different behavior as well (the latter will strip even without
-    // two slashes after the scheme).
     DCHECK(!trim_http || !AutocompleteInput::HasHTTPScheme(text));
     base::string16 display_string(
-        StringForURLDisplay(destination_url, false, false));
+        net::FormatUrl(destination_url, std::string(),
+                       net::kFormatUrlOmitAll & ~net::kFormatUrlOmitHTTP,
+                       net::UnescapeRule::SPACES, NULL, NULL, NULL));
     const size_t offset = trim_http ? TrimHttpPrefix(&display_string) : 0;
     match.fill_into_edit =
-        AutocompleteInput::FormattedStringWithEquivalentMeaning(destination_url,
-                                                                display_string);
+        AutocompleteInput::FormattedStringWithEquivalentMeaning(
+            destination_url,
+            display_string,
+            ChromeAutocompleteSchemeClassifier(profile_));
     match.allowed_to_be_default_match = true;
     // NOTE: Don't set match.inline_autocompletion to something non-empty here;
     // it's surprising and annoying.
@@ -488,10 +651,9 @@ AutocompleteMatch HistoryURLProvider::SuggestExactInput(
   return match;
 }
 
-// Called on the history thread.
-void HistoryURLProvider::ExecuteWithDB(history::HistoryBackend* backend,
-                                       history::URLDatabase* db,
-                                       HistoryURLProviderParams* params) {
+void HistoryURLProvider::ExecuteWithDB(HistoryURLProviderParams* params,
+                                       history::HistoryBackend* backend,
+                                       history::URLDatabase* db) {
   // We may get called with a NULL database if it couldn't be properly
   // initialized.
   if (!db) {
@@ -510,147 +672,176 @@ void HistoryURLProvider::ExecuteWithDB(history::HistoryBackend* backend,
       &HistoryURLProvider::QueryComplete, this, params));
 }
 
-// Used by both autocomplete passes, and therefore called on multiple different
-// threads (though not simultaneously).
+HistoryURLProvider::~HistoryURLProvider() {
+  // Note: This object can get leaked on shutdown if there are pending
+  // requests on the database (which hold a reference to us). Normally, these
+  // messages get flushed for each thread. We do a round trip from main, to
+  // history, back to main while holding a reference. If the main thread
+  // completes before the history thread, the message to delegate back to the
+  // main thread will not run and the reference will leak. Therefore, don't do
+  // anything on destruction.
+}
+
+// static
+int HistoryURLProvider::CalculateRelevance(MatchType match_type,
+                                           int match_number) {
+  switch (match_type) {
+    case INLINE_AUTOCOMPLETE:
+      return kScoreForBestInlineableResult;
+
+    case UNVISITED_INTRANET:
+      return kScoreForUnvisitedIntranetResult;
+
+    case WHAT_YOU_TYPED:
+      return kScoreForWhatYouTypedResult;
+
+    default:  // NORMAL
+      return kBaseScoreForNonInlineableResult + match_number;
+  }
+}
+
+// static
+ACMatchClassifications HistoryURLProvider::ClassifyDescription(
+    const base::string16& input_text,
+    const base::string16& description) {
+  base::string16 clean_description =
+      bookmarks::CleanUpTitleForMatching(description);
+  history::TermMatches description_matches(SortAndDeoverlapMatches(
+      history::MatchTermInString(input_text, clean_description, 0)));
+  history::WordStarts description_word_starts;
+  history::String16VectorFromString16(
+      clean_description, false, &description_word_starts);
+  // If HistoryURL retrieves any matches (and hence we reach this code), we
+  // are guaranteed that the beginning of input_text must be a word break.
+  history::WordStarts offsets(1, 0u);
+  description_matches =
+      history::ScoredHistoryMatch::FilterTermMatchesByWordStarts(
+          description_matches, offsets, description_word_starts, 0,
+          std::string::npos);
+  return SpansFromTermMatch(
+      description_matches, clean_description.length(), false);
+}
+
 void HistoryURLProvider::DoAutocomplete(history::HistoryBackend* backend,
                                         history::URLDatabase* db,
                                         HistoryURLProviderParams* params) {
-  VisitClassifier classifier(this, params->input, db);
-  // Create a What You Typed match, which we'll need below.
-  //
-  // We display this to the user when there's a reasonable chance they actually
-  // care:
+  // Get the matching URLs from the DB.
+  params->matches.clear();
+  history::URLRows url_matches;
+  const URLPrefixes& prefixes = URLPrefix::GetURLPrefixes();
+  for (URLPrefixes::const_iterator i(prefixes.begin()); i != prefixes.end();
+       ++i) {
+    if (params->cancel_flag.IsSet())
+      return;  // Canceled in the middle of a query, give up.
+
+    // We only need kMaxMatches results in the end, but before we get there we
+    // need to promote lower-quality matches that are prefixes of higher-quality
+    // matches, and remove lower-quality redirects.  So we ask for more results
+    // than we need, of every prefix type, in hopes this will give us far more
+    // than enough to work with.  CullRedirects() will then reduce the list to
+    // the best kMaxMatches results.
+    db->AutocompleteForPrefix(
+        base::UTF16ToUTF8(i->prefix + params->input.text()), kMaxMatches * 2,
+        !backend, &url_matches);
+    for (history::URLRows::const_iterator j(url_matches.begin());
+          j != url_matches.end(); ++j) {
+      const URLPrefix* best_prefix = URLPrefix::BestURLPrefix(
+          base::UTF8ToUTF16(j->url().spec()), base::string16());
+      DCHECK(best_prefix);
+      params->matches.push_back(history::HistoryMatch(
+          *j, i->prefix.length(), !i->num_components,
+          i->num_components >= best_prefix->num_components));
+    }
+  }
+
+  // Create sorted list of suggestions.
+  CullPoorMatches(params);
+  SortAndDedupMatches(&params->matches);
+
+  // Try to create a shorter suggestion from the best match.
+  // We consider the what you typed match eligible for display when there's a
+  // reasonable chance the user actually cares:
   // * Their input can be opened as a URL, and
   // * We parsed the input as a URL, or it starts with an explicit "http:" or
-  //   "https:".
-  //  that is when their input can be opened as a URL.
+  // "https:".
   // Otherwise, this is just low-quality noise.  In the cases where we've parsed
   // as UNKNOWN, we'll still show an accidental search infobar if need be.
-  bool have_what_you_typed_match =
-      params->input.canonicalized_url().is_valid() &&
-      (params->input.type() != AutocompleteInput::QUERY) &&
-      ((params->input.type() != AutocompleteInput::UNKNOWN) ||
+  VisitClassifier classifier(this, params->input, db);
+  params->have_what_you_typed_match =
+      (params->input.type() != metrics::OmniboxInputType::QUERY) &&
+      ((params->input.type() != metrics::OmniboxInputType::UNKNOWN) ||
        (classifier.type() == VisitClassifier::UNVISITED_INTRANET) ||
        !params->trim_http ||
        (AutocompleteInput::NumNonHostComponents(params->input.parts()) > 0));
-  AutocompleteMatch what_you_typed_match(SuggestExactInput(
-      params->input.text(), params->input.canonicalized_url(),
-      params->trim_http));
-  what_you_typed_match.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0);
-
-  // Get the matching URLs from the DB
-  history::URLRows url_matches;
-  history::HistoryMatches history_matches;
-
-  if (search_url_database_) {
-    const URLPrefixes& prefixes = URLPrefix::GetURLPrefixes();
-    for (URLPrefixes::const_iterator i(prefixes.begin()); i != prefixes.end();
-         ++i) {
-      if (params->cancel_flag.IsSet())
-        return;  // Canceled in the middle of a query, give up.
-      // We only need kMaxMatches results in the end, but before we
-      // get there we need to promote lower-quality matches that are
-      // prefixes of higher-quality matches, and remove lower-quality
-      // redirects.  So we ask for more results than we need, of every
-      // prefix type, in hopes this will give us far more than enough
-      // to work with.  CullRedirects() will then reduce the list to
-      // the best kMaxMatches results.
-      db->AutocompleteForPrefix(
-          base::UTF16ToUTF8(i->prefix + params->input.text()),
-          kMaxMatches * 2,
-          (backend == NULL),
-          &url_matches);
-      for (history::URLRows::const_iterator j(url_matches.begin());
-           j != url_matches.end(); ++j) {
-        const URLPrefix* best_prefix =
-            URLPrefix::BestURLPrefix(base::UTF8ToUTF16(j->url().spec()),
-                                     base::string16());
-        DCHECK(best_prefix != NULL);
-        history_matches.push_back(history::HistoryMatch(*j, i->prefix.length(),
-            i->num_components == 0,
-            i->num_components >= best_prefix->num_components));
-      }
-    }
-  }
-
-  // Create sorted list of suggestions.
-  CullPoorMatches(*params, &history_matches);
-  SortAndDedupMatches(&history_matches);
-  PromoteOrCreateShorterSuggestion(db, *params, have_what_you_typed_match,
-                                   what_you_typed_match, &history_matches);
-
-  // Try to promote a match as an exact/inline autocomplete match.  This also
-  // moves it to the front of |history_matches|, so skip over it when
-  // converting the rest of the matches.
-  size_t first_match = 1;
-  size_t exact_suggestion = 0;
-  // Checking |is_history_what_you_typed_match| tells us whether
-  // SuggestExactInput() succeeded in constructing a valid match.
-  if (what_you_typed_match.is_history_what_you_typed_match &&
-      (!backend || !params->dont_suggest_exact_input) &&
-      FixupExactSuggestion(db, params->input, classifier, &what_you_typed_match,
-                           &history_matches)) {
-    // Got an exact match for the user's input.  Treat it as the best match
-    // regardless of the input type.
-    exact_suggestion = 1;
-    params->matches.push_back(what_you_typed_match);
-  } else if (params->prevent_inline_autocomplete ||
-      history_matches.empty() ||
-      !PromoteMatchForInlineAutocomplete(history_matches.front(), params)) {
-    // Failed to promote any URLs for inline autocompletion.  Use the What You
-    // Typed match, if we have it.
-    first_match = 0;
-    if (have_what_you_typed_match)
-      params->matches.push_back(what_you_typed_match);
-  }
-
-  // This is the end of the synchronous pass.
-  if (!backend)
-    return;
-  // If search_url_database_ is false, we shouldn't have scheduled a second
-  // pass.
-  DCHECK(search_url_database_);
-
-  // Determine relevancy of highest scoring match, if any.
-  int relevance = -1;
-  for (ACMatches::const_iterator it = params->matches.begin();
-       it != params->matches.end(); ++it) {
-    relevance = std::max(relevance, it->relevance);
+  const bool have_shorter_suggestion_suitable_for_inline_autocomplete =
+      PromoteOrCreateShorterSuggestion(
+          db, params->have_what_you_typed_match, params);
+
+  // Check whether what the user typed appears in history.
+  const bool can_check_history_for_exact_match =
+      // Checking what_you_typed_match.is_history_what_you_typed_match tells us
+      // whether SuggestExactInput() succeeded in constructing a valid match.
+      params->what_you_typed_match.is_history_what_you_typed_match &&
+      // Additionally, in the case where the user has typed "foo.com" and
+      // visited (but not typed) "foo/", and the input is "foo", the first pass
+      // will fall into the FRONT_HISTORY_MATCH case for "foo.com" but the
+      // second pass can suggest the exact input as a better URL.  Since we need
+      // both passes to agree, and since during the first pass there's no way to
+      // know about "foo/", ensure that if the promote type was set to
+      // FRONT_HISTORY_MATCH during the first pass, the second pass will not
+      // consider the exact suggestion to be in history and therefore will not
+      // suggest the exact input as a better match.  (Note that during the first
+      // pass, this conditional will always succeed since |promote_type| is
+      // initialized to NEITHER.)
+      (params->promote_type != HistoryURLProviderParams::FRONT_HISTORY_MATCH);
+  params->exact_suggestion_is_in_history = can_check_history_for_exact_match &&
+      FixupExactSuggestion(db, classifier, params);
+
+  // If we succeeded in fixing up the exact match based on the user's history,
+  // we should treat it as the best match regardless of input type.  If not,
+  // then we check whether there's an inline autocompletion we can create from
+  // this input, so we can promote that as the best match.
+  if (params->exact_suggestion_is_in_history) {
+    params->promote_type = HistoryURLProviderParams::WHAT_YOU_TYPED_MATCH;
+  } else if (!params->prevent_inline_autocomplete && !params->matches.empty() &&
+      (have_shorter_suggestion_suitable_for_inline_autocomplete ||
+       CanPromoteMatchForInlineAutocomplete(params->matches[0]))) {
+    params->promote_type = HistoryURLProviderParams::FRONT_HISTORY_MATCH;
+  } else {
+    // Failed to promote any URLs.  Use the What You Typed match, if we have it.
+    params->promote_type = params->have_what_you_typed_match ?
+        HistoryURLProviderParams::WHAT_YOU_TYPED_MATCH :
+        HistoryURLProviderParams::NEITHER;
   }
 
-  if (cull_redirects_) {
+  const size_t max_results =
+      kMaxMatches + (params->exact_suggestion_is_in_history ? 1 : 0);
+  if (backend) {
     // Remove redirects and trim list to size.  We want to provide up to
     // kMaxMatches results plus the What You Typed result, if it was added to
-    // |history_matches| above.
-    CullRedirects(backend, &history_matches, kMaxMatches + exact_suggestion);
-  } else {
+    // params->matches above.
+    CullRedirects(backend, &params->matches, max_results);
+  } else if (params->matches.size() > max_results) {
     // Simply trim the list to size.
-    if (history_matches.size() > kMaxMatches + exact_suggestion)
-      history_matches.resize(kMaxMatches + exact_suggestion);
+    params->matches.resize(max_results);
   }
+}
 
-  // Convert the history matches to autocomplete matches.
-  for (size_t i = first_match; i < history_matches.size(); ++i) {
-    const history::HistoryMatch& match = history_matches[i];
-    DCHECK(!have_what_you_typed_match ||
-           (match.url_info.url() !=
-            GURL(params->matches.front().destination_url)));
-    // If we've assigned a score already, all later matches score one
-    // less than the previous match.
-    relevance = (relevance > 0) ? (relevance - 1) :
-       CalculateRelevance(NORMAL, history_matches.size() - 1 - i);
-    AutocompleteMatch ac_match = HistoryMatchToACMatch(*params, match,
-        NORMAL, relevance);
-    // The experimental scoring must not change the top result's score.
-    if (!params->matches.empty()) {
-      relevance = CalculateRelevanceScoreUsingScoringParams(match, relevance);
-      ac_match.relevance = relevance;
+void HistoryURLProvider::PromoteMatchesIfNecessary(
+    const HistoryURLProviderParams& params) {
+  if (params.promote_type == HistoryURLProviderParams::FRONT_HISTORY_MATCH) {
+    matches_.push_back(HistoryMatchToACMatch(params, 0, INLINE_AUTOCOMPLETE,
+        CalculateRelevance(INLINE_AUTOCOMPLETE, 0)));
+    if (OmniboxFieldTrial::AddUWYTMatchEvenIfPromotedURLs() &&
+        params.have_what_you_typed_match) {
+      matches_.push_back(params.what_you_typed_match);
     }
-    params->matches.push_back(ac_match);
+  } else if (params.promote_type ==
+      HistoryURLProviderParams::WHAT_YOU_TYPED_MATCH) {
+    matches_.push_back(params.what_you_typed_match);
   }
 }
 
-// Called on the main thread when the query is complete.
 void HistoryURLProvider::QueryComplete(
     HistoryURLProviderParams* params_gets_deleted) {
   // Ensure |params_gets_deleted| gets deleted on exit.
@@ -668,140 +859,41 @@ void HistoryURLProvider::QueryComplete(
   // Don't modify |matches_| if the query failed, since it might have a default
   // match in it, whereas |params->matches| will be empty.
   if (!params->failed) {
-    matches_.swap(params->matches);
-    UpdateStarredStateOfMatches();
+    matches_.clear();
+    PromoteMatchesIfNecessary(*params);
+
+    // Determine relevance of highest scoring match, if any.
+    int relevance = matches_.empty() ?
+        CalculateRelevance(NORMAL,
+                           static_cast<int>(params->matches.size() - 1)) :
+        matches_[0].relevance;
+
+    // Convert the history matches to autocomplete matches.  If we promoted the
+    // first match, skip over it.
+    const size_t first_match =
+        (params->exact_suggestion_is_in_history ||
+         (params->promote_type ==
+             HistoryURLProviderParams::FRONT_HISTORY_MATCH)) ? 1 : 0;
+    for (size_t i = first_match; i < params->matches.size(); ++i) {
+      // All matches score one less than the previous match.
+      --relevance;
+      // The experimental scoring must not change the top result's score.
+      if (!matches_.empty()) {
+        relevance = CalculateRelevanceScoreUsingScoringParams(
+            params->matches[i], relevance, scoring_params_);
+      }
+      matches_.push_back(HistoryMatchToACMatch(*params, i, NORMAL, relevance));
+    }
   }
 
   done_ = true;
   listener_->OnProviderUpdate(true);
 }
 
-HistoryURLProvider::~HistoryURLProvider() {
-  // Note: This object can get leaked on shutdown if there are pending
-  // requests on the database (which hold a reference to us). Normally, these
-  // messages get flushed for each thread. We do a round trip from main, to
-  // history, back to main while holding a reference. If the main thread
-  // completes before the history thread, the message to delegate back to the
-  // main thread will not run and the reference will leak. Therefore, don't do
-  // anything on destruction.
-}
-
-int HistoryURLProvider::CalculateRelevance(MatchType match_type,
-                                           size_t match_number) const {
-  switch (match_type) {
-    case INLINE_AUTOCOMPLETE:
-      return kScoreForBestInlineableResult;
-
-    case UNVISITED_INTRANET:
-      return kScoreForUnvisitedIntranetResult;
-
-    case WHAT_YOU_TYPED:
-      return kScoreForWhatYouTypedResult;
-
-    default:  // NORMAL
-      return kBaseScoreForNonInlineableResult +
-          static_cast<int>(match_number);
-  }
-}
-
-void HistoryURLProvider::RunAutocompletePasses(
-    const AutocompleteInput& input,
-    bool fixup_input_and_run_pass_1) {
-  matches_.clear();
-
-  if ((input.type() == AutocompleteInput::INVALID) ||
-      (input.type() == AutocompleteInput::FORCED_QUERY))
-    return;
-
-  // Create a match for exactly what the user typed.  This will only be used as
-  // a fallback in case we can't get the history service or URL DB; otherwise,
-  // we'll run this again in DoAutocomplete() and use that result instead.
-  const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text());
-  // Don't do this for queries -- while we can sometimes mark up a match for
-  // this, it's not what the user wants, and just adds noise.
-  if ((input.type() != AutocompleteInput::QUERY) &&
-      input.canonicalized_url().is_valid()) {
-    AutocompleteMatch what_you_typed(SuggestExactInput(
-        input.text(), input.canonicalized_url(), trim_http));
-    what_you_typed.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0);
-    matches_.push_back(what_you_typed);
-  }
-
-  // We'll need the history service to run both passes, so try to obtain it.
-  if (!profile_)
-    return;
-  HistoryService* const history_service =
-      HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
-  if (!history_service)
-    return;
-
-  // Get the default search provider and search terms data now since we have to
-  // retrieve these on the UI thread, and the second pass runs on the history
-  // thread. |template_url_service| can be NULL when testing.
-  TemplateURLService* template_url_service =
-      TemplateURLServiceFactory::GetForProfile(profile_);
-  TemplateURL* default_search_provider = template_url_service ?
-      template_url_service->GetDefaultSearchProvider() : NULL;
-  UIThreadSearchTermsData data(profile_);
-
-  // Create the data structure for the autocomplete passes.  We'll save this off
-  // onto the |params_| member for later deletion below if we need to run pass
-  // 2.
-  scoped_ptr<HistoryURLProviderParams> params(
-      new HistoryURLProviderParams(
-          input, trim_http,
-          profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
-          default_search_provider, data));
-
-  params->prevent_inline_autocomplete =
-      PreventInlineAutocomplete(input);
-
-  if (fixup_input_and_run_pass_1) {
-    // Do some fixup on the user input before matching against it, so we provide
-    // good results for local file paths, input with spaces, etc.
-    if (!FixupUserInput(&params->input))
-      return;
-
-    // Pass 1: Get the in-memory URL database, and use it to find and promote
-    // the inline autocomplete match, if any.
-    history::URLDatabase* url_db = history_service->InMemoryDatabase();
-    // url_db can be NULL if it hasn't finished initializing (or failed to
-    // initialize).  In this case all we can do is fall back on the second
-    // pass.
-    //
-    // TODO(pkasting): We should just block here until this loads.  Any time
-    // someone unloads the history backend, we'll get inconsistent inline
-    // autocomplete behavior here.
-    if (url_db) {
-      DoAutocomplete(NULL, url_db, params.get());
-      // params->matches now has the matches we should expose to the provider.
-      // Pass 2 expects a "clean slate" set of matches.
-      matches_.clear();
-      matches_.swap(params->matches);
-      UpdateStarredStateOfMatches();
-    }
-  }
-
-  // Pass 2: Ask the history service to call us back on the history thread,
-  // where we can read the full on-disk DB.
-  if (search_url_database_ &&
-      (input.matches_requested() == AutocompleteInput::ALL_MATCHES)) {
-    done_ = false;
-    params_ = params.release();  // This object will be destroyed in
-                                 // QueryComplete() once we're done with it.
-    history_service->ScheduleAutocomplete(this, params_);
-  }
-}
-
 bool HistoryURLProvider::FixupExactSuggestion(
     history::URLDatabase* db,
-    const AutocompleteInput& input,
     const VisitClassifier& classifier,
-    AutocompleteMatch* match,
-    history::HistoryMatches* matches) const {
-  DCHECK(match != NULL);
-  DCHECK(matches != NULL);
-
+    HistoryURLProviderParams* params) const {
   MatchType type = INLINE_AUTOCOMPLETE;
   switch (classifier.type()) {
     case VisitClassifier::INVALID:
@@ -812,25 +904,26 @@ bool HistoryURLProvider::FixupExactSuggestion(
     default:
       DCHECK_EQ(VisitClassifier::VISITED, classifier.type());
       // We have data for this match, use it.
-      match->deletable = true;
-      match->description = classifier.url_row().title();
-      RecordAdditionalInfoFromUrlRow(classifier.url_row(), match);
-      match->description_class =
-          ClassifyDescription(input.text(), match->description);
+      params->what_you_typed_match.deletable = true;
+      params->what_you_typed_match.description = classifier.url_row().title();
+      RecordAdditionalInfoFromUrlRow(classifier.url_row(),
+                                     &params->what_you_typed_match);
+      params->what_you_typed_match.description_class = ClassifyDescription(
+          params->input.text(), params->what_you_typed_match.description);
       if (!classifier.url_row().typed_count()) {
         // If we reach here, we must be in the second pass, and we must not have
         // this row's data available during the first pass.  That means we
         // either scored it as WHAT_YOU_TYPED or UNVISITED_INTRANET, and to
         // maintain the ordering between passes consistent, we need to score it
         // the same way here.
-        type = CanFindIntranetURL(db, input) ?
+        type = CanFindIntranetURL(db, params->input) ?
             UNVISITED_INTRANET : WHAT_YOU_TYPED;
       }
       break;
   }
 
-  const GURL& url = match->destination_url;
-  const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
+  const GURL& url = params->what_you_typed_match.destination_url;
+  const url::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
   // If the what-you-typed result looks like a single word (which can be
   // interpreted as an intranet address) followed by a pound sign ("#"),
   // leave the score for the url-what-you-typed result as is.  It will be
@@ -848,27 +941,27 @@ bool HistoryURLProvider::FixupExactSuggestion(
   // between the input "c" and the input "c#", both of which will have empty
   // reference fragments.)
   if ((type == UNVISITED_INTRANET) &&
-      (input.type() != AutocompleteInput::URL) &&
+      (params->input.type() != metrics::OmniboxInputType::URL) &&
       url.username().empty() && url.password().empty() && url.port().empty() &&
       (url.path() == "/") && url.query().empty() &&
-      (parsed.CountCharactersBefore(url_parse::Parsed::REF, true) !=
-       parsed.CountCharactersBefore(url_parse::Parsed::REF, false))) {
+      (parsed.CountCharactersBefore(url::Parsed::REF, true) !=
+       parsed.CountCharactersBefore(url::Parsed::REF, false))) {
     return false;
   }
 
-  match->relevance = CalculateRelevance(type, 0);
+  params->what_you_typed_match.relevance = CalculateRelevance(type, 0);
 
   // If there are any other matches, then don't promote this match here, in
   // hopes the caller will be able to inline autocomplete a better suggestion.
   // DoAutocomplete() will fall back on this match if inline autocompletion
   // fails.  This matches how we react to never-visited URL inputs in the non-
   // intranet case.
-  if (type == UNVISITED_INTRANET && !matches->empty())
+  if (type == UNVISITED_INTRANET && !params->matches.empty())
     return false;
 
   // Put it on the front of the HistoryMatches for redirect culling.
   CreateOrPromoteMatch(classifier.url_row(), base::string16::npos, false,
-                       matches, true, true);
+                       &params->matches, true, true);
   return true;
 }
 
@@ -879,8 +972,8 @@ bool HistoryURLProvider::CanFindIntranetURL(
   // third condition, but because FixupUserInput() can run and modify the
   // input's text and parts between Parse() and here, it seems better to be
   // paranoid and check.
-  if ((input.type() != AutocompleteInput::UNKNOWN) ||
-      !LowerCaseEqualsASCII(input.scheme(), content::kHttpScheme) ||
+  if ((input.type() != metrics::OmniboxInputType::UNKNOWN) ||
+      !LowerCaseEqualsASCII(input.scheme(), url::kHttpScheme) ||
       !input.parts().host.is_nonempty())
     return false;
   const std::string host(base::UTF16ToUTF8(
@@ -893,81 +986,38 @@ bool HistoryURLProvider::CanFindIntranetURL(
   return registry_length == 0 && db->IsTypedHost(host);
 }
 
-bool HistoryURLProvider::PromoteMatchForInlineAutocomplete(
-    const history::HistoryMatch& match,
-    HistoryURLProviderParams* params) {
-  // Promote the first match if it's been marked for promotion or typed at least
-  // n times, where n == 1 for "simple" (host-only) URLs and n == 2 for others.
-  // We set a higher bar for these long URLs because it's less likely that users
-  // will want to visit them again.  Even though we don't increment the
-  // typed_count for pasted-in URLs, if the user manually edits the URL or types
-  // some long thing in by hand, we wouldn't want to immediately start
-  // autocompleting it.
-  if (!match.promoted &&
-      (!match.url_info.typed_count() ||
-       ((match.url_info.typed_count() == 1) &&
-        !match.IsHostOnly())))
-    return false;
-
-  // In the case where the user has typed "foo.com" and visited (but not typed)
-  // "foo/", and the input is "foo", we can reach here for "foo.com" during the
-  // first pass but have the second pass suggest the exact input as a better
-  // URL.  Since we need both passes to agree, and since during the first pass
-  // there's no way to know about "foo/", make reaching this point prevent any
-  // future pass from suggesting the exact input as a better match.
-  if (params) {
-    params->dont_suggest_exact_input = true;
-    AutocompleteMatch ac_match = HistoryMatchToACMatch(
-        *params, match, INLINE_AUTOCOMPLETE,
-        CalculateRelevance(INLINE_AUTOCOMPLETE, 0));
-    params->matches.push_back(ac_match);
-  }
-  return true;
-}
-
-// See if a shorter version of the best match should be created, and if so place
-// it at the front of |matches|.  This can suggest history URLs that are
-// prefixes of the best match (if they've been visited enough, compared to the
-// best match), or create host-only suggestions even when they haven't been
-// visited before: if the user visited http://example.com/asdf once, we'll
-// suggest http://example.com/ even if they've never been to it.
-void HistoryURLProvider::PromoteOrCreateShorterSuggestion(
+bool HistoryURLProvider::PromoteOrCreateShorterSuggestion(
     history::URLDatabase* db,
-    const HistoryURLProviderParams& params,
     bool have_what_you_typed_match,
-    const AutocompleteMatch& what_you_typed_match,
-    history::HistoryMatches* matches) {
-  if (matches->empty())
-    return;  // No matches, nothing to do.
+    HistoryURLProviderParams* params) {
+  if (params->matches.empty())
+    return false;  // No matches, nothing to do.
 
   // Determine the base URL from which to search, and whether that URL could
   // itself be added as a match.  We can add the base iff it's not "effectively
   // the same" as any "what you typed" match.
-  const history::HistoryMatch& match = matches->front();
-  GURL search_base = ConvertToHostOnly(match, params.input.text());
+  const history::HistoryMatch& match = params->matches[0];
+  GURL search_base = ConvertToHostOnly(match, params->input.text());
   bool can_add_search_base_to_matches = !have_what_you_typed_match;
   if (search_base.is_empty()) {
     // Search from what the user typed when we couldn't reduce the best match
     // to a host.  Careful: use a substring of |match| here, rather than the
     // first match in |params|, because they might have different prefixes.  If
-    // the user typed "google.com", |what_you_typed_match| will hold
+    // the user typed "google.com", params->what_you_typed_match will hold
     // "http://google.com/", but |match| might begin with
     // "http://www.google.com/".
     // TODO: this should be cleaned up, and is probably incorrect for IDN.
     std::string new_match = match.url_info.url().possibly_invalid_spec().
-        substr(0, match.input_location + params.input.text().length());
+        substr(0, match.input_location + params->input.text().length());
     search_base = GURL(new_match);
-    // TODO(mrossetti): There is a degenerate case where the following may
-    // cause a failure: http://www/~someword/fubar.html. Diagnose.
-    // See: http://crbug.com/50101
     if (search_base.is_empty())
-      return;  // Can't construct a valid URL from which to start a search.
+      return false;  // Can't construct a URL from which to start a search.
   } else if (!can_add_search_base_to_matches) {
     can_add_search_base_to_matches =
-        (search_base != what_you_typed_match.destination_url);
+        (search_base != params->what_you_typed_match.destination_url);
   }
   if (search_base == match.url_info.url())
-    return;  // Couldn't shorten |match|, so no range of URLs to search over.
+    return false;  // Couldn't shorten |match|, so no URLs to search over.
 
   // Search the DB for short URLs between our base and |match|.
   history::URLRow info(search_base);
@@ -986,7 +1036,7 @@ void HistoryURLProvider::PromoteOrCreateShorterSuggestion(
           match.url_info.url().possibly_invalid_spec(), min_visit_count,
           min_typed_count, can_add_search_base_to_matches, &info)) {
     if (!can_add_search_base_to_matches)
-      return;  // Couldn't find anything and can't add the search base, bail.
+      return false;  // Couldn't find anything and can't add the search base.
 
     // Try to get info on the search base itself.  Promote it to the top if the
     // original best match isn't good enough to autocomplete.
@@ -995,27 +1045,25 @@ void HistoryURLProvider::PromoteOrCreateShorterSuggestion(
   }
 
   // Promote or add the desired URL to the list of matches.
-  bool ensure_can_inline =
-      promote && PromoteMatchForInlineAutocomplete(match, NULL);
-  ensure_can_inline &= CreateOrPromoteMatch(info, match.input_location,
-      match.match_in_scheme, matches, create_shorter_match_, promote);
-  if (ensure_can_inline)
-    matches->front().promoted = true;
+  const bool ensure_can_inline =
+      promote && CanPromoteMatchForInlineAutocomplete(match);
+  return CreateOrPromoteMatch(info, match.input_location, match.match_in_scheme,
+                              &params->matches, true, promote) &&
+      ensure_can_inline;
 }
 
 void HistoryURLProvider::CullPoorMatches(
-    const HistoryURLProviderParams& params,
-    history::HistoryMatches* matches) const {
+    HistoryURLProviderParams* params) const {
   const base::Time& threshold(history::AutocompleteAgeThreshold());
-  for (history::HistoryMatches::iterator i(matches->begin());
-       i != matches->end(); ) {
+  for (history::HistoryMatches::iterator i(params->matches.begin());
+       i != params->matches.end(); ) {
     if (RowQualifiesAsSignificant(i->url_info, threshold) &&
-        !(params.default_search_provider &&
-            params.default_search_provider->IsSearchURLUsingTermsData(
-                i->url_info.url(), *params.search_terms_data.get()))) {
+        (!params->default_search_provider ||
+         !params->default_search_provider->IsSearchURL(
+             i->url_info.url(), *params->search_terms_data))) {
       ++i;
     } else {
-      i = matches->erase(i);
+      i = params->matches.erase(i);
     }
   }
 }
@@ -1028,7 +1076,7 @@ void HistoryURLProvider::CullRedirects(history::HistoryBackend* backend,
     const GURL& url = (*matches)[source].url_info.url();
     // TODO(brettw) this should go away when everything uses GURL.
     history::RedirectList redirects;
-    backend->GetMostRecentRedirectsFrom(url, &redirects);
+    backend->QueryRedirectsFrom(url, &redirects);
     if (!redirects.empty()) {
       // Remove all but the first occurrence of any of these redirects in the
       // search results. We also must add the URL we queried for, since it may
@@ -1082,9 +1130,15 @@ size_t HistoryURLProvider::RemoveSubsequentMatchesOf(
 
 AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
     const HistoryURLProviderParams& params,
-    const history::HistoryMatch& history_match,
+    size_t match_number,
     MatchType match_type,
     int relevance) {
+  // The FormattedStringWithEquivalentMeaning() call below requires callers to
+  // be on the UI thread.
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
+      !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
+
+  const history::HistoryMatch& history_match = params.matches[match_number];
   const history::URLRow& info = history_match.url_info;
   AutocompleteMatch match(this, relevance,
       !!info.visit_count(), AutocompleteMatchType::HISTORY_URL);
@@ -1099,10 +1153,12 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
       ~((params.trim_http && !history_match.match_in_scheme) ?
           0 : net::kFormatUrlOmitHTTP);
   match.fill_into_edit =
-      AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(),
+      AutocompleteInput::FormattedStringWithEquivalentMeaning(
+          info.url(),
           net::FormatUrl(info.url(), languages, format_types,
                          net::UnescapeRule::SPACES, NULL, NULL,
-                         &inline_autocomplete_offset));
+                         &inline_autocomplete_offset),
+          ChromeAutocompleteSchemeClassifier(profile_));
   if (!params.prevent_inline_autocomplete &&
       (inline_autocomplete_offset != base::string16::npos)) {
     DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length());
@@ -1136,46 +1192,3 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
   RecordAdditionalInfoFromUrlRow(info, &match);
   return match;
 }
-
-int HistoryURLProvider::CalculateRelevanceScoreUsingScoringParams(
-    const history::HistoryMatch& match,
-    int old_relevance) const {
-  if (!scoring_params_.experimental_scoring_enabled)
-    return old_relevance;
-
-  const base::TimeDelta time_since_last_visit =
-      base::Time::Now() - match.url_info.last_visit();
-
-  int relevance = CalculateRelevanceUsingScoreBuckets(
-      scoring_params_.typed_count_buckets, time_since_last_visit, old_relevance,
-      match.url_info.typed_count());
-
-  // Additional demotion (on top of typed_count demotion) of URLs that were
-  // never typed.
-  if (match.url_info.typed_count() == 0) {
-    relevance = CalculateRelevanceUsingScoreBuckets(
-        scoring_params_.visited_count_buckets, time_since_last_visit, relevance,
-        match.url_info.visit_count());
-  }
-
-  DCHECK_LE(relevance, old_relevance);
-  return relevance;
-}
-
-// static
-ACMatchClassifications HistoryURLProvider::ClassifyDescription(
-    const base::string16& input_text,
-    const base::string16& description) {
-  base::string16 clean_description = history::CleanUpTitleForMatching(
-      description);
-  history::TermMatches description_matches(SortAndDeoverlapMatches(
-      history::MatchTermInString(input_text, clean_description, 0)));
-  history::WordStarts description_word_starts;
-  history::String16VectorFromString16(
-      clean_description, false, &description_word_starts);
-  description_matches =
-      history::ScoredHistoryMatch::FilterTermMatchesByWordStarts(
-          description_matches, description_word_starts, 0, std::string::npos);
-  return SpansFromTermMatch(
-      description_matches, clean_description.length(), false);
-}