summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-12 17:31:23 +0000
committermrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-12 17:31:23 +0000
commit497606bc48a31173166147910fdd225533aeca60 (patch)
tree543f2a9c9a918f7330588c27afe8fec263706113 /chrome
parentb6842d34c371f7ff7d8e6d033524903ea7f64dc8 (diff)
downloadchromium_src-497606bc48a31173166147910fdd225533aeca60.zip
chromium_src-497606bc48a31173166147910fdd225533aeca60.tar.gz
chromium_src-497606bc48a31173166147910fdd225533aeca60.tar.bz2
Final phase of the URL History Quick autocomplete provider integration. This phase hooks up the InMemoryURLIndex to the HistoryQuickProvider which is itself made active during the autocomplete process. A small amount of refactoring was done to liberate some common functionality from the history_url_provider.
Previous CL: http://codereview.chromium.org/3375002 BUG=23654,19736 TEST=Green bots. Start typing text which occurs in URLs which are in the history. Verify that those history items appear if they have been manually typed more than once or the have been visited more than three time or they have been visited within the last three days. Review URL: http://codereview.chromium.org/3713003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62298 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-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..55c8c56 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, 4},
+ {"http://startest.com/y/h", "H", 1, 1, 4},
+ {"http://startest.com/y/i", "I", 1, 1, 5},
+ {"http://startest.com/y/j", "J", 1, 1, 5},
+ {"http://startest.com/y/k", "K", 1, 1, 6},
+ {"http://startest.com/y/l", "L", 1, 1, 6},
+ {"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 57b5829..f330798 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 fe58e0b..bc5db7d 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 59f2055..52e02c5 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[];