summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormpearson@chromium.org <mpearson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 04:28:07 +0000
committermpearson@chromium.org <mpearson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 04:28:07 +0000
commitb3a84893aee323f458848fe2b28cc2d5a9aa8c97 (patch)
tree2a701266bbb440570fab09e828df3267647c853c /chrome
parent98e55e8c3281fbf5a18e99b48a1bd67428a0a8e5 (diff)
downloadchromium_src-b3a84893aee323f458848fe2b28cc2d5a9aa8c97.zip
chromium_src-b3a84893aee323f458848fe2b28cc2d5a9aa8c97.tar.gz
chromium_src-b3a84893aee323f458848fe2b28cc2d5a9aa8c97.tar.bz2
Omnibox: Make URLs of Bookmarks Searchable
In particular, this makes * BookmarkIndex index the URLs for bookmarks * BookmarkIndex search for matches (match positions) within those URLs * BookmarkProvider score based on both title and URL matches All these is guarded by a field trial, also added in this changelist. I added ample unit tests. I also verified this works by testing it interactively using a local variations server and --force-fieldtrials. BUG=157204 Review URL: https://codereview.chromium.org/184663002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265539 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/autocomplete/bookmark_provider.cc187
-rw-r--r--chrome/browser/autocomplete/bookmark_provider.h16
-rw-r--r--chrome/browser/autocomplete/bookmark_provider_unittest.cc73
-rw-r--r--chrome/browser/autocomplete/history_url_provider.cc3
-rw-r--r--chrome/browser/autocomplete/shortcuts_provider.cc17
-rw-r--r--chrome/browser/autocomplete/url_prefix.cc17
-rw-r--r--chrome/browser/autocomplete/url_prefix.h9
-rw-r--r--chrome/browser/bookmarks/DEPS1
-rw-r--r--chrome/browser/bookmarks/bookmark_codec_unittest.cc16
-rw-r--r--chrome/browser/bookmarks/bookmark_index.cc75
-rw-r--r--chrome/browser/bookmarks/bookmark_index.h48
-rw-r--r--chrome/browser/bookmarks/bookmark_index_unittest.cc232
-rw-r--r--chrome/browser/bookmarks/bookmark_model.cc26
-rw-r--r--chrome/browser/bookmarks/bookmark_model.h16
-rw-r--r--chrome/browser/bookmarks/bookmark_model_factory.cc4
-rw-r--r--chrome/browser/bookmarks/bookmark_model_unittest.cc2
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.cc34
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.h19
-rw-r--r--chrome/browser/bookmarks/bookmark_utils_unittest.cc16
-rw-r--r--chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc2
-rw-r--r--chrome/browser/history/expire_history_backend_unittest.cc2
-rw-r--r--chrome/browser/history/history_backend_unittest.cc2
-rw-r--r--chrome/browser/history/in_memory_url_index_types.h15
-rw-r--r--chrome/browser/history/scored_history_match.cc5
-rw-r--r--chrome/browser/history/url_database.cc2
-rw-r--r--chrome/browser/history/url_index_private_data.cc13
-rw-r--r--chrome/browser/importer/profile_writer_unittest.cc9
-rw-r--r--chrome/browser/omnibox/omnibox_field_trial.cc7
-rw-r--r--chrome/browser/omnibox/omnibox_field_trial.h12
-rw-r--r--chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc4
-rw-r--r--chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc2
-rw-r--r--chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc4
-rw-r--r--chrome/test/base/testing_profile.cc2
33 files changed, 614 insertions, 278 deletions
diff --git a/chrome/browser/autocomplete/bookmark_provider.cc b/chrome/browser/autocomplete/bookmark_provider.cc
index 07b80d9..de8ea9d 100644
--- a/chrome/browser/autocomplete/bookmark_provider.cc
+++ b/chrome/browser/autocomplete/bookmark_provider.cc
@@ -15,12 +15,13 @@
#include "chrome/browser/autocomplete/url_prefix.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "net/base/net_util.h"
-typedef std::vector<BookmarkTitleMatch> TitleMatches;
+typedef std::vector<BookmarkMatch> BookmarkMatches;
// BookmarkProvider ------------------------------------------------------------
@@ -29,7 +30,8 @@ BookmarkProvider::BookmarkProvider(
Profile* profile)
: AutocompleteProvider(listener, profile,
AutocompleteProvider::TYPE_BOOKMARK),
- bookmark_model_(NULL) {
+ bookmark_model_(NULL),
+ score_using_url_matches_(OmniboxFieldTrial::BookmarksIndexURLsValue()) {
if (profile) {
bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
languages_ = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
@@ -43,8 +45,7 @@ void BookmarkProvider::Start(const AutocompleteInput& input,
matches_.clear();
if (input.text().empty() ||
- ((input.type() != AutocompleteInput::UNKNOWN) &&
- (input.type() != AutocompleteInput::QUERY)))
+ (input.type() == AutocompleteInput::FORCED_QUERY))
return;
DoAutocomplete(input);
@@ -57,12 +58,12 @@ void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input) {
if (!bookmark_model_)
return;
- TitleMatches matches;
+ BookmarkMatches matches;
// Retrieve enough bookmarks so that we have a reasonable probability of
// suggesting the one that the user desires.
const size_t kMaxBookmarkMatches = 50;
- // GetBookmarksWithTitlesMatching returns bookmarks matching the user's
+ // GetBookmarksMatching returns bookmarks matching the user's
// search terms using the following rules:
// - The search text is broken up into search terms. Each term is searched
// for separately.
@@ -77,26 +78,21 @@ void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input) {
// - Multiple terms enclosed in quotes will require those exact words in that
// exact order to match.
//
- // Note: GetBookmarksWithTitlesMatching() will never return a match span
- // greater than the length of the title against which it is being matched,
- // nor can those spans ever overlap because the match spans are coalesced
- // for all matched terms.
- //
- // Please refer to the code for BookmarkIndex::GetBookmarksWithTitlesMatching
- // for complete details of how title searches are performed against the user's
+ // Please refer to the code for BookmarkIndex::GetBookmarksMatching for
+ // complete details of how searches are performed against the user's
// bookmarks.
- bookmark_model_->GetBookmarksWithTitlesMatching(input.text(),
- kMaxBookmarkMatches,
- &matches);
+ bookmark_model_->GetBookmarksMatching(input.text(),
+ kMaxBookmarkMatches,
+ &matches);
if (matches.empty())
return; // There were no matches.
AutocompleteInput fixed_up_input(input);
FixupUserInput(&fixed_up_input);
- for (TitleMatches::const_iterator i = matches.begin(); i != matches.end();
+ for (BookmarkMatches::const_iterator i = matches.begin(); i != matches.end();
++i) {
// Create and score the AutocompleteMatch. If its score is 0 then the
// match is discarded.
- AutocompleteMatch match(TitleMatchToACMatch(input, fixed_up_input, *i));
+ AutocompleteMatch match(BookmarkMatchToACMatch(input, fixed_up_input, *i));
if (match.relevance > 0)
matches_.push_back(match);
}
@@ -114,12 +110,8 @@ namespace {
// for_each helper functor that calculates a match factor for each query term
// when calculating the final score.
//
-// Calculate a 'factor' from 0.0 to 1.0 based on 1) how much of the bookmark's
-// title the term matches, and 2) where the match is positioned within the
-// bookmark's title. A full length match earns a 1.0. A half-length match earns
-// at most a 0.5 and at least a 0.25. A single character match against a title
-// that is 100 characters long where the match is at the first character will
-// earn a 0.01 and at the last character will earn a 0.0001.
+// Calculate a 'factor' from 0 to the bookmark's title length for a match
+// based on 1) how many characters match and 2) where the match is positioned.
class ScoringFunctor {
public:
// |title_length| is the length of the bookmark title against which this
@@ -131,7 +123,7 @@ class ScoringFunctor {
void operator()(const query_parser::Snippet::MatchPosition& match) {
double term_length = static_cast<double>(match.second - match.first);
- scoring_factor_ += term_length / title_length_ *
+ scoring_factor_ += term_length *
(title_length_ - match.first) / title_length_;
}
@@ -144,32 +136,44 @@ class ScoringFunctor {
} // namespace
-AutocompleteMatch BookmarkProvider::TitleMatchToACMatch(
+AutocompleteMatch BookmarkProvider::BookmarkMatchToACMatch(
const AutocompleteInput& input,
const AutocompleteInput& fixed_up_input,
- const BookmarkTitleMatch& title_match) {
+ const BookmarkMatch& bookmark_match) {
// The AutocompleteMatch we construct is non-deletable because the only
// way to support this would be to delete the underlying bookmark, which is
// unlikely to be what the user intends.
AutocompleteMatch match(this, 0, false,
AutocompleteMatchType::BOOKMARK_TITLE);
- const base::string16& title(title_match.node->GetTitle());
- DCHECK(!title.empty());
-
- const GURL& url(title_match.node->url());
+ base::string16 title(bookmark_match.node->GetTitle());
+ const GURL& url(bookmark_match.node->url());
const base::string16& url_utf16 = base::UTF8ToUTF16(url.spec());
- size_t match_start, inline_autocomplete_offset;
- URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset(
- input, fixed_up_input, false, url_utf16, &match_start,
- &inline_autocomplete_offset);
+ size_t inline_autocomplete_offset = URLPrefix::GetInlineAutocompleteOffset(
+ input, fixed_up_input, false, url_utf16);
match.destination_url = url;
+ const size_t match_start = bookmark_match.url_match_positions.empty() ?
+ 0 : bookmark_match.url_match_positions[0].first;
const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text()) &&
((match_start == base::string16::npos) || (match_start != 0));
- match.contents = net::FormatUrl(url, languages_,
+ std::vector<size_t> offsets = BookmarkMatch::OffsetsFromMatchPositions(
+ bookmark_match.url_match_positions);
+ // In addition to knowing how |offsets| is transformed, we need to know how
+ // |inline_autocomplete_offset| is transformed. We add it to the end of
+ // |offsets|, compute how everything is transformed, then remove it from the
+ // end.
+ offsets.push_back(inline_autocomplete_offset);
+ match.contents = net::FormatUrlWithOffsets(url, languages_,
net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP),
- net::UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset);
- match.contents_class.push_back(
- ACMatchClassification(0, ACMatchClassification::URL));
+ net::UnescapeRule::SPACES, NULL, NULL, &offsets);
+ inline_autocomplete_offset = offsets.back();
+ offsets.pop_back();
+ BookmarkMatch::MatchPositions new_url_match_positions =
+ BookmarkMatch::ReplaceOffsetsInMatchPositions(
+ bookmark_match.url_match_positions, offsets);
+ match.contents_class =
+ ClassificationsFromMatch(new_url_match_positions,
+ match.contents.size(),
+ true);
match.fill_into_edit =
AutocompleteInput::FormattedStringWithEquivalentMeaning(url,
match.contents);
@@ -187,48 +191,56 @@ AutocompleteMatch BookmarkProvider::TitleMatchToACMatch(
}
match.description = title;
match.description_class =
- ClassificationsFromMatch(title_match.match_positions,
- match.description.size());
+ ClassificationsFromMatch(bookmark_match.title_match_positions,
+ match.description.size(),
+ false);
match.starred = true;
// Summary on how a relevance score is determined for the match:
//
- // For each term matching within the bookmark's title (as given by the set of
- // Snippet::MatchPositions) calculate a 'factor', sum up those factors, then
- // use the sum to figure out a value between the base score and the maximum
- // score.
- //
- // The factor for each term is the product of:
+ // For each match within the bookmark's title or URL (or both), calculate a
+ // 'factor', sum up those factors, then use the sum to figure out a value
+ // between the base score and the maximum score.
//
- // 1) how much of the bookmark's title has been matched by the term:
- // (term length / title length).
+ // The factor for each match is the product of:
//
- // Example: Given a bookmark title 'abcde fghijklm', with a title length
- // of 14, and two different search terms, 'abcde' and 'fghijklm', with
- // term lengths of 5 and 8, respectively, 'fghijklm' will score higher
- // (with a partial factor of 8/14 = 0.571) than 'abcde' (5/14 = 0.357).
+ // 1) how many characters in the bookmark's title/URL are part of this match.
+ // This is capped at the length of the bookmark's title
+ // to prevent terms that match in both the title and the URL from
+ // scoring too strongly.
//
- // 2) where the term match occurs within the bookmark's title, giving more
- // points for matches that appear earlier in the title:
- // ((title length - position of match start) / title_length).
+ // 2) where the match occurs within the bookmark's title or URL,
+ // giving more points for matches that appear earlier in the string:
+ // ((string_length - position of match start) / string_length).
//
// Example: Given a bookmark title of 'abcde fghijklm', with a title length
// of 14, and two different search terms, 'abcde' and 'fghij', with
// start positions of 0 and 6, respectively, 'abcde' will score higher
// (with a a partial factor of (14-0)/14 = 1.000 ) than 'fghij' (with
- // a partial factor of (14-6)/14 = 0.571 ).
+ // a partial factor of (14-6)/14 = 0.571 ). (In this example neither
+ // term matches in the URL.)
//
- // Once all term factors have been calculated they are summed. The resulting
- // sum will never be greater than 1.0 because of the way the bookmark model
- // matches and removes overlaps. (In particular, the bookmark model only
+ // Once all match factors have been calculated they are summed. If URL
+ // matches are not considered, the resulting sum will never be greater than
+ // the length of the bookmark title because of the way the bookmark model
+ // matches and removes overlaps. (In particular, the bookmark model only
// matches terms to the beginning of words and it removes all overlapping
- // matches, keeping only the longest. Together these mean that each
- // character is included in at most one match. This property ensures the
- // sum of factors is at most 1.) This sum is then multiplied against the
- // scoring range available, which is 299. The 299 is calculated by
- // subtracting the minimum possible score, 900, from the maximum possible
- // score, 1199. This product, ranging from 0 to 299, is added to the minimum
- // possible score, 900, giving the preliminary score.
+ // matches, keeping only the longest. Together these mean that each
+ // character is included in at most one match.) If URL matches are
+ // considered, the sum can be greater.
+ //
+ // This sum is then normalized by the length of the bookmark title (if URL
+ // matches are not considered) or by the length of the bookmark title + 10
+ // (if URL matches are considered) and capped at 1.0. (If URL matches
+ // are considered, we want to expand the scoring range so fewer bookmarks
+ // will hit the 1.0 cap and hence lose all ability to distinguish between
+ // these high-quality bookmarks.)
+ //
+ // The normalized value is multiplied against the scoring range available,
+ // which is 299. The 299 is calculated by subtracting the minimum possible
+ // score, 900, from the maximum possible score, 1199. This product, ranging
+ // from 0 to 299, is added to the minimum possible score, 900, giving the
+ // preliminary score.
//
// If the preliminary score is less than the maximum possible score, 1199,
// it can be boosted up to that maximum possible score if the URL referenced
@@ -238,18 +250,32 @@ AutocompleteMatch BookmarkProvider::TitleMatchToACMatch(
// scored up to a maximum of three, the score is boosted by a fixed amount
// given by |kURLCountBoost|, below.
//
- ScoringFunctor position_functor =
- for_each(title_match.match_positions.begin(),
- title_match.match_positions.end(), ScoringFunctor(title.size()));
+ if (score_using_url_matches_) {
+ // Pretend empty titles are identical to the URL.
+ if (title.empty())
+ title = base::ASCIIToUTF16(url.spec());
+ } else {
+ DCHECK(!title.empty());
+ }
+ ScoringFunctor title_position_functor =
+ for_each(bookmark_match.title_match_positions.begin(),
+ bookmark_match.title_match_positions.end(),
+ ScoringFunctor(title.size()));
+ ScoringFunctor url_position_functor =
+ for_each(bookmark_match.url_match_positions.begin(),
+ bookmark_match.url_match_positions.end(),
+ ScoringFunctor(bookmark_match.node->url().spec().length()));
+ const double summed_factors = title_position_functor.ScoringFactor() +
+ (score_using_url_matches_ ? url_position_functor.ScoringFactor() : 0);
+ const double normalized_sum = std::min(
+ summed_factors / (title.size() + (score_using_url_matches_ ? 10 : 0)),
+ 1.0);
const int kBaseBookmarkScore = 900;
const int kMaxBookmarkScore = 1199;
const double kBookmarkScoreRange =
static_cast<double>(kMaxBookmarkScore - kBaseBookmarkScore);
- // It's not likely that GetBookmarksWithTitlesMatching will return overlapping
- // matches but let's play it safe.
- match.relevance = std::min(kMaxBookmarkScore,
- static_cast<int>(position_functor.ScoringFactor() * kBookmarkScoreRange) +
- kBaseBookmarkScore);
+ match.relevance = static_cast<int>(normalized_sum * kBookmarkScoreRange) +
+ kBaseBookmarkScore;
// Don't waste any time searching for additional referenced URLs if we
// already have a perfect title match.
if (match.relevance >= kMaxBookmarkScore)
@@ -268,11 +294,14 @@ AutocompleteMatch BookmarkProvider::TitleMatchToACMatch(
// static
ACMatchClassifications BookmarkProvider::ClassificationsFromMatch(
const query_parser::Snippet::MatchPositions& positions,
- size_t text_length) {
+ size_t text_length,
+ bool is_url) {
+ ACMatchClassification::Style url_style =
+ is_url ? ACMatchClassification::URL : ACMatchClassification::NONE;
ACMatchClassifications classifications;
if (positions.empty()) {
classifications.push_back(
- ACMatchClassification(0, ACMatchClassification::NONE));
+ ACMatchClassification(0, url_style));
return classifications;
}
@@ -282,7 +311,7 @@ ACMatchClassifications BookmarkProvider::ClassificationsFromMatch(
++i) {
AutocompleteMatch::ACMatchClassifications new_class;
AutocompleteMatch::ClassifyLocationInString(i->first, i->second - i->first,
- text_length, 0, &new_class);
+ text_length, url_style, &new_class);
classifications = AutocompleteMatch::MergeClassifications(
classifications, new_class);
}
diff --git a/chrome/browser/autocomplete/bookmark_provider.h b/chrome/browser/autocomplete/bookmark_provider.h
index 8bdf2e9..be256e9 100644
--- a/chrome/browser/autocomplete/bookmark_provider.h
+++ b/chrome/browser/autocomplete/bookmark_provider.h
@@ -13,7 +13,7 @@
#include "components/query_parser/snippet.h"
class BookmarkModel;
-struct BookmarkTitleMatch;
+struct BookmarkMatch;
class Profile;
// This class is an autocomplete provider which quickly (and synchronously)
@@ -48,15 +48,15 @@ class BookmarkProvider : public AutocompleteProvider {
// |matches_|.
void DoAutocomplete(const AutocompleteInput& input);
- // Compose an AutocompleteMatch based on |title_match| that has 1) the URL of
- // title_match's bookmark, and 2) the bookmark's title, not the URL's page
+ // Compose an AutocompleteMatch based on |match| that has 1) the URL of
+ // |match|'s bookmark, and 2) the bookmark's title, not the URL's page
// title, as the description. |input| is used to compute the match's
// inline_autocompletion. |fixed_up_input| is used in that way as well;
// it's passed separately so this function doesn't have to compute it.
- AutocompleteMatch TitleMatchToACMatch(
+ AutocompleteMatch BookmarkMatchToACMatch(
const AutocompleteInput& input,
const AutocompleteInput& fixed_up_input,
- const BookmarkTitleMatch& title_match);
+ const BookmarkMatch& match);
// Converts |positions| into ACMatchClassifications and returns the
// classifications. |text_length| is used to determine the need to add an
@@ -64,10 +64,14 @@ class BookmarkProvider : public AutocompleteProvider {
// properly highlighted.
static ACMatchClassifications ClassificationsFromMatch(
const query_parser::Snippet::MatchPositions& positions,
- size_t text_length);
+ size_t text_length,
+ bool is_url);
BookmarkModel* bookmark_model_;
+ // True if we should use matches in the URL for scoring.
+ const bool score_using_url_matches_;
+
// Languages used during the URL formatting.
std::string languages_;
diff --git a/chrome/browser/autocomplete/bookmark_provider_unittest.cc b/chrome/browser/autocomplete/bookmark_provider_unittest.cc
index 380eadb..1cca616 100644
--- a/chrome/browser/autocomplete/bookmark_provider_unittest.cc
+++ b/chrome/browser/autocomplete/bookmark_provider_unittest.cc
@@ -12,13 +12,14 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/test/base/testing_profile.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "testing/gtest/include/gtest/gtest.h"
// The bookmark corpus against which we will simulate searches.
@@ -35,6 +36,8 @@ struct BookmarksTestInfo {
{ "jkl ghi", "http://www.catsanddogs.com/g" },
{ "frankly frankly frank", "http://www.catsanddogs.com/h" },
{ "foobar foobar", "http://www.foobar.com/" },
+ { "domain", "http://www.domain.com/http/" },
+ { "repeat", "http://www.repeat.com/1/repeat/2/" },
// For testing inline_autocompletion.
{ "http://blah.com/", "http://blah.com/" },
{ "http://fiddle.com/", "http://fiddle.com/" },
@@ -61,7 +64,7 @@ struct BookmarksTestInfo {
class BookmarkProviderTest : public testing::Test,
public AutocompleteProviderListener {
public:
- BookmarkProviderTest() : model_(new BookmarkModel(NULL)) {}
+ BookmarkProviderTest();
// AutocompleteProviderListener: Not called.
virtual void OnProviderUpdate(bool updated_matches) OVERRIDE {}
@@ -77,6 +80,10 @@ class BookmarkProviderTest : public testing::Test,
DISALLOW_COPY_AND_ASSIGN(BookmarkProviderTest);
};
+BookmarkProviderTest::BookmarkProviderTest() {
+ model_.reset(new BookmarkModel(NULL, false));
+}
+
void BookmarkProviderTest::SetUp() {
profile_.reset(new TestingProfile());
DCHECK(profile_.get());
@@ -387,13 +394,69 @@ TEST_F(BookmarkProviderTest, InlineAutocompletion) {
provider_->FixupUserInput(&fixed_up_input);
BookmarkNode node(GURL(query_data[i].url));
node.SetTitle(base::ASCIIToUTF16(query_data[i].url));
- BookmarkTitleMatch bookmark_match;
+ BookmarkMatch bookmark_match;
bookmark_match.node = &node;
- const AutocompleteMatch& ac_match =
- provider_->TitleMatchToACMatch(input, fixed_up_input, bookmark_match);
+ const AutocompleteMatch& ac_match = provider_->BookmarkMatchToACMatch(
+ input, fixed_up_input, bookmark_match);
EXPECT_EQ(query_data[i].allowed_to_be_default_match,
ac_match.allowed_to_be_default_match) << description;
EXPECT_EQ(base::ASCIIToUTF16(query_data[i].inline_autocompletion),
ac_match.inline_autocompletion) << description;
}
}
+
+TEST_F(BookmarkProviderTest, StripHttpAndAdjustOffsets) {
+ // Simulate searches.
+ struct QueryData {
+ const std::string query;
+ const std::string expected_contents;
+ // |expected_contents_class| is in format offset:style,offset:style,...
+ const std::string expected_contents_class;
+ } query_data[] = {
+ { "foo", "www.foobar.com", "0:1,4:3,7:1" },
+ { "www foo", "www.foobar.com", "0:3,3:1,4:3,7:1" },
+ { "foo www", "www.foobar.com", "0:3,3:1,4:3,7:1" },
+ { "foo http", "http://www.foobar.com", "0:3,4:1,11:3,14:1" },
+ { "blah", "blah.com", "0:3,4:1" },
+ { "http blah", "http://blah.com", "0:3,4:1,7:3,11:1" },
+ { "dom", "www.domain.com/http/", "0:1,4:3,7:1" },
+ { "dom http", "http://www.domain.com/http/",
+ "0:3,4:1,11:3,14:1,22:3,26:1" },
+ { "rep", "www.repeat.com/1/repeat/2/", "0:1,4:3,7:1,17:3,20:1" },
+ { "versi", "chrome://version", "0:1,9:3,14:1" }
+ };
+
+ // Reload the bookmarks index with |index_urls| == true.
+ model_.reset(new BookmarkModel(NULL, true));
+ SetUp();
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(query_data); ++i) {
+ std::string description = "for query=" + query_data[i].query;
+ AutocompleteInput input(base::ASCIIToUTF16(query_data[i].query),
+ base::string16::npos, base::string16(), GURL(),
+ AutocompleteInput::INVALID_SPEC, false, false,
+ false, true);
+ provider_->Start(input, false);
+ const ACMatches& matches(provider_->matches());
+ ASSERT_EQ(1U, matches.size()) << description;
+ const AutocompleteMatch& match = matches[0];
+ EXPECT_EQ(base::ASCIIToUTF16(query_data[i].expected_contents),
+ match.contents) << description;
+ std::vector<std::string> class_strings;
+ base::SplitString(
+ query_data[i].expected_contents_class, ',', &class_strings);
+ ASSERT_EQ(class_strings.size(), match.contents_class.size())
+ << description;
+ for (size_t i = 0; i < class_strings.size(); ++i) {
+ std::vector<std::string> chunks;
+ base::SplitString(class_strings[i], ':', &chunks);
+ ASSERT_EQ(2U, chunks.size()) << description;
+ size_t offset;
+ EXPECT_TRUE(base::StringToSizeT(chunks[0], &offset)) << description;
+ EXPECT_EQ(offset, match.contents_class[i].offset) << description;
+ int style;
+ EXPECT_TRUE(base::StringToInt(chunks[1], &style)) << description;
+ EXPECT_EQ(style, match.contents_class[i].style) << description;
+ }
+ }
+}
diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc
index df2d4cd..afe6422 100644
--- a/chrome/browser/autocomplete/history_url_provider.cc
+++ b/chrome/browser/autocomplete/history_url_provider.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
#include "chrome/browser/autocomplete/autocomplete_result.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history_service.h"
@@ -1149,7 +1150,7 @@ int HistoryURLProvider::CalculateRelevanceScoreUsingScoringParams(
ACMatchClassifications HistoryURLProvider::ClassifyDescription(
const base::string16& input_text,
const base::string16& description) {
- base::string16 clean_description = history::CleanUpTitleForMatching(
+ base::string16 clean_description = bookmark_utils::CleanUpTitleForMatching(
description);
history::TermMatches description_matches(SortAndDeoverlapMatches(
history::MatchTermInString(input_text, clean_description, 0)));
diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc
index 98bf327..7d46bb6 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider.cc
@@ -218,11 +218,11 @@ AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
// If the match is a search query this is easy: simply check whether the
// user text is a prefix of the query. If the match is a navigation, we
// assume the fill_into_edit looks something like a URL, so we use
- // URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset() to try and strip
- // off any prefixes that the user might not think would change the meaning,
- // but would otherwise prevent inline autocompletion. This allows, for
- // example, the input of "foo.c" to autocomplete to "foo.com" for a
- // fill_into_edit of "http://foo.com".
+ // URLPrefix::GetInlineAutocompleteOffset() to try and strip off any prefixes
+ // that the user might not think would change the meaning, but would
+ // otherwise prevent inline autocompletion. This allows, for example, the
+ // input of "foo.c" to autocomplete to "foo.com" for a fill_into_edit of
+ // "http://foo.com".
if (AutocompleteMatch::IsSearchType(match.type)) {
if (StartsWith(match.fill_into_edit, input.text(), false)) {
match.inline_autocompletion =
@@ -232,10 +232,9 @@ AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
match.inline_autocompletion.empty();
}
} else {
- size_t match_start, inline_autocomplete_offset;
- URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset(
- input, fixed_up_input, true, match.fill_into_edit,
- &match_start, &inline_autocomplete_offset);
+ const size_t inline_autocomplete_offset =
+ URLPrefix::GetInlineAutocompleteOffset(
+ input, fixed_up_input, true, match.fill_into_edit);
if (inline_autocomplete_offset != base::string16::npos) {
match.inline_autocompletion =
match.fill_into_edit.substr(inline_autocomplete_offset);
diff --git a/chrome/browser/autocomplete/url_prefix.cc b/chrome/browser/autocomplete/url_prefix.cc
index 1d680db..8a49f2c 100644
--- a/chrome/browser/autocomplete/url_prefix.cc
+++ b/chrome/browser/autocomplete/url_prefix.cc
@@ -77,13 +77,11 @@ bool URLPrefix::PrefixMatch(const URLPrefix& prefix,
}
// static
-void URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset(
+size_t URLPrefix::GetInlineAutocompleteOffset(
const AutocompleteInput& input,
const AutocompleteInput& fixed_up_input,
const bool allow_www_prefix_without_scheme,
- const base::string16& text,
- size_t* match_start,
- size_t* inline_autocomplete_offset) {
+ const base::string16& text) {
const URLPrefix* best_prefix = allow_www_prefix_without_scheme ?
BestURLPrefixWithWWWCase(text, input.text()) :
BestURLPrefix(text, input.text());
@@ -99,12 +97,7 @@ void URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset(
BestURLPrefix(text, fixed_up_input.text());
matching_string = &fixed_up_input.text();
}
- if (best_prefix != NULL) {
- *match_start = best_prefix->prefix.length();
- *inline_autocomplete_offset =
- best_prefix->prefix.length() + matching_string->length();
- } else {
- *match_start = base::string16::npos;
- *inline_autocomplete_offset = base::string16::npos;
- }
+ return (best_prefix != NULL) ?
+ (best_prefix->prefix.length() + matching_string->length()) :
+ base::string16::npos;
}
diff --git a/chrome/browser/autocomplete/url_prefix.h b/chrome/browser/autocomplete/url_prefix.h
index f5494cb..b7728b0 100644
--- a/chrome/browser/autocomplete/url_prefix.h
+++ b/chrome/browser/autocomplete/url_prefix.h
@@ -39,20 +39,19 @@ struct URLPrefix {
const base::string16& prefix_suffix);
// Sees if |text| is inlineable against either |input| or |fixed_up_input|,
- // filling in |match_start| and |inline_autocomplete_offset| appropriately.
+ // returning the appropriate inline autocomplete offset or
+ // base::string16::npos if |text| is not inlineable.
// |allow_www_prefix_without_scheme| says whether to consider an input such
// as "foo" to be allowed to match against text "www.foo.com". This is
// needed because sometimes the string we're matching against here can come
// from a match's fill_into_edit, which can start with "www." without having
// a protocol at the beginning, and we want to allow these matches to be
// inlineable. ("www." is not otherwise on the default prefix list.)
- static void ComputeMatchStartAndInlineAutocompleteOffset(
+ static size_t GetInlineAutocompleteOffset(
const AutocompleteInput& input,
const AutocompleteInput& fixed_up_input,
const bool allow_www_prefix_without_scheme,
- const base::string16& text,
- size_t* match_start,
- size_t* inline_autocomplete_offset);
+ const base::string16& text);
base::string16 prefix;
diff --git a/chrome/browser/bookmarks/DEPS b/chrome/browser/bookmarks/DEPS
index a702b0e..e7b25b7 100644
--- a/chrome/browser/bookmarks/DEPS
+++ b/chrome/browser/bookmarks/DEPS
@@ -17,6 +17,7 @@ include_rules = [
"!chrome/browser/history/history_service_factory.h",
"!chrome/browser/history/query_parser.h",
"!chrome/browser/history/url_database.h",
+ "!chrome/browser/omnibox/omnibox_field_trial.h",
"!chrome/browser/profiles/incognito_helpers.h",
"!chrome/browser/profiles/profile.h",
"!chrome/browser/profiles/startup_task_runner_service.h",
diff --git a/chrome/browser/bookmarks/bookmark_codec_unittest.cc b/chrome/browser/bookmarks/bookmark_codec_unittest.cc
index 4735779..01da754 100644
--- a/chrome/browser/bookmarks/bookmark_codec_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_codec_unittest.cc
@@ -73,20 +73,20 @@ class BookmarkCodecTest : public testing::Test {
protected:
// Helpers to create bookmark models with different data.
BookmarkModel* CreateTestModel1() {
- scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL));
+ scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL, false));
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
return model.release();
}
BookmarkModel* CreateTestModel2() {
- scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL));
+ scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL, false));
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
model->AddURL(bookmark_bar, 1, ASCIIToUTF16(kUrl2Title), GURL(kUrl2Url));
return model.release();
}
BookmarkModel* CreateTestModel3() {
- scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL));
+ scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL, false));
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
const BookmarkNode* folder1 = model->AddFolder(bookmark_bar, 1,
@@ -173,7 +173,7 @@ class BookmarkCodecTest : public testing::Test {
EXPECT_EQ("", decoder.computed_checksum());
EXPECT_EQ("", decoder.stored_checksum());
- scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL));
+ scoped_ptr<BookmarkModel> model(new BookmarkModel(NULL, false));
EXPECT_TRUE(Decode(&decoder, model.get(), value));
*computed_checksum = decoder.computed_checksum();
@@ -311,7 +311,7 @@ TEST_F(BookmarkCodecTest, PersistIDsTest) {
BookmarkCodec encoder;
scoped_ptr<base::Value> model_value(encoder.Encode(model_to_encode.get()));
- BookmarkModel decoded_model(NULL);
+ BookmarkModel decoded_model(NULL, false);
BookmarkCodec decoder;
ASSERT_TRUE(Decode(&decoder, &decoded_model, *model_value.get()));
ASSERT_NO_FATAL_FAILURE(
@@ -331,7 +331,7 @@ TEST_F(BookmarkCodecTest, PersistIDsTest) {
BookmarkCodec encoder2;
scoped_ptr<base::Value> model_value2(encoder2.Encode(&decoded_model));
- BookmarkModel decoded_model2(NULL);
+ BookmarkModel decoded_model2(NULL, false);
BookmarkCodec decoder2;
ASSERT_TRUE(Decode(&decoder2, &decoded_model2, *model_value2.get()));
ASSERT_NO_FATAL_FAILURE(AssertModelsEqual(&decoded_model, &decoded_model2));
@@ -347,7 +347,7 @@ TEST_F(BookmarkCodecTest, CanDecodeModelWithoutMobileBookmarks) {
JSONFileValueSerializer serializer(test_file);
scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL));
- BookmarkModel decoded_model(NULL);
+ BookmarkModel decoded_model(NULL, false);
BookmarkCodec decoder;
ASSERT_TRUE(Decode(&decoder, &decoded_model, *root.get()));
ExpectIDsUnique(&decoded_model);
@@ -435,7 +435,7 @@ TEST_F(BookmarkCodecTest, CanDecodeMetaInfoAsString) {
JSONFileValueSerializer serializer(test_file);
scoped_ptr<base::Value> root(serializer.Deserialize(NULL, NULL));
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
BookmarkCodec decoder;
ASSERT_TRUE(Decode(&decoder, &model, *root.get()));
diff --git a/chrome/browser/bookmarks/bookmark_index.cc b/chrome/browser/bookmarks/bookmark_index.cc
index feb2384..77c22d9 100644
--- a/chrome/browser/bookmarks/bookmark_index.cc
+++ b/chrome/browser/bookmarks/bookmark_index.cc
@@ -11,11 +11,13 @@
#include "base/i18n/case_conversion.h"
#include "base/strings/string16.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/url_database.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "components/query_parser/query_parser.h"
+#include "components/query_parser/snippet.h"
#include "third_party/icu/source/common/unicode/normalizer2.h"
namespace {
@@ -71,8 +73,12 @@ BookmarkIndex::NodeSet::const_iterator BookmarkIndex::Match::nodes_end() const {
return nodes.empty() ? terms.front()->second.end() : nodes.end();
}
-BookmarkIndex::BookmarkIndex(content::BrowserContext* browser_context)
- : browser_context_(browser_context) {
+BookmarkIndex::BookmarkIndex(content::BrowserContext* browser_context,
+ bool index_urls,
+ const std::string& languages)
+ : index_urls_(index_urls),
+ browser_context_(browser_context),
+ languages_(languages) {
}
BookmarkIndex::~BookmarkIndex() {
@@ -85,6 +91,12 @@ void BookmarkIndex::Add(const BookmarkNode* node) {
ExtractQueryWords(Normalize(node->GetTitle()));
for (size_t i = 0; i < terms.size(); ++i)
RegisterNode(terms[i], node);
+ if (index_urls_) {
+ terms = ExtractQueryWords(
+ bookmark_utils::CleanUpUrlForMatching(node->url(), languages_));
+ for (size_t i = 0; i < terms.size(); ++i)
+ RegisterNode(terms[i], node);
+ }
}
void BookmarkIndex::Remove(const BookmarkNode* node) {
@@ -95,12 +107,17 @@ void BookmarkIndex::Remove(const BookmarkNode* node) {
ExtractQueryWords(Normalize(node->GetTitle()));
for (size_t i = 0; i < terms.size(); ++i)
UnregisterNode(terms[i], node);
+ if (index_urls_) {
+ terms = ExtractQueryWords(
+ bookmark_utils::CleanUpUrlForMatching(node->url(), languages_));
+ for (size_t i = 0; i < terms.size(); ++i)
+ UnregisterNode(terms[i], node);
+ }
}
-void BookmarkIndex::GetBookmarksWithTitlesMatching(
- const base::string16& input_query,
- size_t max_count,
- std::vector<BookmarkTitleMatch>* results) {
+void BookmarkIndex::GetBookmarksMatching(const base::string16& input_query,
+ size_t max_count,
+ std::vector<BookmarkMatch>* results) {
const base::string16 query = Normalize(input_query);
std::vector<base::string16> terms = ExtractQueryWords(query);
if (terms.empty())
@@ -108,7 +125,7 @@ void BookmarkIndex::GetBookmarksWithTitlesMatching(
Matches matches;
for (size_t i = 0; i < terms.size(); ++i) {
- if (!GetBookmarksWithTitleMatchingTerm(terms[i], i == 0, &matches))
+ if (!GetBookmarksMatchingTerm(terms[i], i == 0, &matches))
return;
}
@@ -177,22 +194,48 @@ void BookmarkIndex::ExtractBookmarkNodePairs(
void BookmarkIndex::AddMatchToResults(
const BookmarkNode* node,
query_parser::QueryParser* parser,
- const std::vector<query_parser::QueryNode*>& query_nodes,
- std::vector<BookmarkTitleMatch>* results) {
- BookmarkTitleMatch title_match;
+ const query_parser::QueryNodeStarVector& query_nodes,
+ std::vector<BookmarkMatch>* results) {
// Check that the result matches the query. The previous search
// was a simple per-word search, while the more complex matching
// of QueryParser may filter it out. For example, the query
// ["thi"] will match the bookmark titled [Thinking], but since
// ["thi"] is quoted we don't want to do a prefix match.
- if (parser->DoesQueryMatch(Normalize(node->GetTitle()), query_nodes,
- &(title_match.match_positions))) {
- title_match.node = node;
- results->push_back(title_match);
+ query_parser::QueryWordVector title_words, url_words;
+ const base::string16 lower_title =
+ base::i18n::ToLower(Normalize(node->GetTitle()));
+ parser->ExtractQueryWords(lower_title, &title_words);
+ if (index_urls_) {
+ parser->ExtractQueryWords(
+ bookmark_utils::CleanUpUrlForMatching(node->url(), languages_),
+ &url_words);
+ }
+ query_parser::Snippet::MatchPositions title_matches, url_matches;
+ for (size_t i = 0; i < query_nodes.size(); ++i) {
+ const bool has_title_matches =
+ query_nodes[i]->HasMatchIn(title_words, &title_matches);
+ const bool has_url_matches = index_urls_ &&
+ query_nodes[i]->HasMatchIn(url_words, &url_matches);
+ if (!has_title_matches && !has_url_matches)
+ return;
+ query_parser::QueryParser::SortAndCoalesceMatchPositions(&title_matches);
+ if (index_urls_)
+ query_parser::QueryParser::SortAndCoalesceMatchPositions(&url_matches);
+ }
+ BookmarkMatch match;
+ if (lower_title.length() == node->GetTitle().length()) {
+ // Only use title matches if the lowercase string is the same length
+ // as the original string, otherwise the matches are meaningless.
+ // TODO(mpearson): revise match positions appropriately.
+ match.title_match_positions.swap(title_matches);
}
+ if (index_urls_)
+ match.url_match_positions.swap(url_matches);
+ match.node = node;
+ results->push_back(match);
}
-bool BookmarkIndex::GetBookmarksWithTitleMatchingTerm(const base::string16& term,
+bool BookmarkIndex::GetBookmarksMatchingTerm(const base::string16& term,
bool first_term,
Matches* matches) {
Index::const_iterator i = index_.lower_bound(term);
diff --git a/chrome/browser/bookmarks/bookmark_index.h b/chrome/browser/bookmarks/bookmark_index.h
index 4027e14d..93ce5f1 100644
--- a/chrome/browser/bookmarks/bookmark_index.h
+++ b/chrome/browser/bookmarks/bookmark_index.h
@@ -11,9 +11,10 @@
#include "base/basictypes.h"
#include "base/strings/string16.h"
+#include "components/query_parser/query_parser.h"
class BookmarkNode;
-struct BookmarkTitleMatch;
+struct BookmarkMatch;
namespace content {
class BrowserContext;
@@ -23,21 +24,21 @@ namespace history {
class URLDatabase;
}
-namespace query_parser {
-class QueryNode;
-class QueryParser;
-}
-
-// BookmarkIndex maintains an index of the titles of bookmarks for quick
-// look up. BookmarkIndex is owned and maintained by BookmarkModel, you
+// BookmarkIndex maintains an index of the titles and URLs of bookmarks for
+// quick look up. BookmarkIndex is owned and maintained by BookmarkModel, you
// shouldn't need to interact directly with BookmarkIndex.
//
// BookmarkIndex maintains the index (index_) as a map of sets. The map (type
// Index) maps from a lower case string to the set (type NodeSet) of
-// BookmarkNodes that contain that string in their title.
+// BookmarkNodes that contain that string in their title or URL.
class BookmarkIndex {
public:
- explicit BookmarkIndex(content::BrowserContext* browser_context);
+ // |index_urls| says whether URLs should be stored in the index in addition
+ // to bookmark titles. |languages| used to help parse IDNs in URLs for the
+ // bookmark index.
+ BookmarkIndex(content::BrowserContext* browser_context,
+ bool index_urls,
+ const std::string& languages);
~BookmarkIndex();
// Invoked when a bookmark has been added to the model.
@@ -46,11 +47,12 @@ class BookmarkIndex {
// Invoked when a bookmark has been removed from the model.
void Remove(const BookmarkNode* node);
- // Returns up to |max_count| of bookmarks containing the text |query|.
- void GetBookmarksWithTitlesMatching(
+ // Returns up to |max_count| of bookmarks containing each term from
+ // the text |query| in either the title or the URL.
+ void GetBookmarksMatching(
const base::string16& query,
size_t max_count,
- std::vector<BookmarkTitleMatch>* results);
+ std::vector<BookmarkMatch>* results);
private:
typedef std::set<const BookmarkNode*> NodeSet;
@@ -88,21 +90,21 @@ class BookmarkIndex {
void AddMatchToResults(
const BookmarkNode* node,
query_parser::QueryParser* parser,
- const std::vector<query_parser::QueryNode*>& query_nodes,
- std::vector<BookmarkTitleMatch>* results);
+ const query_parser::QueryNodeStarVector& query_nodes,
+ std::vector<BookmarkMatch>* results);
// Populates |matches| for the specified term. If |first_term| is true, this
// is the first term in the query. Returns true if there is at least one node
// matching the term.
- bool GetBookmarksWithTitleMatchingTerm(const base::string16& term,
- bool first_term,
- Matches* matches);
+ bool GetBookmarksMatchingTerm(const base::string16& term,
+ bool first_term,
+ Matches* matches);
// Iterates over |matches| updating each Match's nodes to contain the
// intersection of the Match's current nodes and the nodes at |index_i|.
// If the intersection is empty, the Match is removed.
//
- // This is invoked from GetBookmarksWithTitleMatchingTerm.
+ // This is invoked from GetBookmarksMatchingTerm.
void CombineMatchesInPlace(const Index::const_iterator& index_i,
Matches* matches);
@@ -114,7 +116,7 @@ class BookmarkIndex {
// non-empty the result is added to result, not combined in place. This
// variant is used for prefix matching.
//
- // This is invoked from GetBookmarksWithTitleMatchingTerm.
+ // This is invoked from GetBookmarksMatchingTerm.
void CombineMatches(const Index::const_iterator& index_i,
const Matches& current_matches,
Matches* result);
@@ -130,8 +132,14 @@ class BookmarkIndex {
Index index_;
+ // True if URLs are stored in the index as well as bookmark titles.
+ const bool index_urls_;
+
content::BrowserContext* browser_context_;
+ // Languages used to help parse IDNs in URLs for the bookmark index.
+ const std::string languages_;
+
DISALLOW_COPY_AND_ASSIGN(BookmarkIndex);
};
diff --git a/chrome/browser/bookmarks/bookmark_index_unittest.cc b/chrome/browser/bookmarks/bookmark_index_unittest.cc
index 057e608..557e1a2 100644
--- a/chrome/browser/bookmarks/bookmark_index_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_index_unittest.cc
@@ -19,7 +19,7 @@
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/url_database.h"
#include "chrome/test/base/testing_profile.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,20 +27,27 @@ using base::ASCIIToUTF16;
class BookmarkIndexTest : public testing::Test {
public:
- BookmarkIndexTest() : model_(new BookmarkModel(NULL)) {}
+ BookmarkIndexTest() : model_(new BookmarkModel(NULL, false)) {
+ }
- void AddBookmarksWithTitles(const char** titles, size_t count) {
- std::vector<std::string> title_vector;
- for (size_t i = 0; i < count; ++i)
- title_vector.push_back(titles[i]);
- AddBookmarksWithTitles(title_vector);
+ typedef std::pair<std::string, std::string> TitleAndURL;
+
+ void AddBookmarks(const char** titles, const char** urls, size_t count) {
+ // The pair is (title, url).
+ std::vector<TitleAndURL> bookmarks;
+ for (size_t i = 0; i < count; ++i) {
+ TitleAndURL bookmark(titles[i], urls[i]);
+ bookmarks.push_back(bookmark);
+ }
+ AddBookmarks(bookmarks);
}
- void AddBookmarksWithTitles(const std::vector<std::string>& titles) {
- GURL url("about:blank");
- for (size_t i = 0; i < titles.size(); ++i)
+ void AddBookmarks(const std::vector<TitleAndURL> bookmarks) {
+ for (size_t i = 0; i < bookmarks.size(); ++i) {
model_->AddURL(model_->other_node(), static_cast<int>(i),
- ASCIIToUTF16(titles[i]), url);
+ ASCIIToUTF16(bookmarks[i].first),
+ GURL(bookmarks[i].second));
+ }
}
void ExpectMatches(const std::string& query,
@@ -54,8 +61,8 @@ class BookmarkIndexTest : public testing::Test {
void ExpectMatches(const std::string& query,
const std::vector<std::string>& expected_titles) {
- std::vector<BookmarkTitleMatch> matches;
- model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16(query), 1000, &matches);
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(ASCIIToUTF16(query), 1000, &matches);
ASSERT_EQ(expected_titles.size(), matches.size());
for (size_t i = 0; i < expected_titles.size(); ++i) {
bool found = false;
@@ -71,14 +78,14 @@ class BookmarkIndexTest : public testing::Test {
}
void ExtractMatchPositions(const std::string& string,
- BookmarkTitleMatch::MatchPositions* matches) {
+ BookmarkMatch::MatchPositions* matches) {
std::vector<std::string> match_strings;
base::SplitString(string, ':', &match_strings);
for (size_t i = 0; i < match_strings.size(); ++i) {
std::vector<std::string> chunks;
base::SplitString(match_strings[i], ',', &chunks);
ASSERT_EQ(2U, chunks.size());
- matches->push_back(BookmarkTitleMatch::MatchPosition());
+ matches->push_back(BookmarkMatch::MatchPosition());
int chunks0, chunks1;
base::StringToInt(chunks[0], &chunks0);
base::StringToInt(chunks[1], &chunks1);
@@ -88,16 +95,12 @@ class BookmarkIndexTest : public testing::Test {
}
void ExpectMatchPositions(
- const std::string& query,
- const BookmarkTitleMatch::MatchPositions& expected_positions) {
- std::vector<BookmarkTitleMatch> matches;
- model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16(query), 1000, &matches);
- ASSERT_EQ(1U, matches.size());
- const BookmarkTitleMatch& match = matches[0];
- ASSERT_EQ(expected_positions.size(), match.match_positions.size());
+ const BookmarkMatch::MatchPositions& actual_positions,
+ const BookmarkMatch::MatchPositions& expected_positions) {
+ ASSERT_EQ(expected_positions.size(), actual_positions.size());
for (size_t i = 0; i < expected_positions.size(); ++i) {
- EXPECT_EQ(expected_positions[i].first, match.match_positions[i].first);
- EXPECT_EQ(expected_positions[i].second, match.match_positions[i].second);
+ EXPECT_EQ(expected_positions[i].first, actual_positions[i].first);
+ EXPECT_EQ(expected_positions[i].second, actual_positions[i].second);
}
}
@@ -110,9 +113,9 @@ class BookmarkIndexTest : public testing::Test {
// Various permutations with differing input, queries and output that exercises
// all query paths.
-TEST_F(BookmarkIndexTest, Tests) {
+TEST_F(BookmarkIndexTest, GetBookmarksMatching) {
struct TestData {
- const std::string input;
+ const std::string titles;
const std::string query;
const std::string expected;
} data[] = {
@@ -144,8 +147,13 @@ TEST_F(BookmarkIndexTest, Tests) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
std::vector<std::string> titles;
- base::SplitString(data[i].input, ';', &titles);
- AddBookmarksWithTitles(titles);
+ base::SplitString(data[i].titles, ';', &titles);
+ std::vector<TitleAndURL> bookmarks;
+ for (size_t j = 0; j < titles.size(); ++j) {
+ TitleAndURL bookmark(titles[j], "about:blank");
+ bookmarks.push_back(bookmark);
+ }
+ AddBookmarks(bookmarks);
std::vector<std::string> expected;
if (!data[i].expected.empty())
@@ -153,11 +161,69 @@ TEST_F(BookmarkIndexTest, Tests) {
ExpectMatches(data[i].query, expected);
- model_.reset(new BookmarkModel(NULL));
+ model_.reset(new BookmarkModel(NULL, false));
+ }
+}
+
+// Analogous to GetBookmarksMatching, this test tests various permutations
+// of title, URL, and input to see if the title/URL matches the input as
+// expected.
+TEST_F(BookmarkIndexTest, GetBookmarksMatchingWithURLs) {
+ struct TestData {
+ const std::string query;
+ const std::string title;
+ const std::string url;
+ const bool should_be_retrieved;
+ } data[] = {
+ // Test single-word inputs. Include both exact matches and prefix matches.
+ { "foo", "Foo", "http://www.bar.com/", true },
+ { "foo", "Foodie", "http://www.bar.com/", true },
+ { "foo", "Bar", "http://www.foo.com/", true },
+ { "foo", "Bar", "http://www.foodie.com/", true },
+ { "foo", "Foo", "http://www.foo.com/", true },
+ { "foo", "Bar", "http://www.bar.com/", false },
+ { "foo", "Bar", "http://www.bar.com/blah/foo/blah-again/ ", true },
+ { "foo", "Bar", "http://www.bar.com/blah/foodie/blah-again/ ", true },
+ { "foo", "Bar", "http://www.bar.com/blah-foo/blah-again/ ", true },
+ { "foo", "Bar", "http://www.bar.com/blah-foodie/blah-again/ ", true },
+ { "foo", "Bar", "http://www.bar.com/blahafoo/blah-again/ ", false },
+
+ // Test multi-word inputs.
+ { "foo bar", "Foo Bar", "http://baz.com/", true },
+ { "foo bar", "Foodie Bar", "http://baz.com/", true },
+ { "bar foo", "Foo Bar", "http://baz.com/", true },
+ { "bar foo", "Foodie Barly", "http://baz.com/", true },
+ { "foo bar", "Foo Baz", "http://baz.com/", false },
+ { "foo bar", "Foo Baz", "http://bar.com/", true },
+ { "foo bar", "Foo Baz", "http://barly.com/", true },
+ { "foo bar", "Foodie Baz", "http://barly.com/", true },
+ { "bar foo", "Foo Baz", "http://bar.com/", true },
+ { "bar foo", "Foo Baz", "http://barly.com/", true },
+ { "foo bar", "Baz Bar", "http://blah.com/foo", true },
+ { "foo bar", "Baz Barly", "http://blah.com/foodie", true },
+ { "foo bar", "Baz Bur", "http://blah.com/foo/bar", true },
+ { "foo bar", "Baz Bur", "http://blah.com/food/barly", true },
+ { "foo bar", "Baz Bur", "http://bar.com/blah/foo", true },
+ { "foo bar", "Baz Bur", "http://barly.com/blah/food", true },
+ { "foo bar", "Baz Bur", "http://bar.com/blah/flub", false },
+ { "foo bar", "Baz Bur", "http://foo.com/blah/flub", false }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
+ model_.reset(new BookmarkModel(NULL, true));
+ std::vector<TitleAndURL> bookmarks;
+ bookmarks.push_back(TitleAndURL(data[i].title, data[i].url));
+ AddBookmarks(bookmarks);
+
+ std::vector<std::string> expected;
+ if (data[i].should_be_retrieved)
+ expected.push_back(data[i].title);
+
+ ExpectMatches(data[i].query, expected);
}
}
-TEST_F(BookmarkIndexTest, TestNormalization) {
+TEST_F(BookmarkIndexTest, Normalization) {
struct TestData {
const char* title;
const char* query;
@@ -179,25 +245,25 @@ TEST_F(BookmarkIndexTest, TestNormalization) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
model_->AddURL(model_->other_node(), 0, base::UTF8ToUTF16(data[i].title),
url);
- std::vector<BookmarkTitleMatch> matches;
- model_->GetBookmarksWithTitlesMatching(
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(
base::UTF8ToUTF16(data[i].query), 10, &matches);
EXPECT_EQ(1u, matches.size());
- model_.reset(new BookmarkModel(NULL));
+ model_.reset(new BookmarkModel(NULL, false));
}
}
-// Makes sure match positions are updated appropriately.
-TEST_F(BookmarkIndexTest, MatchPositions) {
+// Makes sure match positions are updated appropriately for title matches.
+TEST_F(BookmarkIndexTest, MatchPositionsTitles) {
struct TestData {
const std::string title;
const std::string query;
- const std::string expected;
+ const std::string expected_title_match_positions;
} data[] = {
// Trivial test case of only one term, exact match.
{ "a", "A", "0,1" },
{ "foo bar", "bar", "4,7" },
- { "fooey bark", "bar foo", "0,3:6,9"},
+ { "fooey bark", "bar foo", "0,3:6,9" },
// Non-trivial tests.
{ "foobar foo", "foobar foo", "0,6:7,10" },
{ "foobar foo", "foo foobar", "0,6:7,10" },
@@ -205,22 +271,70 @@ TEST_F(BookmarkIndexTest, MatchPositions) {
{ "foobar foobar", "foo foobar", "0,6:7,13" },
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
- std::vector<std::string> titles;
- titles.push_back(data[i].title);
- AddBookmarksWithTitles(titles);
+ std::vector<TitleAndURL> bookmarks;
+ TitleAndURL bookmark(data[i].title, "about:blank");
+ bookmarks.push_back(bookmark);
+ AddBookmarks(bookmarks);
+
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(ASCIIToUTF16(data[i].query), 1000, &matches);
+ ASSERT_EQ(1U, matches.size());
- BookmarkTitleMatch::MatchPositions expected_matches;
- ExtractMatchPositions(data[i].expected, &expected_matches);
- ExpectMatchPositions(data[i].query, expected_matches);
+ BookmarkMatch::MatchPositions expected_title_matches;
+ ExtractMatchPositions(data[i].expected_title_match_positions,
+ &expected_title_matches);
+ ExpectMatchPositions(matches[0].title_match_positions,
+ expected_title_matches);
- model_.reset(new BookmarkModel(NULL));
+ model_.reset(new BookmarkModel(NULL, false));
+ }
+}
+
+// Makes sure match positions are updated appropriately for URL matches.
+TEST_F(BookmarkIndexTest, MatchPositionsURLs) {
+ struct TestData {
+ const std::string query;
+ const std::string url;
+ const std::string expected_url_match_positions;
+ } data[] = {
+ { "foo", "http://www.foo.com/", "11,14" },
+ { "foo", "http://www.foodie.com/", "11,14" },
+ { "foo", "http://www.foofoo.com/", "11,14" },
+ { "www", "http://www.foo.com/", "7,10" },
+ { "foo", "http://www.foodie.com/blah/foo/fi", "11,14:27,30" },
+ { "foo", "http://www.blah.com/blah/foo/fi", "25,28" },
+ { "foo www", "http://www.foodie.com/blah/foo/fi", "7,10:11,14:27,30" },
+ { "www foo", "http://www.foodie.com/blah/foo/fi", "7,10:11,14:27,30" },
+ { "www bla", "http://www.foodie.com/blah/foo/fi", "7,10:22,25" },
+ { "http", "http://www.foo.com/", "0,4" },
+ { "http www", "http://www.foo.com/", "0,4:7,10" },
+ { "http foo", "http://www.foo.com/", "0,4:11,14" },
+ { "http foo", "http://www.bar.com/baz/foodie/hi", "0,4:23,26" }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
+ model_.reset(new BookmarkModel(NULL, true));
+ std::vector<TitleAndURL> bookmarks;
+ TitleAndURL bookmark("123456", data[i].url);
+ bookmarks.push_back(bookmark);
+ AddBookmarks(bookmarks);
+
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(ASCIIToUTF16(data[i].query), 1000, &matches);
+ ASSERT_EQ(1U, matches.size()) << data[i].url << data[i].query;
+
+ BookmarkMatch::MatchPositions expected_url_matches;
+ ExtractMatchPositions(data[i].expected_url_match_positions,
+ &expected_url_matches);
+ ExpectMatchPositions(matches[0].url_match_positions, expected_url_matches);
}
}
// Makes sure index is updated when a node is removed.
TEST_F(BookmarkIndexTest, Remove) {
- const char* input[] = { "a", "b" };
- AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input));
+ const char* titles[] = { "a", "b" };
+ const char* urls[] = { "about:blank", "about:blank" };
+ AddBookmarks(titles, urls, ARRAYSIZE_UNSAFE(titles));
// Remove the node and make sure we don't get back any results.
model_->Remove(model_->other_node(), 0);
@@ -229,8 +343,9 @@ TEST_F(BookmarkIndexTest, Remove) {
// Makes sure index is updated when a node's title is changed.
TEST_F(BookmarkIndexTest, ChangeTitle) {
- const char* input[] = { "a", "b" };
- AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input));
+ const char* titles[] = { "a", "b" };
+ const char* urls[] = { "about:blank", "about:blank" };
+ AddBookmarks(titles, urls, ARRAYSIZE_UNSAFE(titles));
// Remove the node and make sure we don't get back any results.
const char* expected[] = { "blah" };
@@ -240,11 +355,12 @@ TEST_F(BookmarkIndexTest, ChangeTitle) {
// Makes sure no more than max queries is returned.
TEST_F(BookmarkIndexTest, HonorMax) {
- const char* input[] = { "abcd", "abcde" };
- AddBookmarksWithTitles(input, ARRAYSIZE_UNSAFE(input));
+ const char* titles[] = { "abcd", "abcde" };
+ const char* urls[] = { "about:blank", "about:blank" };
+ AddBookmarks(titles, urls, ARRAYSIZE_UNSAFE(titles));
- std::vector<BookmarkTitleMatch> matches;
- model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16("ABc"), 1, &matches);
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(ASCIIToUTF16("ABc"), 1, &matches);
EXPECT_EQ(1U, matches.size());
}
@@ -255,11 +371,11 @@ TEST_F(BookmarkIndexTest, EmptyMatchOnMultiwideLowercaseString) {
base::WideToUTF16(L"\u0130 i"),
GURL("http://www.google.com"));
- std::vector<BookmarkTitleMatch> matches;
- model_->GetBookmarksWithTitlesMatching(ASCIIToUTF16("i"), 100, &matches);
+ std::vector<BookmarkMatch> matches;
+ model_->GetBookmarksMatching(ASCIIToUTF16("i"), 100, &matches);
ASSERT_EQ(1U, matches.size());
EXPECT_TRUE(matches[0].node == n1);
- EXPECT_TRUE(matches[0].match_positions.empty());
+ EXPECT_TRUE(matches[0].title_match_positions.empty());
}
TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) {
@@ -320,8 +436,8 @@ TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) {
EXPECT_EQ(data[3].title, base::UTF16ToUTF8(result4.title()));
// Populate match nodes.
- std::vector<BookmarkTitleMatch> matches;
- model->GetBookmarksWithTitlesMatching(ASCIIToUTF16("google"), 4, &matches);
+ std::vector<BookmarkMatch> matches;
+ model->GetBookmarksMatching(ASCIIToUTF16("google"), 4, &matches);
// The resulting order should be:
// 1. Google (google.com) 100
@@ -336,7 +452,7 @@ TEST_F(BookmarkIndexTest, GetResultsSortedByTypedCount) {
matches.clear();
// Select top two matches.
- model->GetBookmarksWithTitlesMatching(ASCIIToUTF16("google"), 2, &matches);
+ model->GetBookmarksMatching(ASCIIToUTF16("google"), 2, &matches);
EXPECT_EQ(2, static_cast<int>(matches.size()));
EXPECT_EQ(data[0].url, matches[0].node->url());
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc
index 794e6e7..1f49a23 100644
--- a/chrome/browser/bookmarks/bookmark_model.cc
+++ b/chrome/browser/bookmarks/bookmark_model.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/i18n/string_compare.h"
+#include "base/prefs/pref_service.h"
#include "base/sequenced_task_runner.h"
#include "chrome/browser/bookmarks/bookmark_expanded_state_tracker.h"
#include "chrome/browser/bookmarks/bookmark_index.h"
@@ -23,7 +24,8 @@
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "chrome/common/pref_names.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "components/favicon_base/favicon_types.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
@@ -70,7 +72,8 @@ class SortComparator : public std::binary_function<const BookmarkNode*,
// BookmarkModel --------------------------------------------------------------
-BookmarkModel::BookmarkModel(Profile* profile)
+BookmarkModel::BookmarkModel(Profile* profile,
+ bool index_urls)
: profile_(profile),
loaded_(false),
root_(GURL()),
@@ -79,6 +82,7 @@ BookmarkModel::BookmarkModel(Profile* profile)
mobile_node_(NULL),
next_node_id_(1),
observers_(ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY),
+ index_urls_(index_urls),
loaded_signal_(true, false),
extensive_changes_(0) {
if (!profile_) {
@@ -609,14 +613,14 @@ void BookmarkModel::ResetDateFolderModified(const BookmarkNode* node) {
SetDateFolderModified(node, Time());
}
-void BookmarkModel::GetBookmarksWithTitlesMatching(
+void BookmarkModel::GetBookmarksMatching(
const base::string16& text,
size_t max_count,
- std::vector<BookmarkTitleMatch>* matches) {
+ std::vector<BookmarkMatch>* matches) {
if (!loaded_)
return;
- index_->GetBookmarksWithTitlesMatching(text, max_count, matches);
+ index_->GetBookmarksMatching(text, max_count, matches);
}
void BookmarkModel::ClearStore() {
@@ -945,7 +949,13 @@ BookmarkLoadDetails* BookmarkModel::CreateLoadDetails() {
CreatePermanentNode(BookmarkNode::OTHER_NODE);
BookmarkPermanentNode* mobile_node =
CreatePermanentNode(BookmarkNode::MOBILE);
- return new BookmarkLoadDetails(bb_node, other_node, mobile_node,
- new BookmarkIndex(profile_),
- next_node_id_);
+ return new BookmarkLoadDetails(
+ bb_node, other_node, mobile_node,
+ new BookmarkIndex(
+ profile_,
+ index_urls_,
+ profile_ ?
+ profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) :
+ std::string()),
+ next_node_id_);
}
diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h
index b6dfd70..816b89b 100644
--- a/chrome/browser/bookmarks/bookmark_model.h
+++ b/chrome/browser/bookmarks/bookmark_model.h
@@ -32,7 +32,7 @@ class BookmarkIndex;
class BookmarkLoadDetails;
class BookmarkModelObserver;
class BookmarkStorage;
-struct BookmarkTitleMatch;
+struct BookmarkMatch;
class Profile;
class ScopedGroupBookmarkActions;
@@ -58,7 +58,9 @@ class BookmarkModel : public content::NotificationObserver,
public BookmarkService,
public KeyedService {
public:
- explicit BookmarkModel(Profile* profile);
+ // |index_urls| says whether URLs should be stored in the BookmarkIndex
+ // in addition to bookmark titles.
+ BookmarkModel(Profile* profile, bool index_urls);
virtual ~BookmarkModel();
// Invoked prior to destruction to release any necessary resources.
@@ -210,10 +212,12 @@ class BookmarkModel : public content::NotificationObserver,
// combobox of most recently modified folders.
void ResetDateFolderModified(const BookmarkNode* node);
- void GetBookmarksWithTitlesMatching(
+ // Returns up to |max_count| of bookmarks containing each term from |text|
+ // in either the title or the URL.
+ void GetBookmarksMatching(
const base::string16& text,
size_t max_count,
- std::vector<BookmarkTitleMatch>* matches);
+ std::vector<BookmarkMatch>* matches);
// Sets the store to NULL, making it so the BookmarkModel does not persist
// any changes to disk. This is only useful during testing to speed up
@@ -385,6 +389,10 @@ class BookmarkModel : public content::NotificationObserver,
scoped_ptr<BookmarkIndex> index_;
+ // True if URLs are stored in the BookmarkIndex in addition to bookmark
+ // titles.
+ const bool index_urls_;
+
base::WaitableEvent loaded_signal_;
// See description of IsDoingExtensiveChanges above.
diff --git a/chrome/browser/bookmarks/bookmark_model_factory.cc b/chrome/browser/bookmarks/bookmark_model_factory.cc
index c54cff9..a03b909 100644
--- a/chrome/browser/bookmarks/bookmark_model_factory.cc
+++ b/chrome/browser/bookmarks/bookmark_model_factory.cc
@@ -9,6 +9,7 @@
#include "base/memory/singleton.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/startup_task_runner_service.h"
@@ -47,7 +48,8 @@ BookmarkModelFactory::~BookmarkModelFactory() {}
KeyedService* BookmarkModelFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = static_cast<Profile*>(context);
- BookmarkModel* bookmark_model = new BookmarkModel(profile);
+ BookmarkModel* bookmark_model =
+ new BookmarkModel(profile, OmniboxFieldTrial::BookmarksIndexURLsValue());
bookmark_model->Load(StartupTaskRunnerServiceFactory::GetForProfile(profile)->
GetBookmarkTaskRunner());
#if !defined(OS_ANDROID)
diff --git a/chrome/browser/bookmarks/bookmark_model_unittest.cc b/chrome/browser/bookmarks/bookmark_model_unittest.cc
index 65139b3..eec75f9 100644
--- a/chrome/browser/bookmarks/bookmark_model_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_model_unittest.cc
@@ -141,7 +141,7 @@ class BookmarkModelTest : public testing::Test,
};
BookmarkModelTest()
- : model_(NULL) {
+ : model_(NULL, false) {
model_.AddObserver(this);
ClearCounts();
}
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index c41a933..4b4bcdd 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -21,6 +21,7 @@
#include "content/public/browser/user_metrics.h"
#include "net/base/net_util.h"
#include "ui/base/models/tree_node_iterator.h"
+#include "url/gurl.h"
#if !defined(OS_ANDROID)
#include "chrome/browser/bookmarks/scoped_group_bookmark_actions.h"
@@ -30,6 +31,10 @@ using base::Time;
namespace {
+// The maximum length of URL or title returned by the Cleanup functions.
+const size_t kCleanedUpUrlMaxLength = 1024u;
+const size_t kCleanedUpTitleMaxLength = 1024u;
+
void CloneBookmarkNodeImpl(BookmarkModel* model,
const BookmarkNodeData::Element& element,
const BookmarkNode* parent,
@@ -123,6 +128,22 @@ const BookmarkNode* GetNodeByID(const BookmarkNode* node, int64 id) {
return NULL;
}
+// Attempts to shorten a URL safely (i.e., by preventing the end of the URL
+// from being in the middle of an escape sequence) to no more than
+// kCleanedUpUrlMaxLength characters, returning the result.
+std::string TruncateUrl(const std::string& url) {
+ if (url.length() <= kCleanedUpUrlMaxLength)
+ return url;
+
+ // If we're in the middle of an escape sequence, truncate just before it.
+ if (url[kCleanedUpUrlMaxLength - 1] == '%')
+ return url.substr(0, kCleanedUpUrlMaxLength - 1);
+ if (url[kCleanedUpUrlMaxLength - 2] == '%')
+ return url.substr(0, kCleanedUpUrlMaxLength - 2);
+
+ return url.substr(0, kCleanedUpUrlMaxLength);
+}
+
} // namespace
namespace bookmark_utils {
@@ -386,6 +407,19 @@ void RemoveAllBookmarks(BookmarkModel* model, const GURL& url) {
}
}
+base::string16 CleanUpUrlForMatching(const GURL& gurl,
+ const std::string& languages) {
+ return base::i18n::ToLower(net::FormatUrl(
+ GURL(TruncateUrl(gurl.spec())), languages,
+ net::kFormatUrlOmitUsernamePassword,
+ net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS,
+ NULL, NULL, NULL));
+}
+
+base::string16 CleanUpTitleForMatching(const base::string16& title) {
+ return base::i18n::ToLower(title.substr(0u, kCleanedUpTitleMaxLength));
+}
+
} // namespace bookmark_utils
const BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) {
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index a96be4e..9eecedb 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -14,13 +14,15 @@
class BookmarkModel;
class BookmarkNode;
class Profile;
+class GURL;
namespace user_prefs {
class PrefRegistrySyncable;
}
// A collection of bookmark utility functions used by various parts of the UI
-// that show bookmarks: bookmark manager, bookmark bar view ...
+// that show bookmarks (bookmark manager, bookmark bar view, ...) and other
+// systems that involve indexing and searching bookmarks.
namespace bookmark_utils {
// Fields to use when finding matching bookmarks.
@@ -107,6 +109,21 @@ void AddIfNotBookmarked(BookmarkModel* model,
// Removes all bookmarks for the given |url|.
void RemoveAllBookmarks(BookmarkModel* model, const GURL& url);
+// Truncates an overly-long URL, unescapes it, and lower-cases it,
+// returning the result. This unescaping makes it possible to match
+// substrings that were originally escaped for navigation; for
+// example, if the user searched for "a&p", the query would be escaped
+// as "a%26p", so without unescaping, an input string of "a&p" would
+// no longer match this URL. Note that the resulting unescaped URL
+// may not be directly navigable (which is why we escaped it to begin
+// with). |languages| is passed to net::FormatUrl().
+base::string16 CleanUpUrlForMatching(const GURL& gurl,
+ const std::string& languages);
+
+// Returns the lower-cased title, possibly truncated if the original title
+// is overly-long.
+base::string16 CleanUpTitleForMatching(const base::string16& title);
+
} // namespace bookmark_utils
// Returns the node with |id|, or NULL if there is no node with |id|.
diff --git a/chrome/browser/bookmarks/bookmark_utils_unittest.cc b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
index cfbf400..428fa1b 100644
--- a/chrome/browser/bookmarks/bookmark_utils_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_utils_unittest.cc
@@ -70,7 +70,7 @@ class BookmarkUtilsTest : public testing::Test,
};
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesWordPhraseQuery) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* node1 = model.AddURL(model.other_node(),
0,
ASCIIToUTF16("foo bar"),
@@ -128,7 +128,7 @@ TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesWordPhraseQuery) {
// Check exact matching against a URL query.
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesUrl) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* node1 = model.AddURL(model.other_node(),
0,
ASCIIToUTF16("Google"),
@@ -163,7 +163,7 @@ TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesUrl) {
// Check exact matching against a title query.
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesTitle) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* node1 = model.AddURL(model.other_node(),
0,
ASCIIToUTF16("Google"),
@@ -200,7 +200,7 @@ TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesTitle) {
// Check matching against a query with multiple predicates.
TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesConjunction) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* node1 = model.AddURL(model.other_node(),
0,
ASCIIToUTF16("Google"),
@@ -249,7 +249,7 @@ TEST_F(BookmarkUtilsTest, GetBookmarksMatchingPropertiesConjunction) {
}
TEST_F(BookmarkUtilsTest, CopyPaste) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* node = model.AddURL(model.other_node(),
0,
ASCIIToUTF16("foo bar"),
@@ -276,7 +276,7 @@ TEST_F(BookmarkUtilsTest, CopyPaste) {
}
TEST_F(BookmarkUtilsTest, CutToClipboard) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
model.AddObserver(this);
base::string16 title(ASCIIToUTF16("foo"));
@@ -301,7 +301,7 @@ TEST_F(BookmarkUtilsTest, CutToClipboard) {
}
TEST_F(BookmarkUtilsTest, GetParentForNewNodes) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
// This tests the case where selection contains one item and that item is a
// folder.
std::vector<const BookmarkNode*> nodes;
@@ -342,7 +342,7 @@ TEST_F(BookmarkUtilsTest, GetParentForNewNodes) {
// Verifies that meta info is copied when nodes are cloned.
TEST_F(BookmarkUtilsTest, CloneMetaInfo) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
// Add a node containing meta info.
const BookmarkNode* node = model.AddURL(model.other_node(),
0,
diff --git a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
index ee0eaaf..072f841 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
@@ -22,7 +22,7 @@ namespace bookmark_api_helpers {
class ExtensionBookmarksTest : public testing::Test {
public:
virtual void SetUp() OVERRIDE {
- model_.reset(new BookmarkModel(NULL));
+ model_.reset(new BookmarkModel(NULL, false));
model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("Digg"),
GURL("http://www.reddit.com"));
model_->AddURL(model_->other_node(), 0, base::ASCIIToUTF16("News"),
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc
index 7c9d20b..b80b25c 100644
--- a/chrome/browser/history/expire_history_backend_unittest.cc
+++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -56,7 +56,7 @@ class ExpireHistoryTest : public testing::Test,
public BroadcastNotificationDelegate {
public:
ExpireHistoryTest()
- : bookmark_model_(NULL),
+ : bookmark_model_(NULL, false),
ui_thread_(BrowserThread::UI, &message_loop_),
db_thread_(BrowserThread::DB, &message_loop_),
expirer_(this, &bookmark_model_),
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc
index debfcd8..4b7ef08 100644
--- a/chrome/browser/history/history_backend_unittest.cc
+++ b/chrome/browser/history/history_backend_unittest.cc
@@ -115,7 +115,7 @@ class HistoryBackendTestBase : public testing::Test {
typedef std::vector<std::pair<int, HistoryDetails*> > NotificationList;
HistoryBackendTestBase()
- : bookmark_model_(NULL),
+ : bookmark_model_(NULL, false),
loaded_(false),
ui_thread_(content::BrowserThread::UI, &message_loop_) {
}
diff --git a/chrome/browser/history/in_memory_url_index_types.h b/chrome/browser/history/in_memory_url_index_types.h
index 91ef29f..d8a0243 100644
--- a/chrome/browser/history/in_memory_url_index_types.h
+++ b/chrome/browser/history/in_memory_url_index_types.h
@@ -38,21 +38,6 @@ struct TermMatch {
};
typedef std::vector<TermMatch> TermMatches;
-// Truncates an overly-long URL, unescapes it, and lower-cases it,
-// returning the result. This unescaping makes it possible to match
-// substrings that were originally escaped for navigation; for
-// example, if the user searched for "a&p", the query would be escaped
-// as "a%26p", so without unescaping, an input string of "a&p" would
-// no longer match this URL. Note that the resulting unescaped URL
-// may not be directly navigable (which is why we escaped it to begin
-// with). |languages| is passed to net::FormatUrl().
-base::string16 CleanUpUrlForMatching(const GURL& gurl,
- const std::string& languages);
-
-// Returns the lower-cased title, possibly truncated if the original title
-// is overly-long.
-base::string16 CleanUpTitleForMatching(const base::string16& title);
-
// Returns a TermMatches which has an entry for each occurrence of the
// string |term| found in the string |cleaned_string|. Use
// CleanUpUrlForMatching() or CleanUpUrlTitleMatching() before passing
diff --git a/chrome/browser/history/scored_history_match.cc b/chrome/browser/history/scored_history_match.cc
index 5a385bc..d9cab36 100644
--- a/chrome/browser/history/scored_history_match.cc
+++ b/chrome/browser/history/scored_history_match.cc
@@ -18,6 +18,7 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/history_url_provider.h"
#include "chrome/browser/autocomplete/url_prefix.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "chrome/common/chrome_switches.h"
#include "components/bookmarks/core/browser/bookmark_service.h"
@@ -67,8 +68,8 @@ ScoredHistoryMatch::ScoredHistoryMatch(
// Figure out where each search term appears in the URL and/or page title
// so that we can score as well as provide autocomplete highlighting.
- base::string16 url = CleanUpUrlForMatching(gurl, languages);
- base::string16 title = CleanUpTitleForMatching(row.title());
+ base::string16 url = bookmark_utils::CleanUpUrlForMatching(gurl, languages);
+ base::string16 title = bookmark_utils::CleanUpTitleForMatching(row.title());
int term_num = 0;
for (String16Vector::const_iterator iter = terms.begin(); iter != terms.end();
++iter, ++term_num) {
diff --git a/chrome/browser/history/url_database.cc b/chrome/browser/history/url_database.cc
index 2adb518..605213b 100644
--- a/chrome/browser/history/url_database.cc
+++ b/chrome/browser/history/url_database.cc
@@ -370,7 +370,7 @@ bool URLDatabase::GetTextMatches(const base::string16& query,
"SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE hidden = 0"));
while (statement.Step()) {
- std::vector<query_parser::QueryWord> query_words;
+ query_parser::QueryWordVector query_words;
base::string16 url = base::i18n::ToLower(statement.ColumnString16(1));
query_parser_.ExtractQueryWords(url, &query_words);
GURL gurl(url);
diff --git a/chrome/browser/history/url_index_private_data.cc b/chrome/browser/history/url_index_private_data.cc
index 482880f..d592f17 100644
--- a/chrome/browser/history/url_index_private_data.cc
+++ b/chrome/browser/history/url_index_private_data.cc
@@ -22,6 +22,7 @@
#include "base/time/time.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
#include "chrome/browser/autocomplete/url_prefix.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history_db_task.h"
#include "chrome/browser/history/history_service.h"
@@ -756,10 +757,12 @@ void URLIndexPrivateData::AddRowWordsToIndex(const URLRow& row,
HistoryID history_id = static_cast<HistoryID>(row.id());
// Split URL into individual, unique words then add in the title words.
const GURL& gurl(row.url());
- const base::string16& url = CleanUpUrlForMatching(gurl, languages);
+ const base::string16& url =
+ bookmark_utils::CleanUpUrlForMatching(gurl, languages);
String16Set url_words = String16SetFromString16(url,
word_starts ? &word_starts->url_word_starts_ : NULL);
- const base::string16& title = CleanUpTitleForMatching(row.title());
+ const base::string16& title =
+ bookmark_utils::CleanUpTitleForMatching(row.title());
String16Set title_words = String16SetFromString16(title,
word_starts ? &word_starts->title_word_starts_ : NULL);
String16Set words;
@@ -1237,9 +1240,11 @@ bool URLIndexPrivateData::RestoreWordStartsMap(
iter != history_info_map_.end(); ++iter) {
RowWordStarts word_starts;
const URLRow& row(iter->second.url_row);
- const base::string16& url = CleanUpUrlForMatching(row.url(), languages);
+ const base::string16& url =
+ bookmark_utils::CleanUpUrlForMatching(row.url(), languages);
String16VectorFromString16(url, false, &word_starts.url_word_starts_);
- const base::string16& title = CleanUpTitleForMatching(row.title());
+ const base::string16& title =
+ bookmark_utils::CleanUpTitleForMatching(row.title());
String16VectorFromString16(title, false, &word_starts.title_word_starts_);
word_starts_map_[iter->first] = word_starts;
}
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc
index 6ef78c5..51cef04 100644
--- a/chrome/browser/importer/profile_writer_unittest.cc
+++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -18,7 +18,7 @@
#include "chrome/browser/importer/importer_unittest_utils.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/test/base/testing_profile.h"
-#include "components/bookmarks/core/browser/bookmark_title_match.h"
+#include "components/bookmarks/core/browser/bookmark_match.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -80,11 +80,10 @@ class ProfileWriterTest : public testing::Test {
const std::vector<BookmarkService::URLAndTitle>& bookmarks_record,
BookmarkModel* bookmark_model,
size_t expected) {
- std::vector<BookmarkTitleMatch> matches;
+ std::vector<BookmarkMatch> matches;
for (size_t i = 0; i < bookmarks_record.size(); ++i) {
- bookmark_model->GetBookmarksWithTitlesMatching(bookmarks_record[i].title,
- 10,
- &matches);
+ bookmark_model->GetBookmarksMatching(
+ bookmarks_record[i].title, 10, &matches);
EXPECT_EQ(expected, matches.size());
matches.clear();
}
diff --git a/chrome/browser/omnibox/omnibox_field_trial.cc b/chrome/browser/omnibox/omnibox_field_trial.cc
index 858e4f8..3d0afe7 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial.cc
@@ -418,6 +418,12 @@ bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() {
kHQPAllowMatchInSchemeRule) == "true";
}
+bool OmniboxFieldTrial::BookmarksIndexURLsValue() {
+ return chrome_variations::GetVariationParamValue(
+ kBundledExperimentFieldTrialName,
+ kBookmarksIndexURLsRule) == "true";
+}
+
const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
"OmniboxBundledExperimentV1";
const char OmniboxFieldTrial::kShortcutsScoringMaxRelevanceRule[] =
@@ -431,6 +437,7 @@ const char OmniboxFieldTrial::kHQPAllowMatchInSchemeRule[] =
"HQPAllowMatchInScheme";
const char OmniboxFieldTrial::kZeroSuggestRule[] = "ZeroSuggest";
const char OmniboxFieldTrial::kZeroSuggestVariantRule[] = "ZeroSuggestVariant";
+const char OmniboxFieldTrial::kBookmarksIndexURLsRule[] = "BookmarksIndexURLs";
const char OmniboxFieldTrial::kHUPNewScoringEnabledParam[] =
"HUPExperimentalScoringEnabled";
diff --git a/chrome/browser/omnibox/omnibox_field_trial.h b/chrome/browser/omnibox/omnibox_field_trial.h
index 95913f9d..1b0a1c7 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.h
+++ b/chrome/browser/omnibox/omnibox_field_trial.h
@@ -259,6 +259,17 @@ class OmniboxFieldTrial {
static bool HQPAllowMatchInSchemeValue();
// ---------------------------------------------------------
+ // For the BookmarksIndexURLs experiment that's part of the
+ // bundled omnibox field trial.
+
+ // Returns true if BookmarkIndex should index the URL of bookmarks
+ // (not only the titles) and search for / mark matches in the URLs,
+ // and BookmarkProvider should score bookmarks based on both the
+ // matches in bookmark title and URL. Returns false if the bookmarks
+ // index URLs experiment isn't active.
+ static bool BookmarksIndexURLsValue();
+
+ // ---------------------------------------------------------
// Exposed publicly for the sake of unittests.
static const char kBundledExperimentFieldTrialName[];
// Rule names used by the bundled experiment.
@@ -271,6 +282,7 @@ class OmniboxFieldTrial {
static const char kHQPAllowMatchInSchemeRule[];
static const char kZeroSuggestRule[];
static const char kZeroSuggestVariantRule[];
+ static const char kBookmarksIndexURLsRule[];
// Parameter names used by the HUP new scoring experiments.
static const char kHUPNewScoringEnabledParam[];
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
index 73babc4..91f0f1c 100644
--- a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
@@ -56,14 +56,14 @@ class HistoryMock : public HistoryService {
KeyedService* BuildBookmarkModel(content::BrowserContext* context) {
Profile* profile = static_cast<Profile*>(context);
- BookmarkModel* bookmark_model = new BookmarkModel(profile);
+ BookmarkModel* bookmark_model = new BookmarkModel(profile, false);
bookmark_model->Load(profile->GetIOTaskRunner());
return bookmark_model;
}
KeyedService* BuildBookmarkModelWithoutLoading(
content::BrowserContext* profile) {
- return new BookmarkModel(static_cast<Profile*>(profile));
+ return new BookmarkModel(static_cast<Profile*>(profile), false);
}
KeyedService* BuildHistoryService(content::BrowserContext* profile) {
diff --git a/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc
index 7d2d504..186e1b2 100644
--- a/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_editor_unittest.cc
@@ -12,7 +12,7 @@ using base::ASCIIToUTF16;
namespace {
TEST(BookmarkEditorTest, ApplyEditsWithNoFolderChange) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
const BookmarkNode* bookmarkbar = model.bookmark_bar_node();
model.AddURL(bookmarkbar, 0, ASCIIToUTF16("url0"), GURL("chrome://newtab"));
model.AddURL(bookmarkbar, 1, ASCIIToUTF16("url1"), GURL("chrome://newtab"));
diff --git a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
index a647b77..cbded0f 100644
--- a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
@@ -16,7 +16,7 @@ using base::ASCIIToUTF16;
namespace {
TEST(BookmarkUIUtilsTest, HasBookmarkURLs) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
std::vector<const BookmarkNode*> nodes;
@@ -56,7 +56,7 @@ TEST(BookmarkUIUtilsTest, HasBookmarkURLs) {
}
TEST(BookmarkUIUtilsTest, HasBookmarkURLsAllowedInIncognitoMode) {
- BookmarkModel model(NULL);
+ BookmarkModel model(NULL, false);
TestingProfile profile;
std::vector<const BookmarkNode*> nodes;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 85a7bf7..4889808 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -494,7 +494,7 @@ void TestingProfile::DestroyTopSites() {
static KeyedService* BuildBookmarkModel(content::BrowserContext* context) {
Profile* profile = static_cast<Profile*>(context);
- BookmarkModel* bookmark_model = new BookmarkModel(profile);
+ BookmarkModel* bookmark_model = new BookmarkModel(profile, false);
bookmark_model->Load(profile->GetIOTaskRunner());
return bookmark_model;
}