diff options
22 files changed, 680 insertions, 179 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc index cf516e5..d5b6cc6 100644 --- a/chrome/browser/autocomplete/autocomplete.cc +++ b/chrome/browser/autocomplete/autocomplete.cc @@ -780,10 +780,11 @@ AutocompleteController::AutocompleteController(Profile* profile) have_committed_during_this_query_(false), done_(true) { providers_.push_back(new SearchProvider(this, profile)); - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableInMemoryURLIndex)) + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableHistoryQuickProvider)) providers_.push_back(new HistoryQuickProvider(this, profile)); - else + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableHistoryURLProvider)) providers_.push_back(new HistoryURLProvider(this, profile)); providers_.push_back(new KeywordProvider(this, profile)); history_contents_provider_ = new HistoryContentsProvider(this, profile); diff --git a/chrome/browser/autocomplete/history_provider.cc b/chrome/browser/autocomplete/history_provider.cc new file mode 100644 index 0000000..bbc2fe5 --- /dev/null +++ b/chrome/browser/autocomplete/history_provider.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/history_url_provider.h" + +#include <string> + +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/common/url_constants.h" +#include "googleurl/src/url_util.h" + +HistoryProvider::HistoryProvider(ACProviderListener* listener, + Profile* profile, + const char* name) + : AutocompleteProvider(listener, profile, name) { +} + +// static +std::wstring HistoryProvider::FixupUserInput(const AutocompleteInput& input) { + const std::wstring& input_text = input.text(); + // Fixup and canonicalize user input. + const GURL canonical_gurl(URLFixerUpper::FixupURL(WideToUTF8(input_text), + std::string())); + std::string canonical_gurl_str(canonical_gurl.possibly_invalid_spec()); + if (canonical_gurl_str.empty()) { + // This probably won't happen, but there are no guarantees. + return input_text; + } + + // If the user types a number, GURL will convert it to a dotted quad. + // However, if the parser did not mark this as a URL, then the user probably + // didn't intend this interpretation. Since this can break history matching + // for hostname beginning with numbers (e.g. input of "17173" will be matched + // against "0.0.67.21" instead of the original "17173", failing to find + // "17173.com"), swap the original hostname in for the fixed-up one. + if ((input.type() != AutocompleteInput::URL) && + canonical_gurl.HostIsIPAddress()) { + std::string original_hostname = + WideToUTF8(input_text.substr(input.parts().host.begin, + input.parts().host.len)); + const url_parse::Parsed& parts = + canonical_gurl.parsed_for_possibly_invalid_spec(); + // parts.host must not be empty when HostIsIPAddress() is true. + DCHECK(parts.host.is_nonempty()); + canonical_gurl_str.replace(parts.host.begin, parts.host.len, + original_hostname); + } + std::wstring output = UTF8ToWide(canonical_gurl_str); + // Don't prepend a scheme when the user didn't have one. Since the fixer + // upper only prepends the "http" scheme, that's all we need to check for. + if (canonical_gurl.SchemeIs(chrome::kHttpScheme) && + !url_util::FindAndCompareScheme(WideToUTF8(input_text), + chrome::kHttpScheme, NULL)) + TrimHttpPrefix(&output); + + // Make the number of trailing slashes on the output exactly match the input. + // Examples of why not doing this would matter: + // * The user types "a" and has this fixed up to "a/". Now no other sites + // beginning with "a" will match. + // * The user types "file:" and has this fixed up to "file://". Now inline + // autocomplete will append too few slashes, resulting in e.g. "file:/b..." + // instead of "file:///b..." + // * The user types "http:/" and has this fixed up to "http:". Now inline + // autocomplete will append too many slashes, resulting in e.g. + // "http:///c..." instead of "http://c...". + // NOTE: We do this after calling TrimHttpPrefix() since that can strip + // trailing slashes (if the scheme is the only thing in the input). It's not + // clear that the result of fixup really matters in this case, but there's no + // harm in making sure. + const size_t last_input_nonslash = input_text.find_last_not_of(L"/\\"); + const size_t num_input_slashes = (last_input_nonslash == std::wstring::npos) ? + input_text.length() : (input_text.length() - 1 - last_input_nonslash); + const size_t last_output_nonslash = output.find_last_not_of(L"/\\"); + const size_t num_output_slashes = + (last_output_nonslash == std::wstring::npos) ? + output.length() : (output.length() - 1 - last_output_nonslash); + if (num_output_slashes < num_input_slashes) + output.append(num_input_slashes - num_output_slashes, '/'); + else if (num_output_slashes > num_input_slashes) + output.erase(output.length() - num_output_slashes + num_input_slashes); + + return output; +} + +// static +size_t HistoryProvider::TrimHttpPrefix(std::wstring* url) { + // Find any "http:". + if (!HasHTTPScheme(*url)) + return 0; + size_t scheme_pos = url->find(ASCIIToWide(chrome::kHttpScheme) + L":"); + DCHECK(scheme_pos != std::wstring::npos); + + // Erase scheme plus up to two slashes. + size_t prefix_end = scheme_pos + strlen(chrome::kHttpScheme) + 1; + const size_t after_slashes = std::min(url->length(), prefix_end + 2); + while ((prefix_end < after_slashes) && ((*url)[prefix_end] == L'/')) + ++prefix_end; + url->erase(scheme_pos, prefix_end - scheme_pos); + return (scheme_pos == 0) ? prefix_end : 0; +} diff --git a/chrome/browser/autocomplete/history_provider.h b/chrome/browser/autocomplete/history_provider.h new file mode 100644 index 0000000..bdefabd --- /dev/null +++ b/chrome/browser/autocomplete/history_provider.h @@ -0,0 +1,53 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_HISTORY_PROVIDER_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_PROVIDER_H_ +#pragma once + +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/autocomplete/history_provider_util.h" + +namespace history { + +class HistoryBackend; +class URLDatabase; +class URLRow; + +} // namespace history + +// This class is a base class for the history autocomplete providers and +// provides functions useful to all derived classes. +class HistoryProvider : public AutocompleteProvider { + protected: + enum MatchType { + NORMAL, + WHAT_YOU_TYPED, + INLINE_AUTOCOMPLETE + }; + + HistoryProvider(ACProviderListener* listener, + Profile* profile, + const char* name); + + // Fixes up user URL input to make it more possible to match against. Among + // many other things, this takes care of the following: + // * Prepending file:// to file URLs + // * Converting drive letters in file URLs to uppercase + // * Converting case-insensitive parts of URLs (like the scheme and domain) + // to lowercase + // * Convert spaces to %20s + // Note that we don't do this in AutocompleteInput's constructor, because if + // e.g. we convert a Unicode hostname to punycode, other providers will show + // output that surprises the user ("Search Google for xn--6ca.com"). + static std::wstring FixupUserInput(const AutocompleteInput& input); + + // Trims "http:" and up to two subsequent slashes from |url|. Returns the + // number of characters that were trimmed. + // NOTE: For a view-source: URL, this will trim from after "view-source:" and + // return 0. + static size_t TrimHttpPrefix(std::wstring* url); +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_HISTORY_PROVIDER_H_ diff --git a/chrome/browser/autocomplete/history_quick_provider.cc b/chrome/browser/autocomplete/history_quick_provider.cc index 0d4fdda..776c343 100644 --- a/chrome/browser/autocomplete/history_quick_provider.cc +++ b/chrome/browser/autocomplete/history_quick_provider.cc @@ -4,7 +4,193 @@ #include "chrome/browser/autocomplete/history_quick_provider.h" +#include "base/basictypes.h" +#include "base/histogram.h" +#include "base/i18n/word_iterator.h" +#include "base/string_util.h" +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/history/in_memory_url_index.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/common/notification_source.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "googleurl/src/url_util.h" +#include "net/base/escape.h" +#include "net/base/net_util.h" + +using history::InMemoryURLIndex; +using history::ScoredHistoryMatch; +using history::ScoredHistoryMatches; + +HistoryQuickProvider::HistoryQuickProvider(ACProviderListener* listener, + Profile* profile) + : HistoryProvider(listener, profile, "HistoryQuickProvider"), + trim_http_(false), + languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) {} + +HistoryQuickProvider::~HistoryQuickProvider() {} + void HistoryQuickProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - // TODO(mrossetti): Implement. + matches_.clear(); + + if ((input.type() == AutocompleteInput::INVALID) || + (input.type() == AutocompleteInput::FORCED_QUERY)) + return; + + autocomplete_input_ = input; + trim_http_ = !HasHTTPScheme(input.text()); + + // Do some fixup on the user input before matching against it, so we provide + // good results for local file paths, input with spaces, etc. + // NOTE: This purposefully doesn't take input.desired_tld() into account; if + // it did, then holding "ctrl" would change all the results from the + // HistoryQuickProvider provider, not just the What You Typed Result. + const std::wstring fixed_text(FixupUserInput(input)); + if (fixed_text.empty()) { + // Conceivably fixup could result in an empty string (although I don't + // have cases where this happens offhand). We can't do anything with + // empty input, so just bail; otherwise we'd crash later. + return; + } + autocomplete_input_.set_text(fixed_text); + + // 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 (GetIndex()) { + DoAutocomplete(); + UpdateStarredStateOfMatches(); + } +} + +void HistoryQuickProvider::DoAutocomplete() { + // Get the matching URLs from the DB. + string16 term_string(WideToUTF16(autocomplete_input_.text())); + term_string = UnescapeURLComponent(term_string, + UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); + history::InMemoryURLIndex::String16Vector terms( + HistoryQuickProvider::WordVectorFromString16(term_string)); + ScoredHistoryMatches matches = GetIndex()->HistoryItemsForTerms(terms); + + size_t match_num = matches.size() - 1; + for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); + match_iter != matches.end(); ++match_iter, --match_num) { + const ScoredHistoryMatch& history_match(*match_iter); + AutocompleteMatch ac_match = + QuickMatchToACMatch(history_match, NORMAL, match_num); + matches_.push_back(ac_match); + } +} + +AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( + const ScoredHistoryMatch& history_match, + MatchType match_type, + size_t match_number) { + const history::URLRow& info = history_match.url_info; + int score = CalculateRelevance(history_match.raw_score, + autocomplete_input_.type(), + match_type, match_number); + AutocompleteMatch match(this, score, !!info.visit_count(), + AutocompleteMatch::HISTORY_URL); + match.destination_url = info.url(); + DCHECK(match.destination_url.is_valid()); + size_t inline_autocomplete_offset = + history_match.input_location + autocomplete_input_.text().length(); + const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & + ~((trim_http_ && !history_match.match_in_scheme) ? + 0 : net::kFormatUrlOmitHTTP); + std::string languages = + match_type == WHAT_YOU_TYPED ? std::string() : languages_; + match.fill_into_edit = + AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(), + UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, + UnescapeRule::SPACES, NULL, NULL, + &inline_autocomplete_offset))); + if (!autocomplete_input_.prevent_inline_autocomplete()) + match.inline_autocomplete_offset = inline_autocomplete_offset; + DCHECK((match.inline_autocomplete_offset == std::wstring::npos) || + (match.inline_autocomplete_offset <= match.fill_into_edit.length())); + + size_t match_start = history_match.input_location; + match.contents = + UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, + UnescapeRule::SPACES, NULL, NULL, + &match_start)); + if ((match_start != std::wstring::npos) && + (inline_autocomplete_offset != std::wstring::npos) && + (inline_autocomplete_offset != match_start)) { + DCHECK(inline_autocomplete_offset > match_start); + AutocompleteMatch::ClassifyLocationInString(match_start, + inline_autocomplete_offset - match_start, match.contents.length(), + ACMatchClassification::URL, &match.contents_class); + } else { + AutocompleteMatch::ClassifyLocationInString(std::wstring::npos, 0, + match.contents.length(), ACMatchClassification::URL, + &match.contents_class); + } + match.description = UTF16ToWide(info.title()); + AutocompleteMatch::ClassifyMatchInString(autocomplete_input_.text(), + UTF16ToWide(info.title()), + ACMatchClassification::NONE, + &match.description_class); + + return match; } + +history::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { + if (index_for_testing_.get()) + return index_for_testing_.get(); + + HistoryService* const history_service = + profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!history_service) + return NULL; + + return history_service->InMemoryIndex(); +} + +void HistoryQuickProvider::SetIndexForTesting( + history::InMemoryURLIndex* index) { + DCHECK(index); + index_for_testing_.reset(index); +} + +// Utility Functions + +history::InMemoryURLIndex::String16Vector + HistoryQuickProvider::WordVectorFromString16(const string16& uni_string) { + history::InMemoryURLIndex::String16Vector words; + WordIterator iter(&uni_string, WordIterator::BREAK_WORD); + if (iter.Init()) { + while (iter.Advance()) { + if (iter.IsWord()) + words.push_back(iter.GetWord()); + } + } + return words; +} + +// static +int HistoryQuickProvider::CalculateRelevance(int raw_score, + AutocompleteInput::Type input_type, + MatchType match_type, + size_t match_number) { + switch (match_type) { + case INLINE_AUTOCOMPLETE: + return 1400; + + case WHAT_YOU_TYPED: + return 1200; + + default: + return 900 + static_cast<int>(match_number); + } +} + diff --git a/chrome/browser/autocomplete/history_quick_provider.h b/chrome/browser/autocomplete/history_quick_provider.h index 5d4a577..b86ca8c 100644 --- a/chrome/browser/autocomplete/history_quick_provider.h +++ b/chrome/browser/autocomplete/history_quick_provider.h @@ -6,7 +6,17 @@ #define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_QUICK_PROVIDER_H_ #pragma once -#include "chrome/browser/autocomplete/autocomplete.h" +#include <string> + +#include "chrome/browser/autocomplete/history_provider.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/browser/history/in_memory_url_index.h" + +class Profile; + +namespace history { +class HistoryBackend; +} // namespace history // This class is an autocomplete provider (a pseudo-internal component of // the history system) which quickly (and synchronously) provides matching @@ -15,26 +25,52 @@ // // TODO(mrossetti): Review to see if the following applies since we're not // using the database during the autocomplete pass. -// -// 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. -class HistoryQuickProvider : public AutocompleteProvider { +class HistoryQuickProvider : public HistoryProvider { public: - HistoryQuickProvider(ACProviderListener* listener, Profile* profile) - : AutocompleteProvider(listener, profile, "HistoryQuickProvider") {} + HistoryQuickProvider(ACProviderListener* listener, Profile* profile); - // no destructor (see note above) + ~HistoryQuickProvider(); - // AutocompleteProvider + // AutocompleteProvider. |minimal_changes| is ignored since there + // is no asynch completion performed. void Start(const AutocompleteInput& input, bool minimal_changes); + // Performs the autocomplete matching and scoring. + void DoAutocomplete(); + private: - ~HistoryQuickProvider() {} + friend class HistoryQuickProviderTest; + + AutocompleteMatch QuickMatchToACMatch( + const history::ScoredHistoryMatch& history_match, + MatchType match_type, + size_t match_number); + + // Breaks a string down into individual words and return as a vector with + // the individual words in their original order. + static history::InMemoryURLIndex::String16Vector WordVectorFromString16( + const string16& uni_string); + + // Determines the relevance for some input, given its type and which match it + // is. If |match_type| is NORMAL, |match_number| is a number + // [0, kMaxSuggestions) indicating the relevance of the match (higher == more + // relevant). For other values of |match_type|, |match_number| is ignored. + static int CalculateRelevance(int raw_score, + AutocompleteInput::Type input_type, + MatchType match_type, + size_t match_number); + + // Returns the index that should be used for history lookups. + history::InMemoryURLIndex* GetIndex(); + + // Only for use in unittests. Takes ownership of |index|. + void SetIndexForTesting(history::InMemoryURLIndex* index); + AutocompleteInput autocomplete_input_; + bool trim_http_; + std::string languages_; + + // Only used for testing. + scoped_ptr<history::InMemoryURLIndex> index_for_testing_; }; #endif // CHROME_BROWSER_AUTOCOMPLETE_HISTORY_QUICK_PROVIDER_H_ diff --git a/chrome/browser/autocomplete/history_quick_provider_unittest.cc b/chrome/browser/autocomplete/history_quick_provider_unittest.cc index 24ed677..760ad12 100644 --- a/chrome/browser/autocomplete/history_quick_provider_unittest.cc +++ b/chrome/browser/autocomplete/history_quick_provider_unittest.cc @@ -4,32 +4,233 @@ #include "chrome/browser/autocomplete/history_quick_provider.h" +#include <algorithm> +#include <functional> +#include <set> +#include <string> +#include <vector> + +#include "base/message_loop.h" #include "base/scoped_ptr.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/history/url_database.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/pref_names.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" +using base::Time; +using base::TimeDelta; + +struct TestURLInfo { + std::string url; + std::string title; + int visit_count; + int typed_count; + int days_from_now; +} quick_test_db[] = { + {"http://www.google.com/", "Google", 3, 3, 0}, + {"http://slashdot.org/favorite_page.html", "Favorite page", 200, 100, 0}, + {"http://kerneltrap.org/not_very_popular.html", "Less popular", 4, 0, 0}, + {"http://freshmeat.net/unpopular.html", "Unpopular", 1, 1, 0}, + {"http://news.google.com/?ned=us&topic=n", "Google News - U.S.", 2, 2, 0}, + {"http://news.google.com/", "Google News", 1, 1, 0}, + {"http://foo.com/", "Dir", 5, 5, 0}, + {"http://foo.com/dir/", "Dir", 2, 2, 0}, + {"http://foo.com/dir/another/", "Dir", 5, 1, 0}, + {"http://foo.com/dir/another/again/", "Dir", 10, 0, 0}, + {"http://foo.com/dir/another/again/myfile.html", "File", 10, 2, 0}, + {"http://startest.com/y/a", "A", 5, 2, 0}, + {"http://startest.com/y/b", "B", 1, 2, 0}, + {"http://startest.com/x/c", "C", 1, 1, 1}, + {"http://startest.com/x/d", "D", 1, 1, 1}, + {"http://startest.com/y/e", "E", 1, 1, 2}, + {"http://startest.com/y/f", "F", 1, 1, 2}, + {"http://startest.com/y/g", "G", 1, 1, 3}, + {"http://startest.com/y/h", "H", 1, 1, 3}, + {"http://startest.com/y/i", "I", 1, 1, 4}, + {"http://startest.com/y/j", "J", 1, 1, 4}, + {"http://startest.com/y/k", "K", 1, 1, 5}, + {"http://startest.com/y/l", "L", 1, 1, 5}, + {"http://startest.com/y/m", "M", 1, 1, 6}, + {"http://abcdefghixyzjklmnopqrstuvw.com/a", "An XYZ", 1, 1, 0}, + {"http://spaces.com/path%20with%20spaces/foo.html", "Spaces", 2, 2, 0}, + {"http://abcdefghijklxyzmnopqrstuvw.com/a", "An XYZ", 1, 1, 0}, + {"http://abcdefxyzghijklmnopqrstuvw.com/a", "An XYZ", 1, 1, 0}, + {"http://abcxyzdefghijklmnopqrstuvw.com/a", "An XYZ", 1, 1, 0}, + {"http://xyzabcdefghijklmnopqrstuvw.com/a", "An XYZ", 1, 1, 0}, +}; + class HistoryQuickProviderTest : public testing::Test, public ACProviderListener { public: + HistoryQuickProviderTest() + : ui_thread_(ChromeThread::UI, &message_loop_), + file_thread_(ChromeThread::FILE, &message_loop_) {} + // ACProviderListener virtual void OnProviderUpdate(bool updated_matches); protected: void SetUp() { profile_.reset(new TestingProfile()); + profile_->CreateHistoryService(true, false); + profile_->CreateBookmarkModel(true); + profile_->BlockUntilBookmarkModelLoaded(); + history_service_ = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + EXPECT_TRUE(history_service_); provider_ = new HistoryQuickProvider(this, profile_.get()); + FillData(); } + void TearDown() { provider_ = NULL; } - scoped_refptr<HistoryQuickProvider> provider_; + // Fills test data into the history system. + void FillData(); + + // Runs an autocomplete query on |text| and checks to see that the returned + // results' destination URLs match those provided. |expected_urls| does not + // need to be in sorted order. + void RunTest(const std::wstring text, + std::vector<std::string> expected_urls, + std::string expected_top_result); + + MessageLoopForUI message_loop_; + ChromeThread ui_thread_; + ChromeThread file_thread_; + scoped_ptr<TestingProfile> profile_; + HistoryService* history_service_; + + private: + scoped_refptr<HistoryQuickProvider> provider_; }; void HistoryQuickProviderTest::OnProviderUpdate(bool updated_matches) { + MessageLoop::current()->Quit(); +} + +void HistoryQuickProviderTest::FillData() { + history::URLDatabase* db = history_service_->InMemoryDatabase(); + ASSERT_TRUE(db != NULL); + for (size_t i = 0; i < arraysize(quick_test_db); ++i) { + const TestURLInfo& cur = quick_test_db[i]; + const GURL current_url(cur.url); + Time visit_time = Time::Now() - TimeDelta::FromDays(cur.days_from_now); + + history::URLRow url_info(current_url); + url_info.set_title(UTF8ToUTF16(cur.title)); + url_info.set_visit_count(cur.visit_count); + url_info.set_typed_count(cur.typed_count); + url_info.set_last_visit(visit_time); + url_info.set_hidden(false); + EXPECT_TRUE(db->AddURL(url_info)); + + history_service_->AddPageWithDetails(current_url, UTF8ToUTF16(cur.title), + cur.visit_count, cur.typed_count, + visit_time, false, + history::SOURCE_BROWSED); + } + + history::InMemoryURLIndex* index = new history::InMemoryURLIndex(); + PrefService* prefs = profile_->GetPrefs(); + std::string languages(prefs->GetString(prefs::kAcceptLanguages)); + index->Init(db, languages); + provider_->SetIndexForTesting(index); +} + +class SetShouldContain : public std::unary_function<const std::string&, + std::set<std::string> > { + public: + explicit SetShouldContain(const ACMatches& matched_urls) { + for (ACMatches::const_iterator iter = matched_urls.begin(); + iter != matched_urls.end(); ++iter) + matches_.insert(iter->destination_url.spec()); + } + + void operator()(const std::string& expected) { + EXPECT_EQ(1U, matches_.erase(expected)); + } + + std::set<std::string> LeftOvers() const { return matches_; } + + private: + std::set<std::string> matches_; +}; + +void HistoryQuickProviderTest::RunTest(const std::wstring text, + std::vector<std::string> expected_urls, + std::string expected_top_result) { + std::sort(expected_urls.begin(), expected_urls.end()); + + MessageLoop::current()->RunAllPending(); + AutocompleteInput input(text, std::wstring(), false, false, false); + provider_->Start(input, false); + EXPECT_TRUE(provider_->done()); + + ACMatches matches = provider_->matches(); + // If the number of expected and actual matches aren't equal then we need + // test no further, but let's do anyway so that we know which URLs failed. + EXPECT_EQ(expected_urls.size(), matches.size()); + + // Verify that all expected URLs were found and that all found URLs + // were expected. + std::set<std::string> leftovers = + for_each(expected_urls.begin(), expected_urls.end(), + SetShouldContain(matches)).LeftOvers(); + EXPECT_TRUE(leftovers.empty()); + + // See if we got the expected top scorer. + if (!matches.empty()) { + std::partial_sort(matches.begin(), matches.begin() + 1, + matches.end(), AutocompleteMatch::MoreRelevant); + EXPECT_EQ(expected_top_result, matches[0].destination_url.spec()); + } +} + +TEST_F(HistoryQuickProviderTest, SimpleSingleMatch) { + std::wstring text(L"slashdot"); + std::string expected_url("http://slashdot.org/favorite_page.html"); + std::vector<std::string> expected_urls; + expected_urls.push_back(expected_url); + RunTest(text, expected_urls, expected_url); +} + +TEST_F(HistoryQuickProviderTest, MultiMatch) { + std::wstring text(L"foo"); + std::vector<std::string> expected_urls; + expected_urls.push_back("http://foo.com/"); + expected_urls.push_back("http://foo.com/dir/"); + expected_urls.push_back("http://foo.com/dir/another/"); + expected_urls.push_back("http://foo.com/dir/another/again/"); + expected_urls.push_back("http://foo.com/dir/another/again/myfile.html"); + expected_urls.push_back("http://spaces.com/path%20with%20spaces/foo.html"); + RunTest(text, expected_urls, "http://foo.com/"); +} + +TEST_F(HistoryQuickProviderTest, StartRelativeMatch) { + std::wstring text(L"xyz"); + std::vector<std::string> expected_urls; + expected_urls.push_back("http://xyzabcdefghijklmnopqrstuvw.com/a"); + expected_urls.push_back("http://abcxyzdefghijklmnopqrstuvw.com/a"); + expected_urls.push_back("http://abcdefxyzghijklmnopqrstuvw.com/a"); + expected_urls.push_back("http://abcdefghixyzjklmnopqrstuvw.com/a"); + expected_urls.push_back("http://abcdefghijklxyzmnopqrstuvw.com/a"); + RunTest(text, expected_urls, "http://xyzabcdefghijklmnopqrstuvw.com/a"); } -TEST_F(HistoryQuickProviderTest, Construction) { - EXPECT_TRUE(provider_.get()); +TEST_F(HistoryQuickProviderTest, RecencyMatch) { + std::wstring text(L"startest"); + std::vector<std::string> expected_urls; + expected_urls.push_back("http://startest.com/y/a"); + expected_urls.push_back("http://startest.com/y/b"); + expected_urls.push_back("http://startest.com/x/c"); + expected_urls.push_back("http://startest.com/x/d"); + expected_urls.push_back("http://startest.com/y/e"); + expected_urls.push_back("http://startest.com/y/f"); + RunTest(text, expected_urls, "http://startest.com/y/a"); } diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc index 9dab45d..234bed4 100644 --- a/chrome/browser/autocomplete/history_url_provider.cc +++ b/chrome/browser/autocomplete/history_url_provider.cc @@ -104,7 +104,7 @@ GURL ConvertToHostOnly(const HistoryMatch& match, const std::wstring& input) { HistoryURLProviderParams::HistoryURLProviderParams( const AutocompleteInput& input, bool trim_http, - const std::wstring& languages) + const std::string& languages) : message_loop(MessageLoop::current()), input(input), trim_http(trim_http), @@ -115,7 +115,7 @@ HistoryURLProviderParams::HistoryURLProviderParams( HistoryURLProvider::HistoryURLProvider(ACProviderListener* listener, Profile* profile) - : AutocompleteProvider(listener, profile, "HistoryURL"), + : HistoryProvider(listener, profile, "HistoryURL"), prefixes_(GetPrefixes()), params_(NULL) { } @@ -457,91 +457,6 @@ bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( } // static -std::wstring HistoryURLProvider::FixupUserInput( - const AutocompleteInput& input) { - const std::wstring& input_text = input.text(); - // Fixup and canonicalize user input. - const GURL canonical_gurl(URLFixerUpper::FixupURL(WideToUTF8(input_text), - std::string())); - std::string canonical_gurl_str(canonical_gurl.possibly_invalid_spec()); - if (canonical_gurl_str.empty()) { - // This probably won't happen, but there are no guarantees. - return input_text; - } - - // If the user types a number, GURL will convert it to a dotted quad. - // However, if the parser did not mark this as a URL, then the user probably - // didn't intend this interpretation. Since this can break history matching - // for hostname beginning with numbers (e.g. input of "17173" will be matched - // against "0.0.67.21" instead of the original "17173", failing to find - // "17173.com"), swap the original hostname in for the fixed-up one. - if ((input.type() != AutocompleteInput::URL) && - canonical_gurl.HostIsIPAddress()) { - std::string original_hostname = - WideToUTF8(input_text.substr(input.parts().host.begin, - input.parts().host.len)); - const url_parse::Parsed& parts = - canonical_gurl.parsed_for_possibly_invalid_spec(); - // parts.host must not be empty when HostIsIPAddress() is true. - DCHECK(parts.host.is_nonempty()); - canonical_gurl_str.replace(parts.host.begin, parts.host.len, - original_hostname); - } - std::wstring output(UTF8ToWide(canonical_gurl_str)); - // Don't prepend a scheme when the user didn't have one. Since the fixer - // upper only prepends the "http" scheme, that's all we need to check for. - if (canonical_gurl.SchemeIs(chrome::kHttpScheme) && - !url_util::FindAndCompareScheme(WideToUTF8(input_text), - chrome::kHttpScheme, NULL)) - TrimHttpPrefix(&output); - - // Make the number of trailing slashes on the output exactly match the input. - // Examples of why not doing this would matter: - // * The user types "a" and has this fixed up to "a/". Now no other sites - // beginning with "a" will match. - // * The user types "file:" and has this fixed up to "file://". Now inline - // autocomplete will append too few slashes, resulting in e.g. "file:/b..." - // instead of "file:///b..." - // * The user types "http:/" and has this fixed up to "http:". Now inline - // autocomplete will append too many slashes, resulting in e.g. - // "http:///c..." instead of "http://c...". - // NOTE: We do this after calling TrimHttpPrefix() since that can strip - // trailing slashes (if the scheme is the only thing in the input). It's not - // clear that the result of fixup really matters in this case, but there's no - // harm in making sure. - const size_t last_input_nonslash = input_text.find_last_not_of(L"/\\"); - const size_t num_input_slashes = (last_input_nonslash == std::wstring::npos) ? - input_text.length() : (input_text.length() - 1 - last_input_nonslash); - const size_t last_output_nonslash = output.find_last_not_of(L"/\\"); - const size_t num_output_slashes = - (last_output_nonslash == std::wstring::npos) ? - output.length() : (output.length() - 1 - last_output_nonslash); - if (num_output_slashes < num_input_slashes) - output.append(num_input_slashes - num_output_slashes, '/'); - else if (num_output_slashes > num_input_slashes) - output.erase(output.length() - num_output_slashes + num_input_slashes); - - return output; -} - -// static -size_t HistoryURLProvider::TrimHttpPrefix(std::wstring* url) { - // Find any "http:". - if (!HasHTTPScheme(*url)) - return 0; - size_t scheme_pos = url->find(ASCIIToWide(chrome::kHttpScheme) + L":"); - DCHECK(scheme_pos != std::wstring::npos); - - // Erase scheme plus up to two slashes. - size_t prefix_end = scheme_pos + strlen(chrome::kHttpScheme) + 1; - const size_t after_slashes = std::min(url->length(), prefix_end + 2); - while ((prefix_end < after_slashes) && ((*url)[prefix_end] == L'/')) - ++prefix_end; - url->erase(scheme_pos, prefix_end - scheme_pos); - return (scheme_pos == 0) ? prefix_end : 0; -} - -// static history::Prefixes HistoryURLProvider::GetPrefixes() { // We'll complete text following these prefixes. // NOTE: There's no requirement that these be in any particular order. @@ -696,10 +611,10 @@ void HistoryURLProvider::RunAutocompletePasses( // 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. - std::wstring languages(languages_); + std::string languages(languages_); if (languages.empty() && profile_) { languages = - UTF8ToWide(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); } scoped_ptr<HistoryURLProviderParams> params( new HistoryURLProviderParams(input, trim_http, languages)); @@ -888,7 +803,7 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( size_t inline_autocomplete_offset = history_match.input_location + params->input.text().length(); std::string languages = (match_type == WHAT_YOU_TYPED) ? - std::string() : WideToUTF8(params->languages); + std::string() : params->languages; const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & ~((params->trim_http && !history_match.match_in_scheme) ? 0 : net::kFormatUrlOmitHTTP); diff --git a/chrome/browser/autocomplete/history_url_provider.h b/chrome/browser/autocomplete/history_url_provider.h index 1a6c6f0..16b0346 100644 --- a/chrome/browser/autocomplete/history_url_provider.h +++ b/chrome/browser/autocomplete/history_url_provider.h @@ -6,7 +6,9 @@ #define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_URL_PROVIDER_H_ #pragma once -#include "chrome/browser/autocomplete/autocomplete.h" +#include <string> + +#include "chrome/browser/autocomplete/history_provider.h" #include "chrome/browser/autocomplete/history_provider_util.h" class MessageLoop; @@ -83,7 +85,7 @@ class URLRow; struct HistoryURLProviderParams { HistoryURLProviderParams(const AutocompleteInput& input, bool trim_http, - const std::wstring& languages); + const std::string& languages); MessageLoop* message_loop; @@ -115,7 +117,7 @@ struct HistoryURLProviderParams { ACMatches matches; // Languages we should pass to gfx::GetCleanStringFromUrl. - std::wstring languages; + std::string languages; private: DISALLOW_COPY_AND_ASSIGN(HistoryURLProviderParams); @@ -131,15 +133,15 @@ struct HistoryURLProviderParams { // 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. -class HistoryURLProvider : public AutocompleteProvider { +class HistoryURLProvider : public HistoryProvider { public: HistoryURLProvider(ACProviderListener* listener, Profile* profile); #ifdef UNIT_TEST HistoryURLProvider(ACProviderListener* listener, Profile* profile, - const std::wstring& languages) - : AutocompleteProvider(listener, profile, "History"), + const std::string& languages) + : HistoryProvider(listener, profile, "History"), prefixes_(GetPrefixes()), params_(NULL), languages_(languages) {} @@ -174,31 +176,6 @@ class HistoryURLProvider : public AutocompleteProvider { private: ~HistoryURLProvider() {} - - enum MatchType { - NORMAL, - WHAT_YOU_TYPED, - INLINE_AUTOCOMPLETE - }; - - // Fixes up user URL input to make it more possible to match against. Among - // many other things, this takes care of the following: - // * Prepending file:// to file URLs - // * Converting drive letters in file URLs to uppercase - // * Converting case-insensitive parts of URLs (like the scheme and domain) - // to lowercase - // * Convert spaces to %20s - // Note that we don't do this in AutocompleteInput's constructor, because if - // e.g. we convert a Unicode hostname to punycode, other providers will show - // output that surprises the user ("Search Google for xn--6ca.com"). - static std::wstring FixupUserInput(const AutocompleteInput& input); - - // Trims "http:" and up to two subsequent slashes from |url|. Returns the - // number of characters that were trimmed. - // NOTE: For a view-source: URL, this will trim from after "view-source:" and - // return 0. - static size_t TrimHttpPrefix(std::wstring* url); - // Returns the set of prefixes to use for prefixes_. static history::Prefixes GetPrefixes(); @@ -320,7 +297,7 @@ class HistoryURLProvider : public AutocompleteProvider { // Only used by unittests; if non-empty, overrides accept-languages in the // profile's pref system. - std::wstring languages_; + std::string languages_; }; #endif // CHROME_BROWSER_AUTOCOMPLETE_HISTORY_URL_PROVIDER_H_ diff --git a/chrome/browser/autocomplete/history_url_provider_unittest.cc b/chrome/browser/autocomplete/history_url_provider_unittest.cc index 0bc080d..17ce1c7 100644 --- a/chrome/browser/autocomplete/history_url_provider_unittest.cc +++ b/chrome/browser/autocomplete/history_url_provider_unittest.cc @@ -153,7 +153,7 @@ void HistoryURLProviderTest::SetUpImpl(bool no_db) { profile_->CreateHistoryService(true, no_db); history_service_ = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - autocomplete_ = new HistoryURLProvider(this, profile_.get(), L"en-US,en,ko"); + autocomplete_ = new HistoryURLProvider(this, profile_.get(), "en-US,en,ko"); FillData(); } diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc index db4ebf8..2f20683 100644 --- a/chrome/browser/history/history.cc +++ b/chrome/browser/history/history.cc @@ -42,10 +42,12 @@ #include "chrome/browser/history/in_memory_database.h" #include "chrome/browser/history/in_memory_history_backend.h" #include "chrome/browser/history/top_sites.h" +#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/visitedlink_master.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" #include "chrome/common/thumbnail_score.h" #include "chrome/common/url_constants.h" #include "grit/chromium_strings.h" @@ -228,7 +230,7 @@ history::InMemoryURLIndex* HistoryService::InMemoryIndex() { // for this call. LoadBackendIfNecessary(); if (in_memory_backend_.get()) - return in_memory_backend_->index(); + return in_memory_backend_->InMemoryIndex(); return NULL; } @@ -753,7 +755,13 @@ void HistoryService::LoadBackendIfNecessary() { bookmark_service_)); history_backend_.swap(backend); - ScheduleAndForget(PRIORITY_UI, &HistoryBackend::Init, no_db_); + // There may not be a profile when unit testing. + std::string languages; + if (profile_) { + PrefService* prefs = profile_->GetPrefs(); + languages = prefs->GetString(prefs::kAcceptLanguages); + } + ScheduleAndForget(PRIORITY_UI, &HistoryBackend::Init, languages, no_db_); } void HistoryService::OnDBLoaded() { diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h index 3d24981..83e629e 100644 --- a/chrome/browser/history/history.h +++ b/chrome/browser/history/history.h @@ -150,6 +150,7 @@ class HistoryService : public CancelableRequestProvider, // TODO(brettw) this should return the InMemoryHistoryBackend. history::URLDatabase* InMemoryDatabase(); + // Return the quick history index. history::InMemoryURLIndex* InMemoryIndex(); // Navigation ---------------------------------------------------------------- diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 237b14b..286ddb5 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -239,9 +239,9 @@ HistoryBackend::~HistoryBackend() { } } -void HistoryBackend::Init(bool force_fail) { +void HistoryBackend::Init(const std::string& languages, bool force_fail) { if (!force_fail) - InitImpl(); + InitImpl(languages); delegate_->DBLoaded(); } @@ -509,7 +509,7 @@ void HistoryBackend::AddPage(scoped_refptr<HistoryAddPageArgs> request) { ScheduleCommit(); } -void HistoryBackend::InitImpl() { +void HistoryBackend::InitImpl(const std::string& languages) { DCHECK(!db_.get()) << "Initializing HistoryBackend twice"; // In the rare case where the db fails to initialize a dialog may get shown // the blocks the caller, yet allows other messages through. For this reason @@ -548,7 +548,7 @@ void HistoryBackend::InitImpl() { // Fill the in-memory database and send it back to the history service on the // main thread. InMemoryHistoryBackend* mem_backend = new InMemoryHistoryBackend; - if (mem_backend->Init(history_name, db_.get())) + if (mem_backend->Init(history_name, db_.get(), languages)) delegate_->SetInMemoryBackend(mem_backend); // Takes ownership of pointer. else delete mem_backend; // Error case, run without the in-memory DB. diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index f3e76cf..3a5cea3 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_ #pragma once +#include <string> #include <utility> #include "base/file_path.h" @@ -103,8 +104,10 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, // fails, all other functions will fail as well. (Since this runs on another // thread, we don't bother returning failure.) // + // |languages| gives a list of language encodings with which the history + // URLs and omnibox searches are interpreted. // |force_fail| can be set during unittests to unconditionally fail to init. - void Init(bool force_fail); + void Init(const std::string& languages, bool force_fail); // Notification that the history system is shutting down. This will break // the refs owned by the delegate and any pending transaction so it will @@ -337,7 +340,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, friend class URLQuerier; // Does the work of Init. - void InitImpl(); + void InitImpl(const std::string& languages); // Adds a single visit to the database, updating the URL information such // as visit and typed count. The visit ID of the added visit and the URL ID diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index 907b7b6..70760bd 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc @@ -136,7 +136,7 @@ class HistoryBackendTest : public testing::Test { backend_ = new HistoryBackend(test_dir_, new HistoryBackendTestDelegate(this), &bookmark_model_); - backend_->Init(false); + backend_->Init(std::string(), false); } virtual void TearDown() { backend_->Closing(); @@ -810,7 +810,7 @@ TEST_F(HistoryBackendTest, MigrationVisitSource) { backend_ = new HistoryBackend(new_history_path, new HistoryBackendTestDelegate(this), &bookmark_model_); - backend_->Init(false); + backend_->Init(std::string(), false); // Now the database should already be migrated. // Check version first. diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc index 46adb45..1cc560e 100644 --- a/chrome/browser/history/history_unittest.cc +++ b/chrome/browser/history/history_unittest.cc @@ -130,7 +130,7 @@ class HistoryTest : public testing::Test { void CreateBackendAndDatabase() { backend_ = new HistoryBackend(history_dir_, new BackendDelegate(this), NULL); - backend_->Init(false); + backend_->Init(std::string(), false); db_ = backend_->db_.get(); DCHECK(in_mem_backend_.get()) << "Mem backend should have been set by " "HistoryBackend::Init"; diff --git a/chrome/browser/history/in_memory_history_backend.cc b/chrome/browser/history/in_memory_history_backend.cc index b3d5da9..6dedaf6 100644 --- a/chrome/browser/history/in_memory_history_backend.cc +++ b/chrome/browser/history/in_memory_history_backend.cc @@ -33,20 +33,18 @@ InMemoryHistoryBackend::~InMemoryHistoryBackend() { } bool InMemoryHistoryBackend::Init(const FilePath& history_filename, - URLDatabase* db) { + URLDatabase* db, + const std::string& languages) { db_.reset(new InMemoryDatabase); bool success = db_->InitFromDisk(history_filename); - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableInMemoryURLIndex)) { + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableHistoryQuickProvider)) { index_.reset(new InMemoryURLIndex()); base::TimeTicks beginning_time = base::TimeTicks::Now(); - // TODO(mrossetti): Provide languages when profile is available. - index_->Init(db, std::string()); + index_->Init(db, languages); UMA_HISTOGRAM_TIMES("Autocomplete.HistoryDatabaseIndexingTime", base::TimeTicks::Now() - beginning_time); } - return success; } diff --git a/chrome/browser/history/in_memory_history_backend.h b/chrome/browser/history/in_memory_history_backend.h index bfa51d8..4fdc3a5 100644 --- a/chrome/browser/history/in_memory_history_backend.h +++ b/chrome/browser/history/in_memory_history_backend.h @@ -14,6 +14,8 @@ #define CHROME_BROWSER_HISTORY_IN_MEMORY_HISTORY_BACKEND_H_ #pragma once +#include <string> + #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" @@ -38,7 +40,9 @@ class InMemoryHistoryBackend : public NotificationObserver { ~InMemoryHistoryBackend(); // Initializes with data from the given history database. - bool Init(const FilePath& history_filename, URLDatabase* db); + bool Init(const FilePath& history_filename, + URLDatabase* db, + const std::string& languages); // Does initialization work when this object is attached to the history // system on the main thread. The argument is the profile with which the @@ -52,17 +56,14 @@ class InMemoryHistoryBackend : public NotificationObserver { return db_.get(); } - // Returns the in memory index owned by this backend. This index is only - // loaded when the --enable-in-memory-url-index flag is used. - InMemoryURLIndex* index() const { - return index_.get(); - } - // Notification callback. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); + // Return the quick history index. + history::InMemoryURLIndex* InMemoryIndex() const { return index_.get(); } + private: FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAll); @@ -76,12 +77,13 @@ class InMemoryHistoryBackend : public NotificationObserver { scoped_ptr<InMemoryDatabase> db_; - scoped_ptr<InMemoryURLIndex> index_; - // The profile that this object is attached. May be NULL before // initialization. Profile* profile_; + // The index used for quick history lookups. + scoped_ptr<history::InMemoryURLIndex> index_; + DISALLOW_COPY_AND_ASSIGN(InMemoryHistoryBackend); }; diff --git a/chrome/browser/history/in_memory_url_index.cc b/chrome/browser/history/in_memory_url_index.cc index 95afa57..ea76e59 100644 --- a/chrome/browser/history/in_memory_url_index.cc +++ b/chrome/browser/history/in_memory_url_index.cc @@ -438,14 +438,23 @@ int InMemoryURLIndex::RawScoreForURL(const URLRow& row, (static_cast<float>(std::min(row.visit_count(), kMaxSignificantVisits))) / static_cast<float>(kMaxSignificantVisits) * kVisitCountMaxValue; + + const float kTypedCountMaxValue = 20.0; + const int kMaxSignificantTyped = 10; + float typed_count_value = + (static_cast<float>(std::min(row.typed_count(), + kMaxSignificantTyped))) / static_cast<float>(kMaxSignificantTyped) * + kTypedCountMaxValue; + float raw_score = order_value + start_value + complete_value + - last_visit_value + visit_count_value; + last_visit_value + visit_count_value + typed_count_value; // Normalize the score. const float kMaxNormalizedRawScore = 1000.0; raw_score = (raw_score / (kOrderMaxValue + kStartMaxValue + kCompleteMaxValue + - kLastVisitMaxValue + kVisitCountMaxValue)) * + kLastVisitMaxValue + kVisitCountMaxValue + + kTypedCountMaxValue)) * kMaxNormalizedRawScore; return static_cast<int>(raw_score); } diff --git a/chrome/browser/history/in_memory_url_index.h b/chrome/browser/history/in_memory_url_index.h index b5b3373..8008a74 100644 --- a/chrome/browser/history/in_memory_url_index.h +++ b/chrome/browser/history/in_memory_url_index.h @@ -74,6 +74,9 @@ class InMemoryURLIndex { typedef std::vector<string16> String16Vector; // Open and index the URL history database. + // |languages| gives a list of language encodings with which the history + // URLs and omnibox searches are interpreted, i.e. when each is broken + // down into words and each word is broken down into characters. bool Init(URLDatabase* history_db, const std::string& languages); // Reset the history index. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 55ba15f..e5216a0 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -117,6 +117,8 @@ 'browser/autocomplete/autocomplete_popup_view_mac.mm', 'browser/autocomplete/history_contents_provider.cc', 'browser/autocomplete/history_contents_provider.h', + 'browser/autocomplete/history_provider.cc', + 'browser/autocomplete/history_provider.h', 'browser/autocomplete/history_provider_util.cc', 'browser/autocomplete/history_provider_util.h', 'browser/autocomplete/history_quick_provider.cc', diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 394160b..3e9b867 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -206,6 +206,12 @@ const char kDisableGLSLTranslator[] = "disable-glsl-translator"; // Manager can be used to terminate the offending process in this case. const char kDisableHangMonitor[] = "disable-hang-monitor"; +// Disable the use of the HistoryQuickProvider for autocomplete results. +const char kDisableHistoryQuickProvider[] = "disable-history-quick-provider"; + +// Disable the use of the HistoryURLProvider for autocomplete results. +const char kDisableHistoryURLProvider[] = "disable-history-url-provider"; + // Disable the Indexed Database API. const char kDisableIndexedDatabase[] = "disable-indexed-database"; @@ -427,10 +433,6 @@ const char kEnableFileCookies[] = "enable-file-cookies"; // Enable the FileSystem API. const char kEnableFileSystem[] = "enable-file-system"; -// Use the InMemoryURLIndex to back the HistoryURLProvider for autocomplete -// results. If not set, defaults to using the InMemoryDatabase. -const char kEnableInMemoryURLIndex[] = "enable-in-memory-url-index"; - // Enable IPv6 support, even if probes suggest that it may not be fully // supported. Some probes may require internet connections, and this flag will // allow support independent of application testing. diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 91aa5fa..1a33d78 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -70,6 +70,8 @@ extern const char kDisableExtensionsFileAccessCheck[]; extern const char kDisableGeolocation[]; extern const char kDisableGLSLTranslator[]; extern const char kDisableHangMonitor[]; +extern const char kDisableHistoryQuickProvider[]; +extern const char kDisableHistoryURLProvider[]; extern const char kDisableInternalFlash[]; extern const char kDisableIndexedDatabase[]; extern const char kDisableIPv6[]; @@ -134,7 +136,6 @@ extern const char kEnableFileCookies[]; extern const char kEnableFileSystem[]; extern const char kEnableGPUPlugin[]; extern const char kEnableGPURendering[]; -extern const char kEnableInMemoryURLIndex[]; extern const char kEnableIPv6[]; extern const char kEnableLogging[]; extern const char kEnableMatchPreview[]; |