summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/history_url_provider.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/autocomplete/history_url_provider.cc')
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc216
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 {