summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-07 21:45:46 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-07 21:45:46 +0000
commitc61870842d8b24bca42bb1b4cc5d8629ae22e83c (patch)
tree44bb3e5649b730f5e38afca35a53aed29d56b9ef
parent95f14bf54cbbca1a2dd77999149f595c14ca18a7 (diff)
downloadchromium_src-c61870842d8b24bca42bb1b4cc5d8629ae22e83c.zip
chromium_src-c61870842d8b24bca42bb1b4cc5d8629ae22e83c.tar.gz
chromium_src-c61870842d8b24bca42bb1b4cc5d8629ae22e83c.tar.bz2
If we promote a shorter match above a longer one, and the longer one was inline autocompletable, make sure the shorter one is too.
BUG=6798 TEST=none Review URL: https://chromiumcodereview.appspot.com/10543047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141088 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc178
-rw-r--r--chrome/browser/autocomplete/history_url_provider.h24
-rw-r--r--chrome/browser/autocomplete/history_url_provider_unittest.cc26
3 files changed, 141 insertions, 87 deletions
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index 389dcfc..548a66f 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -90,80 +90,6 @@ GURL ConvertToHostOnly(const history::HistoryMatch& match,
return host;
}
-// 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 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.
-
- // 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());
- 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
- // "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());
- 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) {
- can_add_search_base_to_matches =
- (search_base != 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.
-
- // Search the DB for short URLs between our base and |match|.
- history::URLRow info(search_base);
- bool promote = true;
- // A short URL is only worth suggesting if it's been visited at least a third
- // as often as the longer URL.
- const int min_visit_count = ((match.url_info.visit_count() - 1) / 3) + 1;
- // For stability between the in-memory and on-disk autocomplete passes, when
- // the long URL has been typed before, only suggest shorter URLs that have
- // also been typed. Otherwise, the on-disk pass could suggest a shorter URL
- // (which hasn't been typed) that the in-memory pass doesn't know about,
- // thereby making the top match, and thus the behavior of inline
- // autocomplete, unstable.
- const int min_typed_count = match.url_info.typed_count() ? 1 : 0;
- if (!db->FindShortestURLFromBase(search_base.possibly_invalid_spec(),
- 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.
-
- // 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.
- db->GetRowForURL(search_base, &info);
- promote = match.url_info.typed_count() <= 1;
- }
-
- // Promote or add the desired URL to the list of matches.
- EnsureMatchPresent(info, match.input_location, match.match_in_scheme,
- matches, promote);
-}
-
// 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) {
@@ -438,8 +364,7 @@ void HistoryURLProvider::DoAutocomplete(history::HistoryBackend* backend,
params->matches.push_back(what_you_typed_match);
} else if (params->prevent_inline_autocomplete ||
history_matches.empty() ||
- !PromoteMatchForInlineAutocomplete(params, history_matches.front(),
- history_matches)) {
+ !PromoteMatchForInlineAutocomplete(params, history_matches.front())) {
// Failed to promote any URLs for inline autocompletion. Use the What You
// Typed match, if we have it.
first_match = 0;
@@ -732,8 +657,7 @@ bool HistoryURLProvider::CanFindIntranetURL(
bool HistoryURLProvider::PromoteMatchForInlineAutocomplete(
HistoryURLProviderParams* params,
- const history::HistoryMatch& match,
- const history::HistoryMatches& matches) {
+ const history::HistoryMatch& match) {
// Promote the first 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
@@ -751,12 +675,104 @@ bool HistoryURLProvider::PromoteMatchForInlineAutocomplete(
// 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.
- params->dont_suggest_exact_input = true;
- params->matches.push_back(HistoryMatchToACMatch(params, match,
- INLINE_AUTOCOMPLETE, CalculateRelevance(INLINE_AUTOCOMPLETE, 0)));
+ if (params) {
+ params->dont_suggest_exact_input = true;
+ params->matches.push_back(HistoryMatchToACMatch(params, match,
+ INLINE_AUTOCOMPLETE, CalculateRelevance(INLINE_AUTOCOMPLETE, 0)));
+ }
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(
+ 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.
+
+ // 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());
+ 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
+ // "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());
+ 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) {
+ can_add_search_base_to_matches =
+ (search_base != 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.
+
+ // Search the DB for short URLs between our base and |match|.
+ history::URLRow info(search_base);
+ bool promote = true;
+ // A short URL is only worth suggesting if it's been visited at least a third
+ // as often as the longer URL.
+ const int min_visit_count = ((match.url_info.visit_count() - 1) / 3) + 1;
+ // For stability between the in-memory and on-disk autocomplete passes, when
+ // the long URL has been typed before, only suggest shorter URLs that have
+ // also been typed. Otherwise, the on-disk pass could suggest a shorter URL
+ // (which hasn't been typed) that the in-memory pass doesn't know about,
+ // thereby making the top match, and thus the behavior of inline
+ // autocomplete, unstable.
+ const int min_typed_count = match.url_info.typed_count() ? 1 : 0;
+ if (!db->FindShortestURLFromBase(search_base.possibly_invalid_spec(),
+ 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.
+
+ // 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.
+ db->GetRowForURL(search_base, &info);
+ promote = match.url_info.typed_count() <= 1;
+ }
+
+ // Promote or add the desired URL to the list of matches.
+ bool ensure_can_inline =
+ promote && PromoteMatchForInlineAutocomplete(NULL, match);
+ EnsureMatchPresent(info, match.input_location, match.match_in_scheme,
+ matches, promote);
+ if (ensure_can_inline) {
+ // If |match| was inline-autocompletable and we're promoting something to
+ // replace it, make sure the promoted item is also inline-autocompletable.
+ // Setting the typed_count to 2 is sufficient to guarantee this (and is safe
+ // because by this point all sorting has already happened and the only thing
+ // checking the typed_count will be PromoteMatchForInlineAutocomplete()).
+ //
+ // We have to do this here rather than changing |info| before calling
+ // EnsureMatchPresent() because if EnsureMatchPresent() merely moves an
+ // existing match to the front, it will ignore the typed_count in |info|.
+ // But we set |ensure_can_inline| above because |match| is a reference and
+ // thus checking it here would examine the wrong match.
+ matches->front().url_info.set_typed_count(2);
+ }
+}
+
void HistoryURLProvider::SortMatches(history::HistoryMatches* matches) const {
// Sort by quality, best first.
std::sort(matches->begin(), matches->end(), &CompareHistoryMatch);
diff --git a/chrome/browser/autocomplete/history_url_provider.h b/chrome/browser/autocomplete/history_url_provider.h
index 3328d2f..716dc3b 100644
--- a/chrome/browser/autocomplete/history_url_provider.h
+++ b/chrome/browser/autocomplete/history_url_provider.h
@@ -220,12 +220,24 @@ class HistoryURLProvider : public HistoryProvider {
bool CanFindIntranetURL(history::URLDatabase* db,
const AutocompleteInput& input) const;
- // Determines if |match| is suitable for inline autocomplete, and promotes it
- // if so.
- bool PromoteMatchForInlineAutocomplete(
- HistoryURLProviderParams* params,
- const history::HistoryMatch& match,
- const history::HistoryMatches& history_matches);
+ // Determines if |match| is suitable for inline autocomplete. If so, and if
+ // |params| is non-NULL, promotes the match. Returns whether |match| is
+ // suitable for inline autocomplete.
+ bool PromoteMatchForInlineAutocomplete(HistoryURLProviderParams* params,
+ const history::HistoryMatch& match);
+
+ // Sees if a shorter version of the best match should be created, and if so
+ // places 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 PromoteOrCreateShorterSuggestion(
+ history::URLDatabase* db,
+ const HistoryURLProviderParams& params,
+ bool have_what_you_typed_match,
+ const AutocompleteMatch& what_you_typed_match,
+ history::HistoryMatches* matches);
// Sorts the given list of matches.
void SortMatches(history::HistoryMatches* matches) const;
diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc
index 6c6535f..b67c831 100644
--- a/chrome/browser/autocomplete/history_url_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc
@@ -47,6 +47,13 @@ struct TestURLInfo {
{"http://news.google.com/?ned=us&topic=n", "Google News - U.S.", 2, 2},
{"http://news.google.com/", "Google News", 1, 1},
+ // Matches that are normally not inline-autocompletable should be
+ // autocompleted if they are shorter substitutes for longer matches that would
+ // have been inline autocompleted.
+ {"http://synthesisatest.com/foo/", "Test A", 1, 1},
+ {"http://synthesisbtest.com/foo/", "Test B", 1, 1},
+ {"http://synthesisbtest.com/foo/bar.html", "Test B Bar", 2, 2},
+
// Suggested short URLs must be "good enough" and must match user input.
{"http://foo.com/", "Dir", 5, 5},
{"http://foo.com/dir/", "Dir", 2, 2},
@@ -281,6 +288,25 @@ TEST_F(HistoryURLProviderTest, PromoteShorterURLs) {
// Test that unpopular pages are ignored completely.
RunTest(ASCIIToUTF16("fresh"), string16(), true, NULL, 0);
+ // Test that if we create or promote shorter suggestions that would not
+ // normally be inline autocompletable, we make them inline autocompletable if
+ // the original suggestion (that we replaced as "top") was inline
+ // autocompletable.
+ const std::string expected_synthesisa[] = {
+ "http://synthesisatest.com/",
+ "http://synthesisatest.com/foo/",
+ };
+ RunTest(ASCIIToUTF16("synthesisa"), string16(), false, expected_synthesisa,
+ arraysize(expected_synthesisa));
+ EXPECT_LT(matches_.front().relevance, 1200);
+ const std::string expected_synthesisb[] = {
+ "http://synthesisbtest.com/foo/",
+ "http://synthesisbtest.com/foo/bar.html",
+ };
+ RunTest(ASCIIToUTF16("synthesisb"), string16(), false, expected_synthesisb,
+ arraysize(expected_synthesisb));
+ EXPECT_GE(matches_.front().relevance, 1410);
+
// Test that if we have a synthesized host that matches a suggestion, they
// get combined into one.
const std::string expected_combine[] = {