summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-19 17:08:00 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-19 17:08:00 +0000
commitfe4eb9827d908251a0f2fd1a2d46cdf51e94cd7a (patch)
treef2d80a848fc72f90e08f63fb6fb4418bd199707f
parent7c5048cb78980caeb134eec8748ab892df2237fb (diff)
downloadchromium_src-fe4eb9827d908251a0f2fd1a2d46cdf51e94cd7a.zip
chromium_src-fe4eb9827d908251a0f2fd1a2d46cdf51e94cd7a.tar.gz
chromium_src-fe4eb9827d908251a0f2fd1a2d46cdf51e94cd7a.tar.bz2
Handle intranet hostnames more consistently.
AutocompleteInput::Parse() now usually marks intranet navigations as UNKNOWN and relies on the HistoryURLProvider to do the right thing. In turn the HistoryURLProvider will mark URLs it's never seen as high-quality navigations if they have a hostname that's part of a previously-type intranet URL. So for example, "abc/def" on a clean profile now defaults to searching rather than navigating; but if any URL on host "abc" has been typed before, both "abc/def" and "abc/def ghi" will navigate, despite the space in the second case. This also changes the default behavior for some similar cases like "abc:81", "user:pass@abc", and "user:pass@abc:81". Again these will all now default to searching, but navigate if the host in question has been typed. Unchanged is the behavior of "abc/"; because the scheme-stripping code relies on a single trailing slash triggering a navigation, and because it's convenient for users to force navigation on an unknown host, this is still parsed as a URL. BUG=6788 TEST=Navigate to "who/", then type "who/a b" and note that the default action is to navigate rather than search. Review URL: http://codereview.chromium.org/7661028 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97470 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/autocomplete.cc61
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_unittest.cc16
-rw-r--r--chrome/browser/autocomplete/autocomplete_unittest.cc14
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc82
-rw-r--r--chrome/browser/autocomplete/history_url_provider.h6
-rw-r--r--chrome/browser/autocomplete/history_url_provider_unittest.cc58
-rw-r--r--chrome/browser/history/url_database.cc5
-rw-r--r--chrome/browser/history/url_database.h7
8 files changed, 152 insertions, 97 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc
index d728924..627e35d 100644
--- a/chrome/browser/autocomplete/autocomplete.cc
+++ b/chrome/browser/autocomplete/autocomplete.cc
@@ -353,11 +353,6 @@ AutocompleteInput::Type AutocompleteInput::Parse(
if (host_info.family == url_canon::CanonHostInfo::IPV6)
return URL;
- // Now that we've ruled out invalid ports and queries that look like they have
- // a port, the presence of a port means this is likely a URL.
- if (parts->port.is_nonempty())
- return URL;
-
// Presence of a password means this is likely a URL. Note that unless the
// user has typed an explicit "http://" or similar, we'll probably think that
// the username is some unknown scheme, and bail out in the scheme-handling
@@ -365,35 +360,31 @@ AutocompleteInput::Type AutocompleteInput::Parse(
if (parts->password.is_nonempty())
return URL;
- // The host doesn't look like a number, so see if the user's given us a path.
- if (parts->path.is_nonempty()) {
- // Most inputs with paths are URLs, even ones without known registries (e.g.
- // intranet URLs). However, if there's no known registry and the path has
- // a space, this is more likely a query with a slash in the first term
- // (e.g. "ps/2 games") than a URL. We can still open URLs with spaces in
- // the path by escaping the space, and we will still inline autocomplete
- // them if users have typed them in the past, but we default to searching
- // since that's the common case.
- return ((registry_length == 0) &&
- (text.substr(parts->path.begin, parts->path.len).find(' ') !=
- string16::npos)) ? UNKNOWN : URL;
- }
+ // Trailing slashes force the input to be treated as a URL.
+ if (parts->path.len == 1)
+ return URL;
- // If we reach here with a username, our input looks like "user@host".
- // Because there is no scheme explicitly specified, we think this is more
- // likely an email address than an HTTP auth attempt. Hence, we search by
- // default and let users correct us on a case-by-case basis.
- if (parts->username.is_nonempty())
+ // If we reach here with a username, but no port or path, our input looks like
+ // "user@host". Because there is no scheme explicitly specified, we think
+ // this is more likely an email address than an HTTP auth attempt. Hence, we
+ // search by default and let users correct us on a case-by-case basis.
+ if (parts->username.is_nonempty() && !parts->port.is_nonempty() &&
+ !parts->path.is_nonempty())
return UNKNOWN;
- // We have a bare host string. If it has a known TLD, it's probably a URL.
- if (registry_length != 0)
+ // If the host has a known TLD, it's probably a URL. Also special-case
+ // "localhost" as a known hostname.
+ if ((registry_length != 0) || (host == ASCIIToUTF16("localhost")))
return URL;
- // No TLD that we know about. This could be:
- // * A string that the user wishes to add a desired_tld to to get a URL. If
- // we reach this point, we know there's no known TLD on the string, so the
- // fixup code will be willing to add one; thus this is a URL.
+ // If we reach this point, we know there's no known TLD on the input, so if
+ // the user wishes to add a desired_tld, the fixup code will oblige; thus this
+ // is a URL.
+ if (!desired_tld.empty())
+ return REQUESTED_URL;
+
+ // No scheme, username, password, port, path, and no known TLD on the host.
+ // This could be:
// * A single word "foo"; possibly an intranet site, but more likely a search.
// This is ideally an UNKNOWN, and we can let the Alternate Nav URL code
// catch our mistakes.
@@ -403,11 +394,10 @@ AutocompleteInput::Type AutocompleteInput::Parse(
// distinguish this case from:
// * A "URL-like" string that's not really a URL (like
// "browser.tabs.closeButtons" or "java.awt.event.*"). This is ideally a
- // QUERY. Since the above case and this one are indistinguishable, and this
- // case is likely to be much more common, just say these are both UNKNOWN,
- // which should default to the right thing and let users correct us on a
- // case-by-case basis.
- return desired_tld.empty() ? UNKNOWN : REQUESTED_URL;
+ // QUERY. Since this is indistinguishable from the case above, and this
+ // case is much more likely, claim these are UNKNOWN, which should default
+ // to the right thing and let users correct us on a case-by-case basis.
+ return UNKNOWN;
}
// static
@@ -431,7 +421,8 @@ void AutocompleteInput::ParseForEmphasizeComponents(
// Obtain the URL prefixed by view-source and parse it.
string16 real_url(text.substr(after_scheme_and_colon));
url_parse::Parsed real_parts;
- AutocompleteInput::Parse(real_url, desired_tld, &real_parts, NULL, NULL);
+ AutocompleteInput::Parse(real_url, desired_tld, &real_parts, NULL,
+ NULL);
if (real_parts.scheme.is_nonempty() || real_parts.host.is_nonempty()) {
if (real_parts.scheme.is_nonempty()) {
*scheme = url_parse::Component(
diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
index eed5a9f..8b26855 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc
@@ -108,32 +108,32 @@ TEST(AutocompleteEditTest, AdjustTextForCopy) {
const char* expected_url;
} input[] = {
// Test that http:// is inserted if all text is selected.
- { "a.b/c", 0, true, "a.b/c", "http://a.b/c", true, "http://a.b/c" },
+ { "a.de/b", 0, true, "a.de/b", "http://a.de/b", true, "http://a.de/b" },
// Test that http:// is inserted if the host is selected.
- { "a.b/c", 0, false, "a.b/", "http://a.b/", true, "http://a.b/" },
+ { "a.de/b", 0, false, "a.de/", "http://a.de/", true, "http://a.de/" },
// Tests that http:// is inserted if the path is modified.
- { "a.b/c", 0, false, "a.b/d", "http://a.b/d", true, "http://a.b/d" },
+ { "a.de/b", 0, false, "a.de/c", "http://a.de/c", true, "http://a.de/c" },
// Tests that http:// isn't inserted if the host is modified.
- { "a.b/c", 0, false, "a.c/", "a.c/", false, "" },
+ { "a.de/b", 0, false, "a.com/b", "a.com/b", false, "" },
// Tests that http:// isn't inserted if the start of the selection is 1.
- { "a.b/c", 1, false, "a.b/", "a.b/", false, "" },
+ { "a.de/b", 1, false, "a.de/b", "a.de/b", false, "" },
// Tests that http:// isn't inserted if a portion of the host is selected.
- { "a.com/", 0, false, "a.co", "a.co", false, "" },
+ { "a.de/", 0, false, "a.d", "a.d", false, "" },
// Tests that http:// isn't inserted for an https url after the user nukes
// https.
{ "https://a.com/", 0, false, "a.com/", "a.com/", false, "" },
// Tests that http:// isn't inserted if the user adds to the host.
- { "a.b/", 0, false, "a.bc/", "a.bc/", false, "" },
+ { "a.de/", 0, false, "a.de.com/", "a.de.com/", false, "" },
// Tests that we don't get double http if the user manually inserts http.
- { "a.b/", 0, false, "http://a.b/", "http://a.b/", true, "http://a.b/" },
+ { "a.de/", 0, false, "http://a.de/", "http://a.de/", true, "http://a.de/" },
};
ScopedTestingBrowserProcess browser_process;
TestingOmniboxView view;
diff --git a/chrome/browser/autocomplete/autocomplete_unittest.cc b/chrome/browser/autocomplete/autocomplete_unittest.cc
index e464fb9..cf3dec1 100644
--- a/chrome/browser/autocomplete/autocomplete_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_unittest.cc
@@ -286,12 +286,13 @@ TEST_F(AutocompleteTest, InputType) {
{ ASCIIToUTF16("?foo bar"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("?http://foo.com/bar"), AutocompleteInput::FORCED_QUERY },
{ ASCIIToUTF16("foo"), AutocompleteInput::UNKNOWN },
+ { ASCIIToUTF16("localhost"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo.c"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("-foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo-.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo.-com"), AutocompleteInput::QUERY },
- { ASCIIToUTF16("foo/bar"), AutocompleteInput::URL },
+ { ASCIIToUTF16("foo/bar"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo;bar"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo/bar baz"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("foo bar.com"), AutocompleteInput::QUERY },
@@ -300,13 +301,16 @@ TEST_F(AutocompleteTest, InputType) {
{ ASCIIToUTF16("foo+bar.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("\"foo:bar\""), AutocompleteInput::QUERY },
{ ASCIIToUTF16("link:foo.com"), AutocompleteInput::UNKNOWN },
- { ASCIIToUTF16("foo:81"), AutocompleteInput::URL },
- { ASCIIToUTF16("www.foo.com:81"), AutocompleteInput::URL },
+ { ASCIIToUTF16("foo:81"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("localhost:8080"), AutocompleteInput::URL },
+ { ASCIIToUTF16("www.foo.com:81"), AutocompleteInput::URL },
{ ASCIIToUTF16("foo.com:123456"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("foo.com:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("1.2.3.4:abc"), AutocompleteInput::QUERY },
{ ASCIIToUTF16("user@foo.com"), AutocompleteInput::UNKNOWN },
+ { ASCIIToUTF16("user@foo/z"), AutocompleteInput::UNKNOWN },
+ { ASCIIToUTF16("user@foo/z z"), AutocompleteInput::UNKNOWN },
+ { ASCIIToUTF16("user@foo.com/z"), AutocompleteInput::URL },
{ ASCIIToUTF16("user:pass@"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user:pass@!foo.com"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user:pass@foo"), AutocompleteInput::URL },
@@ -318,8 +322,8 @@ TEST_F(AutocompleteTest, InputType) {
{ ASCIIToUTF16("1.2/45"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("1.2:45"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user@1.2:45"), AutocompleteInput::UNKNOWN },
+ { ASCIIToUTF16("user@foo:45"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("user:pass@1.2:45"), AutocompleteInput::URL },
- { ASCIIToUTF16("ps/2 games"), AutocompleteInput::UNKNOWN },
{ ASCIIToUTF16("en.wikipedia.org/wiki/James Bond"),
AutocompleteInput::URL },
// In Chrome itself, mailto: will get handled by ShellExecute, but in
@@ -353,7 +357,6 @@ TEST_F(AutocompleteTest, InputType) {
{ ASCIIToUTF16("http://1.2"), AutocompleteInput::URL },
{ ASCIIToUTF16("http://1.2/45"), AutocompleteInput::URL },
{ ASCIIToUTF16("http:ps/2 games"), AutocompleteInput::URL },
- { ASCIIToUTF16("http://ps/2 games"), AutocompleteInput::URL },
{ ASCIIToUTF16("https://foo.com"), AutocompleteInput::URL },
{ ASCIIToUTF16("127.0.0.1"), AutocompleteInput::URL },
{ ASCIIToUTF16("127.0.1"), AutocompleteInput::UNKNOWN },
@@ -383,6 +386,7 @@ TEST_F(AutocompleteTest, InputTypeWithDesiredTLD) {
} input_cases[] = {
{ ASCIIToUTF16("401k"), AutocompleteInput::REQUESTED_URL },
{ ASCIIToUTF16("999999999999999"), AutocompleteInput::REQUESTED_URL },
+ { ASCIIToUTF16("x@y/z z"), AutocompleteInput::REQUESTED_URL },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_cases); ++i) {
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index cadf499..c7cf7f7 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -25,6 +25,7 @@
#include "googleurl/src/url_parse.h"
#include "googleurl/src/url_util.h"
#include "net/base/net_util.h"
+#include "net/base/registry_controlled_domain.h"
namespace {
@@ -242,7 +243,7 @@ float CalculateConfidence(const history::HistoryMatch& match,
return (0.5f * typed_score) + (0.3f * visit_score) + (0.2f * innermost_score);
}
-} // namespace history
+} // namespace
HistoryURLProviderParams::HistoryURLProviderParams(
const AutocompleteInput& input,
@@ -662,33 +663,37 @@ bool HistoryURLProvider::FixupExactSuggestion(
!input.parts().path.is_nonempty())
return false;
- // Tricky corner case: The user has visited intranet site "foo", but not
- // internet site "www.foo.com". He types in foo (getting an exact match),
- // then tries to hit ctrl-enter. When pressing ctrl, the what-you-typed
- // match ("www.foo.com") doesn't show up in history, and thus doesn't get a
- // promoted relevance, but a different match from the input ("foo") does, and
- // gets promoted for inline autocomplete. Thus instead of getting
- // "www.foo.com", the user still gets "foo" (and, before hitting enter,
- // probably gets an odd-looking inline autocomplete of "/").
- //
- // We detect this crazy case as follows:
- // * If the what-you-typed match is not in the history DB,
- // * and the user has specified a TLD,
- // * and the input _without_ the TLD _is_ in the history DB,
- // * ...then just before pressing "ctrl" the best match we supplied was the
- // what-you-typed match, so stick with it by promoting this.
history::URLRow info;
MatchType type = INLINE_AUTOCOMPLETE;
if (!db->GetRowForURL(match->destination_url, &info)) {
- if (input.desired_tld().empty())
- return false;
- GURL destination_url(URLFixerUpper::FixupURL(UTF16ToUTF8(input.text()),
- std::string()));
- if (!db->GetRowForURL(destination_url, NULL))
- return false;
-
- // If we got here, then we hit the tricky corner case. Make sure that
- // |info| corresponds to the right URL.
+ if (CanFindIntranetURL(db, input)) {
+ // The user typed an intranet hostname that they've visited (albeit with a
+ // different port and/or path) before. Continuing ensures this input will
+ // be treated as a navigation.
+ } else {
+ // Tricky corner case: The user has visited intranet site "foo", but not
+ // internet site "www.foo.com". He types in foo (getting an exact match),
+ // then tries to hit ctrl-enter. When pressing ctrl, the what-you-typed
+ // match ("www.foo.com") doesn't show up in history, and thus doesn't get
+ // a promoted relevance, but a different match from the input ("foo")
+ // does, and gets promoted for inline autocomplete. Thus instead of
+ // getting "www.foo.com", the user still gets "foo" (and, before hitting
+ // enter, probably gets an odd-looking inline autocomplete of "/").
+ //
+ // We detect this crazy case as follows:
+ // * If the what-you-typed match is not in the history DB,
+ // * and the user has specified a TLD,
+ // * and the input _without_ the TLD _is_ in the history DB,
+ // * ...then just before pressing "ctrl" the best match we supplied was
+ // the what-you-typed match, so stick with it by promoting this.
+ if (input.desired_tld().empty())
+ return false;
+ GURL destination_url(URLFixerUpper::FixupURL(UTF16ToUTF8(input.text()),
+ std::string()));
+ if (!db->GetRowForURL(destination_url, NULL))
+ return false;
+ // If we got here, then we hit the tricky corner case.
+ }
info = history::URLRow(match->destination_url);
} else {
// We have data for this match, use it.
@@ -717,6 +722,31 @@ bool HistoryURLProvider::FixupExactSuggestion(
return true;
}
+bool HistoryURLProvider::CanFindIntranetURL(
+ history::URLDatabase* db,
+ const AutocompleteInput& input) const {
+ if ((input.type() != AutocompleteInput::UNKNOWN) ||
+ !LowerCaseEqualsASCII(input.scheme(), chrome::kHttpScheme))
+ return false;
+ DCHECK(input.parts().host.is_nonempty());
+ const string16 host(input.text().substr(input.parts().host.begin,
+ input.parts().host.len));
+ if (net::RegistryControlledDomainService::GetRegistryLength(
+ UTF16ToUTF8(host), false) != 0)
+ return false;
+ std::vector<history::URLRow> dummy;
+ for (history::Prefixes::const_iterator i(prefixes_.begin());
+ i != prefixes_.end(); ++i) {
+ if ((i->num_components == 1) &&
+ (db->AutocompleteForPrefix(i->prefix + host + ASCIIToUTF16("/"), 1,
+ true, &dummy) ||
+ db->AutocompleteForPrefix(i->prefix + host + ASCIIToUTF16(":"), 1,
+ true, &dummy)))
+ return true;
+ }
+ return false;
+}
+
bool HistoryURLProvider::PromoteMatchForInlineAutocomplete(
HistoryURLProviderParams* params,
const history::HistoryMatch& match,
@@ -782,7 +812,7 @@ void HistoryURLProvider::CullPoorMatches(
history::HistoryMatches* matches) const {
const base::Time& threshold(history::AutocompleteAgeThreshold());
for (history::HistoryMatches::iterator i(matches->begin());
- i != matches->end();) {
+ i != matches->end(); ) {
if (RowQualifiesAsSignificant(i->url_info, threshold))
++i;
else
diff --git a/chrome/browser/autocomplete/history_url_provider.h b/chrome/browser/autocomplete/history_url_provider.h
index e928fbf..78925b1 100644
--- a/chrome/browser/autocomplete/history_url_provider.h
+++ b/chrome/browser/autocomplete/history_url_provider.h
@@ -215,6 +215,12 @@ class HistoryURLProvider : public HistoryProvider {
AutocompleteMatch* match,
history::HistoryMatches* matches) const;
+ // Helper function for FixupExactSuggestion, this returns true if the input
+ // corresponds to some intranet URL where the user has previously visited the
+ // host in question. In this case the input should be treated as a URL.
+ bool CanFindIntranetURL(history::URLDatabase* db,
+ const AutocompleteInput& input) const;
+
// Determines if |match| is suitable for inline autocomplete, and promotes it
// if so.
bool PromoteMatchForInlineAutocomplete(
diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc
index e0d29bc..0363418 100644
--- a/chrome/browser/autocomplete/history_url_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/history_url_provider.h"
#include "chrome/browser/history/history.h"
+#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_browser_process_test.h"
#include "chrome/test/base/testing_profile.h"
@@ -20,8 +21,8 @@ using base::Time;
using base::TimeDelta;
struct TestURLInfo {
- std::string url;
- std::string title;
+ const char* url;
+ const char* title;
int visit_count;
int typed_count;
} test_db[] = {
@@ -312,21 +313,18 @@ TEST_F(HistoryURLProviderTest, CullRedirects) {
// (the redirect set below will also increment the visit counts). We want
// the results to be in A,B,C order. Note also that our visit counts are
// all high enough so that domain synthesizing won't get triggered.
- struct RedirectCase {
+ struct TestCase {
const char* url;
int count;
- };
- static const RedirectCase redirect[] = {
+ } test_cases[] = {
{"http://redirects/A", 30},
{"http://redirects/B", 20},
{"http://redirects/C", 10}
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(redirect); i++) {
- history_service_->AddPageWithDetails(GURL(redirect[i].url),
- UTF8ToUTF16("Title"),
- redirect[i].count, redirect[i].count,
- Time::Now(), false,
- history::SOURCE_BROWSED);
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
+ history_service_->AddPageWithDetails(GURL(test_cases[i].url),
+ UTF8ToUTF16("Title"), test_cases[i].count, test_cases[i].count,
+ Time::Now(), false, history::SOURCE_BROWSED);
}
// Create a B->C->A redirect chain, but set the visit counts such that they
@@ -334,12 +332,11 @@ TEST_F(HistoryURLProviderTest, CullRedirects) {
// search for the most recent visit when looking for redirects, so this will
// be found even though the previous visits had no redirects.
history::RedirectList redirects_to_a;
- redirects_to_a.push_back(GURL(redirect[1].url));
- redirects_to_a.push_back(GURL(redirect[2].url));
- redirects_to_a.push_back(GURL(redirect[0].url));
- history_service_->AddPage(GURL(redirect[0].url), NULL, 0, GURL(),
- PageTransition::TYPED, redirects_to_a,
- history::SOURCE_BROWSED, true);
+ redirects_to_a.push_back(GURL(test_cases[1].url));
+ redirects_to_a.push_back(GURL(test_cases[2].url));
+ redirects_to_a.push_back(GURL(test_cases[0].url));
+ history_service_->AddPage(GURL(test_cases[0].url), NULL, 0, GURL(),
+ PageTransition::TYPED, redirects_to_a, history::SOURCE_BROWSED, true);
// Because all the results are part of a redirect chain with other results,
// all but the first one (A) should be culled. We should get the default
@@ -347,7 +344,8 @@ TEST_F(HistoryURLProviderTest, CullRedirects) {
const string16 typing(ASCIIToUTF16("http://redirects/"));
const std::string expected_results[] = {
UTF16ToUTF8(typing),
- redirect[0].url};
+ test_cases[0].url,
+ };
RunTest(typing, string16(), true, expected_results,
arraysize(expected_results));
}
@@ -511,3 +509,27 @@ TEST_F(HistoryURLProviderTest, TreatEmailsAsSearches) {
// Visiting foo.com should not make this string be treated as a navigation.
RunTest(ASCIIToUTF16("user@foo.com"), string16(), false, NULL, 0);
}
+
+TEST_F(HistoryURLProviderTest, IntranetURLsWithPaths) {
+ struct TestCase {
+ const char* input;
+ bool has_output;
+ } test_cases[] = {
+ { "fooey", false },
+ { "fooey/", true },
+ { "fooey/a", false },
+ { "fooey/a b", false },
+ { "gooey", true },
+ { "gooey/", true },
+ { "gooey/a", true },
+ { "gooey/a b", true },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ const std::string output[1] = {
+ URLFixerUpper::FixupURL(test_cases[i].input, std::string()).spec()
+ };
+ RunTest(ASCIIToUTF16(test_cases[i].input), string16(), false,
+ test_cases[i].has_output ? output : NULL,
+ test_cases[i].has_output ? 1 : 0);
+ }
+}
diff --git a/chrome/browser/history/url_database.cc b/chrome/browser/history/url_database.cc
index 4b31c10..5ef2a5e 100644
--- a/chrome/browser/history/url_database.cc
+++ b/chrome/browser/history/url_database.cc
@@ -291,7 +291,7 @@ bool URLDatabase::InitIconMappingEnumeratorForEverything(
return true;
}
-void URLDatabase::AutocompleteForPrefix(const string16& prefix,
+bool URLDatabase::AutocompleteForPrefix(const string16& prefix,
size_t max_results,
bool typed_only,
std::vector<history::URLRow>* results) {
@@ -317,7 +317,7 @@ void URLDatabase::AutocompleteForPrefix(const string16& prefix,
sql::Statement statement(
GetDB().GetCachedStatement(sql::StatementID(__FILE__, line), sql));
if (!statement)
- return;
+ return false;
// We will find all strings between "prefix" and this string, which is prefix
// followed by the maximum character size. Use 8-bit strings for everything
@@ -337,6 +337,7 @@ void URLDatabase::AutocompleteForPrefix(const string16& prefix,
if (info.url().is_valid())
results->push_back(info);
}
+ return !results->empty();
}
bool URLDatabase::FindShortestURLFromBase(const std::string& base,
diff --git a/chrome/browser/history/url_database.h b/chrome/browser/history/url_database.h
index b6be207..08c43d8 100644
--- a/chrome/browser/history/url_database.h
+++ b/chrome/browser/history/url_database.h
@@ -164,11 +164,12 @@ class URLDatabase {
// Autocomplete --------------------------------------------------------------
- // Fills the given array with URLs matching the given prefix. They will be
+ // Fills the given array with URLs matching the given prefix. They will be
// sorted by typed count, then by visit count, then by visit date (most recent
// first) up to the given maximum number. If |typed_only| is true, only urls
- // that have been typed once are returned. Called by HistoryURLProvider.
- void AutocompleteForPrefix(const string16& prefix,
+ // that have been typed once are returned. For caller convenience, returns
+ // whether any results were found. Called by HistoryURLProvider.
+ bool AutocompleteForPrefix(const string16& prefix,
size_t max_results,
bool typed_only,
std::vector<URLRow>* results);