summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/autocomplete/autocomplete.cc7
-rw-r--r--chrome/browser/autocomplete/history_provider.cc103
-rw-r--r--chrome/browser/autocomplete/history_provider.h53
-rw-r--r--chrome/browser/autocomplete/history_quick_provider.cc188
-rw-r--r--chrome/browser/autocomplete/history_quick_provider.h66
-rw-r--r--chrome/browser/autocomplete/history_quick_provider_unittest.cc207
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc95
-rw-r--r--chrome/browser/autocomplete/history_url_provider.h41
-rw-r--r--chrome/browser/autocomplete/history_url_provider_unittest.cc2
-rw-r--r--chrome/browser/history/history.cc12
-rw-r--r--chrome/browser/history/history.h1
-rw-r--r--chrome/browser/history/history_backend.cc8
-rw-r--r--chrome/browser/history/history_backend.h7
-rw-r--r--chrome/browser/history/history_backend_unittest.cc4
-rw-r--r--chrome/browser/history/history_unittest.cc2
-rw-r--r--chrome/browser/history/in_memory_history_backend.cc12
-rw-r--r--chrome/browser/history/in_memory_history_backend.h20
-rw-r--r--chrome/browser/history/in_memory_url_index.cc13
-rw-r--r--chrome/browser/history/in_memory_url_index.h3
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/chrome_switches.cc10
-rw-r--r--chrome/common/chrome_switches.h3
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[];