diff options
Diffstat (limited to 'chrome/browser/autocomplete/history_url_provider.cc')
-rw-r--r-- | chrome/browser/autocomplete/history_url_provider.cc | 216 |
1 files changed, 105 insertions, 111 deletions
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc index 3d15658..bac2d1a 100644 --- a/chrome/browser/autocomplete/history_url_provider.cc +++ b/chrome/browser/autocomplete/history_url_provider.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/basictypes.h" +#include "base/command_line.h" #include "base/histogram.h" #include "base/message_loop.h" #include "base/string_util.h" @@ -17,6 +18,7 @@ #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "googleurl/src/gurl.h" @@ -27,80 +29,6 @@ using base::Time; using base::TimeDelta; using base::TimeTicks; -// TODO(mrossetti): Move these to a more appropriate place. -using history::Prefix; -using history::Prefixes; -using history::HistoryMatch; -using history::HistoryMatches; - -namespace history { - -// Returns true if |url| is just a host (e.g. "http://www.google.com/") and -// not some other subpage (e.g. "http://www.google.com/foo.html"). -bool IsHostOnly(const GURL& url) { - DCHECK(url.is_valid()); - return (!url.has_path() || (url.path() == "/")) && !url.has_query() && - !url.has_ref(); -} - -// Acts like the > operator for URLInfo classes. -bool CompareHistoryMatch(const HistoryMatch& a, const HistoryMatch& b) { - // 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()) - return a.url_info.typed_count() > b.url_info.typed_count(); - - // Innermost matches (matches after any scheme or "www.") are better than - // non-innermost matches. - if (a.innermost_match != b.innermost_match) - return a.innermost_match; - - // URLs that have been typed more often are better. - if (a.url_info.typed_count() != b.url_info.typed_count()) - return a.url_info.typed_count() > b.url_info.typed_count(); - - // For URLs that have each been typed once, a host (alone) is better than a - // page inside. - if (a.url_info.typed_count() == 1) { - const bool a_is_host_only = history::IsHostOnly(a.url_info.url()); - if (a_is_host_only != history::IsHostOnly(b.url_info.url())) - return a_is_host_only; - } - - // URLs that have been visited more often are better. - if (a.url_info.visit_count() != b.url_info.visit_count()) - return a.url_info.visit_count() > b.url_info.visit_count(); - - // URLs that have been visited more recently are better. - return a.url_info.last_visit() > b.url_info.last_visit(); -} - -// 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 HistoryMatch& match, const std::wstring& 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 std::wstring spec = UTF8ToWide(host.spec()); - if (spec.compare(match.input_location, input.length(), input)) - return GURL(); // User typing is no longer a prefix. - - return host; -} - -} // namespace history HistoryURLProviderParams::HistoryURLProviderParams( const AutocompleteInput& input, @@ -223,25 +151,30 @@ void HistoryURLProvider::DoAutocomplete(history::HistoryBackend* backend, URLRowVector url_matches; HistoryMatches history_matches; - for (Prefixes::const_iterator i(prefixes_.begin()); i != prefixes_.end(); - ++i) { - if (params->cancel) - 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(WideToUTF16(i->prefix + params->input.text()), - kMaxMatches * 2, &url_matches); - for (URLRowVector::const_iterator j(url_matches.begin()); - j != url_matches.end(); ++j) { - const Prefix* best_prefix = BestPrefix(j->url(), std::wstring()); - DCHECK(best_prefix != NULL); - history_matches.push_back(HistoryMatch(*j, i->prefix.length(), - !i->num_components, - i->num_components >= best_prefix->num_components)); + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableInMemoryURLIndex)) { + // TODO(rohitrao): Fetch results from the index. + } else { + for (Prefixes::const_iterator i(prefixes_.begin()); i != prefixes_.end(); + ++i) { + if (params->cancel) + 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(WideToUTF16(i->prefix + params->input.text()), + kMaxMatches * 2, &url_matches); + for (URLRowVector::const_iterator j(url_matches.begin()); + j != url_matches.end(); ++j) { + const Prefix* best_prefix = BestPrefix(j->url(), std::wstring()); + DCHECK(best_prefix != NULL); + history_matches.push_back(HistoryMatch(*j, i->prefix.length(), + !i->num_components, + i->num_components >= best_prefix->num_components)); + } } } @@ -427,7 +360,7 @@ bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( // hand, we wouldn't want to immediately start autocompleting it. if (!match.url_info.typed_count() || ((match.url_info.typed_count() == 1) && - !history::IsHostOnly(match.url_info.url()))) + !IsHostOnly(match.url_info.url()))) return false; params->matches.push_back(HistoryMatchToACMatch(params, match, @@ -521,7 +454,47 @@ size_t HistoryURLProvider::TrimHttpPrefix(std::wstring* url) { } // static -history::Prefixes HistoryURLProvider::GetPrefixes() { +bool HistoryURLProvider::IsHostOnly(const GURL& url) { + DCHECK(url.is_valid()); + return (!url.has_path() || (url.path() == "/")) && !url.has_query() && + !url.has_ref(); +} + +// static +bool HistoryURLProvider::CompareHistoryMatch(const HistoryMatch& a, + const HistoryMatch& b) { + // 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()) + return a.url_info.typed_count() > b.url_info.typed_count(); + + // Innermost matches (matches after any scheme or "www.") are better than + // non-innermost matches. + if (a.innermost_match != b.innermost_match) + return a.innermost_match; + + // URLs that have been typed more often are better. + if (a.url_info.typed_count() != b.url_info.typed_count()) + return a.url_info.typed_count() > b.url_info.typed_count(); + + // For URLs that have each been typed once, a host (alone) is better than a + // page inside. + if (a.url_info.typed_count() == 1) { + const bool a_is_host_only = IsHostOnly(a.url_info.url()); + if (a_is_host_only != IsHostOnly(b.url_info.url())) + return a_is_host_only; + } + + // URLs that have been visited more often are better. + if (a.url_info.visit_count() != b.url_info.visit_count()) + return a.url_info.visit_count() > b.url_info.visit_count(); + + // URLs that have been visited more recently are better. + return a.url_info.last_visit() > b.url_info.last_visit(); +} + +// static +HistoryURLProvider::Prefixes HistoryURLProvider::GetPrefixes() { // We'll complete text following these prefixes. // NOTE: There's no requirement that these be in any particular order. Prefixes prefixes; @@ -553,6 +526,30 @@ int HistoryURLProvider::CalculateRelevance(AutocompleteInput::Type input_type, } // static +GURL HistoryURLProvider::ConvertToHostOnly(const HistoryMatch& match, + const std::wstring& 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 std::wstring spec = UTF8ToWide(host.spec()); + if (spec.compare(match.input_location, input.length(), input)) + return GURL(); // User typing is no longer a prefix. + + return host; +} + +// static void HistoryURLProvider::PromoteOrCreateShorterSuggestion( history::URLDatabase* db, const HistoryURLProviderParams& params, @@ -566,7 +563,7 @@ void HistoryURLProvider::PromoteOrCreateShorterSuggestion( // 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 HistoryMatch& match = matches->front(); - GURL search_base = history::ConvertToHostOnly(match, params.input.text()); + 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 @@ -576,14 +573,9 @@ void HistoryURLProvider::PromoteOrCreateShorterSuggestion( // "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(); - std::string::size_type substring_length = params.input.text().length(); - substring_length += match.input_location; - new_match = new_match.substr(0, substring_length); + std::string new_match = match.url_info.url().possibly_invalid_spec(). + 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. } else if (!can_add_search_base_to_matches) { @@ -730,7 +722,7 @@ void HistoryURLProvider::RunAutocompletePasses( } } -const history::Prefix* HistoryURLProvider::BestPrefix( +const HistoryURLProvider::Prefix* HistoryURLProvider::BestPrefix( const GURL& url, const std::wstring& prefix_suffix) const { const Prefix* best_prefix = NULL; @@ -750,7 +742,7 @@ const history::Prefix* HistoryURLProvider::BestPrefix( void HistoryURLProvider::SortMatches(HistoryMatches* matches) const { // Sort by quality, best first. - std::sort(matches->begin(), matches->end(), &history::CompareHistoryMatch); + std::sort(matches->begin(), matches->end(), &CompareHistoryMatch); // Remove duplicate matches (caused by the search string appearing in one of // the prefixes as well as after it). Consider the following scenario: @@ -783,13 +775,15 @@ void HistoryURLProvider::SortMatches(HistoryMatches* matches) const { } void HistoryURLProvider::CullPoorMatches(HistoryMatches* matches) const { - Time recent_threshold = history::AutocompleteAgeThreshold(); + static const int kLowQualityMatchTypedLimit = 1; + static const int kLowQualityMatchVisitLimit = 3; + static const int kLowQualityMatchAgeLimitInDays = 3; + Time recent_threshold = + Time::Now() - TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays); for (HistoryMatches::iterator i(matches->begin()); i != matches->end();) { - const history::URLRow& url_info(i->url_info); - if ((url_info.typed_count() <= - history::kLowQualityMatchTypedLimit) && - (url_info.visit_count() <= - history::kLowQualityMatchVisitLimit) && + const history::URLRow& url_info = i->url_info; + if ((url_info.typed_count() <= kLowQualityMatchTypedLimit) && + (url_info.visit_count() <= kLowQualityMatchVisitLimit) && (url_info.last_visit() < recent_threshold)) { i = matches->erase(i); } else { |