Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: chrome/browser/history/in_memory_url_index.cc

Issue 8120004: HQP Refactoring (in Preparation for SQLite Cache) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/history/in_memory_url_index.h" 5 #include "chrome/browser/history/in_memory_url_index.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <iterator> 9 #include <iterator>
10 #include <limits> 10 #include <limits>
11 #include <numeric> 11 #include <numeric>
12 12
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/i18n/break_iterator.h"
15 #include "base/i18n/case_conversion.h" 14 #include "base/i18n/case_conversion.h"
16 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
17 #include "base/string_util.h"
18 #include "base/threading/thread_restrictions.h" 16 #include "base/threading/thread_restrictions.h"
19 #include "base/time.h" 17 #include "base/time.h"
20 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
21 #include "chrome/browser/autocomplete/autocomplete.h" 19 #include "chrome/browser/autocomplete/autocomplete.h"
22 #include "chrome/browser/autocomplete/history_provider_util.h" 20 #include "chrome/browser/autocomplete/history_provider_util.h"
21 #include "chrome/browser/history/history_notifications.h"
23 #include "chrome/browser/history/url_database.h" 22 #include "chrome/browser/history/url_database.h"
24 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
26 #include "content/common/notification_details.h"
27 #include "content/common/notification_source.h"
26 #include "googleurl/src/url_parse.h" 28 #include "googleurl/src/url_parse.h"
27 #include "googleurl/src/url_util.h" 29 #include "googleurl/src/url_util.h"
28 #include "net/base/escape.h" 30 #include "net/base/escape.h"
29 #include "net/base/net_util.h" 31 #include "net/base/net_util.h"
30 #include "third_party/protobuf/src/google/protobuf/repeated_field.h" 32 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
31 #include "ui/base/l10n/l10n_util.h" 33 #include "ui/base/l10n/l10n_util.h"
32 34
33 using google::protobuf::RepeatedField; 35 using google::protobuf::RepeatedField;
34 using google::protobuf::RepeatedPtrField; 36 using google::protobuf::RepeatedPtrField;
35 using in_memory_url_index::InMemoryURLIndexCacheItem; 37 using in_memory_url_index::InMemoryURLIndexCacheItem;
(...skipping 16 matching lines...) Expand all
52 HistoryInfoMapEntry; 54 HistoryInfoMapEntry;
53 55
54 const size_t InMemoryURLIndex::kNoCachedResultForTerm = -1; 56 const size_t InMemoryURLIndex::kNoCachedResultForTerm = -1;
55 57
56 // Score ranges used to get a 'base' score for each of the scoring factors 58 // Score ranges used to get a 'base' score for each of the scoring factors
57 // (such as recency of last visit, times visited, times the URL was typed, 59 // (such as recency of last visit, times visited, times the URL was typed,
58 // and the quality of the string match). There is a matching value range for 60 // and the quality of the string match). There is a matching value range for
59 // each of these scores for each factor. 61 // each of these scores for each factor.
60 const int kScoreRank[] = { 1425, 1200, 900, 400 }; 62 const int kScoreRank[] = { 1425, 1200, 900, 400 };
61 63
62 ScoredHistoryMatch::ScoredHistoryMatch()
63 : raw_score(0),
64 can_inline(false) {}
65
66 ScoredHistoryMatch::ScoredHistoryMatch(const URLRow& url_info)
67 : HistoryMatch(url_info, 0, false, false),
68 raw_score(0),
69 can_inline(false) {}
70
71 ScoredHistoryMatch::~ScoredHistoryMatch() {}
72
73 // Comparison function for sorting ScoredMatches by their scores.
74 bool ScoredHistoryMatch::MatchScoreGreater(const ScoredHistoryMatch& m1,
75 const ScoredHistoryMatch& m2) {
76 return m1.raw_score >= m2.raw_score;
77 }
78
79 InMemoryURLIndex::SearchTermCacheItem::SearchTermCacheItem( 64 InMemoryURLIndex::SearchTermCacheItem::SearchTermCacheItem(
80 const WordIDSet& word_id_set, 65 const WordIDSet& word_id_set,
81 const HistoryIDSet& history_id_set) 66 const HistoryIDSet& history_id_set)
82 : word_id_set_(word_id_set), 67 : word_id_set_(word_id_set),
83 history_id_set_(history_id_set), 68 history_id_set_(history_id_set),
84 used_(true) {} 69 used_(true) {}
85 70
86 InMemoryURLIndex::SearchTermCacheItem::SearchTermCacheItem() 71 InMemoryURLIndex::SearchTermCacheItem::SearchTermCacheItem()
87 : used_(true) {} 72 : used_(true) {}
88 73
89 InMemoryURLIndex::SearchTermCacheItem::~SearchTermCacheItem() {} 74 InMemoryURLIndex::SearchTermCacheItem::~SearchTermCacheItem() {}
90 75
91 // Comparison function for sorting TermMatches by their offsets.
92 bool MatchOffsetLess(const TermMatch& m1, const TermMatch& m2) {
93 return m1.offset < m2.offset;
94 }
95
96 // Comparison function for sorting search terms by descending length. 76 // Comparison function for sorting search terms by descending length.
97 bool LengthGreater(const string16& string_a, const string16& string_b) { 77 bool LengthGreater(const string16& string_a, const string16& string_b) {
98 return string_a.length() > string_b.length(); 78 return string_a.length() > string_b.length();
99 } 79 }
100 80
101 // std::accumulate helper function to add up TermMatches' lengths. 81 // std::accumulate helper function to add up TermMatches' lengths.
102 int AccumulateMatchLength(int total, const TermMatch& match) { 82 int AccumulateMatchLength(int total, const TermMatch& match) {
103 return total + match.length; 83 return total + match.length;
104 } 84 }
105 85
(...skipping 22 matching lines...) Expand all
128 return 0; 108 return 0;
129 int score = kScoreRank[i]; 109 int score = kScoreRank[i];
130 if (i > 0) { 110 if (i > 0) {
131 score += (value - value_ranks[i]) * 111 score += (value - value_ranks[i]) *
132 (kScoreRank[i - 1] - kScoreRank[i]) / 112 (kScoreRank[i - 1] - kScoreRank[i]) /
133 (value_ranks[i - 1] - value_ranks[i]); 113 (value_ranks[i - 1] - value_ranks[i]);
134 } 114 }
135 return score; 115 return score;
136 } 116 }
137 117
138 InMemoryURLIndex::InMemoryURLIndex(const FilePath& history_dir) 118 InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
139 : history_dir_(history_dir), 119 const FilePath& history_dir)
140 history_item_count_(0) { 120 : profile_(profile),
Peter Kasting 2011/10/05 00:11:42 Nit: It doesn't seem like you need to keep this as
mrossetti 2011/10/07 17:04:14 Removed for now. In the next CL it'll probably be
121 history_dir_(history_dir),
122 private_data_(new URLIndexPrivateData) {
141 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_); 123 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_);
124 Source<Profile> source(profile_);
Peter Kasting 2011/10/05 00:11:42 Seems like we should take explicit action when |pr
mrossetti 2011/10/07 17:04:14 Done.
125 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
126 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED,
127 source);
128 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
142 } 129 }
143 130
144 // Called only by unit tests. 131 // Called only by unit tests.
145 InMemoryURLIndex::InMemoryURLIndex() 132 InMemoryURLIndex::InMemoryURLIndex()
146 : history_item_count_(0) { 133 : private_data_(new URLIndexPrivateData) {
147 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_); 134 InMemoryURLIndex::InitializeSchemeWhitelist(&scheme_whitelist_);
148 } 135 }
149 136
150 InMemoryURLIndex::~InMemoryURLIndex() {} 137 InMemoryURLIndex::~InMemoryURLIndex() {}
151 138
152 // static 139 // static
153 void InMemoryURLIndex::InitializeSchemeWhitelist( 140 void InMemoryURLIndex::InitializeSchemeWhitelist(
154 std::set<std::string>* whitelist) { 141 std::set<std::string>* whitelist) {
155 DCHECK(whitelist); 142 DCHECK(whitelist);
156 whitelist->insert(std::string(chrome::kAboutScheme)); 143 whitelist->insert(std::string(chrome::kAboutScheme));
157 whitelist->insert(std::string(chrome::kChromeUIScheme)); 144 whitelist->insert(std::string(chrome::kChromeUIScheme));
158 whitelist->insert(std::string(chrome::kFileScheme)); 145 whitelist->insert(std::string(chrome::kFileScheme));
159 whitelist->insert(std::string(chrome::kFtpScheme)); 146 whitelist->insert(std::string(chrome::kFtpScheme));
160 whitelist->insert(std::string(chrome::kHttpScheme)); 147 whitelist->insert(std::string(chrome::kHttpScheme));
161 whitelist->insert(std::string(chrome::kHttpsScheme)); 148 whitelist->insert(std::string(chrome::kHttpsScheme));
162 whitelist->insert(std::string(chrome::kMailToScheme)); 149 whitelist->insert(std::string(chrome::kMailToScheme));
163 } 150 }
164 151
165 // Indexing 152 // Indexing
166 153
167 bool InMemoryURLIndex::Init(history::URLDatabase* history_db, 154 bool InMemoryURLIndex::Init(URLDatabase* history_db,
168 const std::string& languages) { 155 const std::string& languages) {
169 // TODO(mrossetti): Register for profile/language change notifications. 156 // TODO(mrossetti): Register for profile/language change notifications.
170 languages_ = languages; 157 languages_ = languages;
171 return ReloadFromHistory(history_db, false); 158 return ReloadFromHistory(history_db, false);
172 } 159 }
173 160
174 void InMemoryURLIndex::ShutDown() { 161 void InMemoryURLIndex::ShutDown() {
162 registrar_.RemoveAll();
175 // Write our cache. 163 // Write our cache.
176 SaveToCacheFile(); 164 SaveToCacheFile();
177 } 165 }
178 166
167 void InMemoryURLIndex::Observe(int type,
168 const NotificationSource& source,
169 const NotificationDetails& details) {
170 switch (type) {
171 case chrome::NOTIFICATION_HISTORY_URL_VISITED:
172 OnURLsVisited(*Details<URLVisitedDetails>(details).ptr());
173 break;
174 case chrome::NOTIFICATION_HISTORY_TYPED_URLS_MODIFIED:
175 OnURLsModified(*Details<history::URLsModifiedDetails>(details).ptr());
176 break;
177 case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
178 OnURLsDeleted(*Details<history::URLsDeletedDetails>(details).ptr());
179 break;
180 default:
181 // For simplicity, the unit tests send us all notifications, even when
182 // we haven't registered for them, so don't assert here.
183 break;
184 }
185 }
186
187 void InMemoryURLIndex::OnURLsVisited(const URLVisitedDetails& details) {
188 UpdateURL(details.row);
189 }
190
191 void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails& details) {
192 for (std::vector<history::URLRow>::const_iterator row =
193 details.changed_urls.begin();
194 row != details.changed_urls.end(); ++row) {
Peter Kasting 2011/10/05 00:11:42 Nit: No {} necessary (2 places)
mrossetti 2011/10/07 17:04:14 Gotcha! I was under the mistaken notion that if th
195 UpdateURL(*row);
196 }
197 }
198
199 void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails& details) {
200 if (details.all_history) {
201 ClearPrivateData();
202 } else {
203 for (std::vector<URLRow>::const_iterator row = details.rows.begin();
204 row != details.rows.end(); ++row) {
205 DeleteURL(*row);
206 }
207 }
208 }
209
179 bool InMemoryURLIndex::IndexRow(const URLRow& row) { 210 bool InMemoryURLIndex::IndexRow(const URLRow& row) {
180 const GURL& gurl(row.url()); 211 const GURL& gurl(row.url());
181 212
182 // Index only URLs with a whitelisted scheme. 213 // Index only URLs with a whitelisted scheme.
183 if (!InMemoryURLIndex::URLSchemeIsWhitelisted(gurl)) 214 if (!InMemoryURLIndex::URLSchemeIsWhitelisted(gurl))
184 return true; 215 return true;
185 216
217 URLID row_id = row.id();
218 // Strip out username and password before saving and indexing.
186 string16 url(net::FormatUrl(gurl, languages_, 219 string16 url(net::FormatUrl(gurl, languages_,
187 net::kFormatUrlOmitUsernamePassword, 220 net::kFormatUrlOmitUsernamePassword,
188 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS, 221 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
189 NULL, NULL, NULL)); 222 NULL, NULL, NULL));
190 223 HistoryID history_id = static_cast<HistoryID>(row_id);
191 HistoryID history_id = static_cast<HistoryID>(row.id()); 224 DCHECK_LT(history_id, std::numeric_limits<HistoryID>::max());
192 DCHECK_LT(row.id(), std::numeric_limits<HistoryID>::max());
193 225
194 // Add the row for quick lookup in the history info store. 226 // Add the row for quick lookup in the history info store.
195 URLRow new_row(GURL(url), row.id()); 227 URLRow new_row(GURL(url), row_id);
196 new_row.set_visit_count(row.visit_count()); 228 new_row.set_visit_count(row.visit_count());
197 new_row.set_typed_count(row.typed_count()); 229 new_row.set_typed_count(row.typed_count());
198 new_row.set_last_visit(row.last_visit()); 230 new_row.set_last_visit(row.last_visit());
199 new_row.set_title(row.title()); 231 new_row.set_title(row.title());
200 history_info_map_[history_id] = new_row; 232 private_data_->history_info_map_[history_id] = new_row;
201 233
234 // Index the words contained in the URL and title of the row.
235 AddRowWordsToIndex(new_row);
236 ++(private_data_->history_item_count_);
237 return true;
238 }
239
240 void InMemoryURLIndex::AddRowWordsToIndex(const URLRow& row) {
241 HistoryID history_id = static_cast<HistoryID>(row.id());
202 // Split URL into individual, unique words then add in the title words. 242 // Split URL into individual, unique words then add in the title words.
243 const GURL& gurl(row.url());
244 string16 url(net::FormatUrl(gurl, languages_,
245 net::kFormatUrlOmitUsernamePassword,
246 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS,
247 NULL, NULL, NULL));
203 url = base::i18n::ToLower(url); 248 url = base::i18n::ToLower(url);
204 String16Set url_words = WordSetFromString16(url); 249 String16Set url_words = String16SetFromString16(url);
205 String16Set title_words = WordSetFromString16(row.title()); 250 String16Set title_words = String16SetFromString16(row.title());
206 String16Set words; 251 String16Set words;
207 std::set_union(url_words.begin(), url_words.end(), 252 std::set_union(url_words.begin(), url_words.end(),
208 title_words.begin(), title_words.end(), 253 title_words.begin(), title_words.end(),
209 std::insert_iterator<String16Set>(words, words.begin())); 254 std::insert_iterator<String16Set>(words, words.begin()));
210 for (String16Set::iterator word_iter = words.begin(); 255 for (String16Set::iterator word_iter = words.begin();
211 word_iter != words.end(); ++word_iter) 256 word_iter != words.end(); ++word_iter)
212 AddWordToIndex(*word_iter, history_id); 257 AddWordToIndex(*word_iter, history_id);
213 258
214 ++history_item_count_; 259 search_term_cache_.clear(); // Invalidate the term cache.
215 return true; 260 }
261
262 void InMemoryURLIndex::RemoveRowFromIndex(const URLRow& row) {
263 RemoveRowWordsFromIndex(row);
264 HistoryID history_id = static_cast<HistoryID>(row.id());
265 private_data_->history_info_map_.erase(history_id);
266 }
267
268 void InMemoryURLIndex::RemoveRowWordsFromIndex(const URLRow& row) {
269 // Remove the entries in history_id_word_map_ and word_id_history_map_ for
270 // this row.
271 URLIndexPrivateData& private_data(*(private_data_.get()));
272 HistoryID history_id = static_cast<HistoryID>(row.id());
273 WordIDSet word_id_set = private_data.history_id_word_map_[history_id];
274 private_data.history_id_word_map_.erase(history_id);
275
276 // Reconcile any changes to word usage.
277 for (WordIDSet::iterator word_id_iter = word_id_set.begin();
278 word_id_iter != word_id_set.end(); ++word_id_iter) {
279 WordID word_id = *word_id_iter;
280 HistoryIDSet history_ids = private_data.word_id_history_map_[word_id];
281 history_ids.erase(history_id);
282 if (!history_ids.empty()) {
283 // The word is still in use.
284 private_data.word_id_history_map_[word_id] = history_ids;
285 continue;
286 }
287
288 // The word is no longer in use. Reconcile any changes to character usage.
289 string16 word = private_data.word_list_[word_id];
290 Char16Set characters = Char16SetFromString16(word);
291 for (Char16Set::iterator uni_char_iter = characters.begin();
292 uni_char_iter != characters.end(); ++uni_char_iter) {
293 char16 uni_char = *uni_char_iter;
294 WordIDSet word_ids = private_data.char_word_map_[uni_char];
295 word_ids.erase(word_id);
296 if (!word_ids.empty()) {
297 // The character is still in use.
298 private_data.char_word_map_[uni_char] = word_ids;
299 continue;
300 }
301 // The character is no longer in use.
302 private_data.char_word_map_.erase(uni_char);
303 }
304
305 // Complete the removal of references to the word.
306 private_data.word_id_history_map_.erase(word_id);
307 private_data.word_map_.erase(word);
308 private_data.word_list_[word_id] = string16();
309 private_data.available_words_.insert(word_id);
310 }
216 } 311 }
217 312
218 bool InMemoryURLIndex::ReloadFromHistory(history::URLDatabase* history_db, 313 bool InMemoryURLIndex::ReloadFromHistory(history::URLDatabase* history_db,
219 bool clear_cache) { 314 bool clear_cache) {
220 ClearPrivateData(); 315 ClearPrivateData();
221 316
222 if (!history_db) 317 if (!history_db)
223 return false; 318 return false;
224 319
225 if (clear_cache || !RestoreFromCacheFile()) { 320 if (clear_cache || !RestoreFromCacheFile()) {
226 base::TimeTicks beginning_time = base::TimeTicks::Now(); 321 base::TimeTicks beginning_time = base::TimeTicks::Now();
227 // The index has to be built from scratch. 322 // The index has to be built from scratch.
228 URLDatabase::URLEnumerator history_enum; 323 URLDatabase::URLEnumerator history_enum;
229 if (!history_db->InitURLEnumeratorForSignificant(&history_enum)) 324 if (!history_db->InitURLEnumeratorForSignificant(&history_enum))
230 return false; 325 return false;
231 URLRow row; 326 URLRow row;
232 while (history_enum.GetNextURL(&row)) { 327 while (history_enum.GetNextURL(&row)) {
233 if (!IndexRow(row)) 328 if (!IndexRow(row))
234 return false; 329 return false;
235 } 330 }
236 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexingTime", 331 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexingTime",
237 base::TimeTicks::Now() - beginning_time); 332 base::TimeTicks::Now() - beginning_time);
238 SaveToCacheFile(); 333 SaveToCacheFile();
239 } 334 }
240 return true; 335 return true;
241 } 336 }
242 337
243 void InMemoryURLIndex::ClearPrivateData() { 338 void InMemoryURLIndex::ClearPrivateData() {
244 history_item_count_ = 0; 339 private_data_->Clear();
245 word_list_.clear();
246 word_map_.clear();
247 char_word_map_.clear();
248 word_id_history_map_.clear();
249 history_info_map_.clear();
250 search_term_cache_.clear(); 340 search_term_cache_.clear();
251 } 341 }
252 342
253 bool InMemoryURLIndex::RestoreFromCacheFile() { 343 bool InMemoryURLIndex::RestoreFromCacheFile() {
254 // TODO(mrossetti): Figure out how to determine if the cache is up-to-date. 344 // TODO(mrossetti): Figure out how to determine if the cache is up-to-date.
255 // That is: ensure that the database has not been modified since the cache 345 // That is: ensure that the database has not been modified since the cache
256 // was last saved. DB file modification date is inadequate. There are no 346 // was last saved. DB file modification date is inadequate. There are no
257 // SQLite table checksums automatically stored. 347 // SQLite table checksums automatically stored.
258 // FIXME(mrossetti): Move File IO to another thread. 348 // FIXME(mrossetti): Move File IO to another thread.
259 base::ThreadRestrictions::ScopedAllowIO allow_io; 349 base::ThreadRestrictions::ScopedAllowIO allow_io;
(...skipping 15 matching lines...) Expand all
275 return false; 365 return false;
276 } 366 }
277 367
278 if (!RestorePrivateData(index_cache)) { 368 if (!RestorePrivateData(index_cache)) {
279 ClearPrivateData(); // Back to square one -- must build from scratch. 369 ClearPrivateData(); // Back to square one -- must build from scratch.
280 return false; 370 return false;
281 } 371 }
282 372
283 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexRestoreCacheTime", 373 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexRestoreCacheTime",
284 base::TimeTicks::Now() - beginning_time); 374 base::TimeTicks::Now() - beginning_time);
285 UMA_HISTOGRAM_COUNTS("History.InMemoryURLHistoryItems", history_item_count_); 375 UMA_HISTOGRAM_COUNTS("History.InMemoryURLHistoryItems",
376 private_data_->history_item_count_);
286 UMA_HISTOGRAM_COUNTS("History.InMemoryURLCacheSize", data.size()); 377 UMA_HISTOGRAM_COUNTS("History.InMemoryURLCacheSize", data.size());
287 UMA_HISTOGRAM_COUNTS_10000("History.InMemoryURLWords", word_map_.size()); 378 UMA_HISTOGRAM_COUNTS_10000("History.InMemoryURLWords",
288 UMA_HISTOGRAM_COUNTS_10000("History.InMemoryURLChars", char_word_map_.size()); 379 private_data_->word_map_.size());
380 UMA_HISTOGRAM_COUNTS_10000("History.InMemoryURLChars",
381 private_data_->char_word_map_.size());
289 return true; 382 return true;
290 } 383 }
291 384
292 bool InMemoryURLIndex::SaveToCacheFile() { 385 bool InMemoryURLIndex::SaveToCacheFile() {
293 // TODO(mrossetti): Move File IO to another thread. 386 // TODO(mrossetti): Move File IO to another thread.
294 base::ThreadRestrictions::ScopedAllowIO allow_io; 387 base::ThreadRestrictions::ScopedAllowIO allow_io;
295 base::TimeTicks beginning_time = base::TimeTicks::Now(); 388 base::TimeTicks beginning_time = base::TimeTicks::Now();
296 InMemoryURLIndexCacheItem index_cache; 389 InMemoryURLIndexCacheItem index_cache;
297 SavePrivateData(&index_cache); 390 SavePrivateData(&index_cache);
298 std::string data; 391 std::string data;
(...skipping 11 matching lines...) Expand all
310 int size = data.size(); 403 int size = data.size();
311 if (file_util::WriteFile(file_path, data.c_str(), size) != size) { 404 if (file_util::WriteFile(file_path, data.c_str(), size) != size) {
312 LOG(WARNING) << "Failed to write " << file_path.value(); 405 LOG(WARNING) << "Failed to write " << file_path.value();
313 return false; 406 return false;
314 } 407 }
315 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexSaveCacheTime", 408 UMA_HISTOGRAM_TIMES("History.InMemoryURLIndexSaveCacheTime",
316 base::TimeTicks::Now() - beginning_time); 409 base::TimeTicks::Now() - beginning_time);
317 return true; 410 return true;
318 } 411 }
319 412
320 void InMemoryURLIndex::UpdateURL(URLID row_id, const URLRow& row) { 413 void InMemoryURLIndex::UpdateURL(const URLRow& row) {
321 // The row may or may not already be in our index. If it is not already 414 // The row may or may not already be in our index. If it is not already
322 // indexed and it qualifies then it gets indexed. If it is already 415 // indexed and it qualifies then it gets indexed. If it is already
323 // indexed and still qualifies then it gets updated, otherwise it 416 // indexed and still qualifies then it gets updated, otherwise it
324 // is deleted from the index. 417 // is deleted from the index.
325 HistoryInfoMap::iterator row_pos = history_info_map_.find(row_id); 418 HistoryInfoMap::iterator row_pos =
326 if (row_pos == history_info_map_.end()) { 419 private_data_->history_info_map_.find(row.id());
420 if (row_pos == private_data_->history_info_map_.end()) {
327 // This new row should be indexed if it qualifies. 421 // This new row should be indexed if it qualifies.
328 if (RowQualifiesAsSignificant(row, base::Time())) 422 if (RowQualifiesAsSignificant(row, base::Time()))
329 IndexRow(row); 423 IndexRow(row);
330 } else if (RowQualifiesAsSignificant(row, base::Time())) { 424 } else if (RowQualifiesAsSignificant(row, base::Time())) {
331 // This indexed row still qualifies and will be re-indexed. 425 // This indexed row still qualifies and will be re-indexed.
332 // The url won't have changed but the title, visit count, etc. 426 // The url won't have changed but the title, visit count, etc.
333 // might have changed. 427 // might have changed.
334 URLRow& old_row = row_pos->second; 428 URLRow& old_row = row_pos->second;
335 old_row.set_visit_count(row.visit_count()); 429 old_row.set_visit_count(row.visit_count());
336 old_row.set_typed_count(row.typed_count()); 430 old_row.set_typed_count(row.typed_count());
337 old_row.set_last_visit(row.last_visit()); 431 old_row.set_last_visit(row.last_visit());
338 // TODO(mrossetti): When we start indexing the title the next line 432 // While the URL is guaranteed to remain stable, the title may have change.
339 // will need attention. 433 // If so, then we need to update the index with the changed words.
340 old_row.set_title(row.title()); 434 if (old_row.title() != row.title()) {
435 // Clear all words associated with this row and re-index both the
436 // URL and title.
437 RemoveRowWordsFromIndex(row);
438 old_row.set_title(row.title());
439 AddRowWordsToIndex(old_row);
440 }
341 } else { 441 } else {
342 // This indexed row no longer qualifies and will be de-indexed. 442 // This indexed row no longer qualifies and will be de-indexed by
343 history_info_map_.erase(row_id); 443 // clearing all words associated with this row.
444 RemoveRowFromIndex(row);
344 } 445 }
345 // This invalidates the cache. 446 // This invalidates the cache.
346 search_term_cache_.clear(); 447 search_term_cache_.clear();
347 // TODO(mrossetti): Record this transaction in the cache.
348 } 448 }
349 449
350 void InMemoryURLIndex::DeleteURL(URLID row_id) { 450 void InMemoryURLIndex::DeleteURL(const URLRow& row) {
351 // Note that this does not remove any reference to this row from the 451 RemoveRowFromIndex(row);
352 // word_id_history_map_. That map will continue to contain (and return)
353 // hits against this row until that map is rebuilt, but since the
354 // history_info_map_ no longer references the row no erroneous results
355 // will propagate to the user.
356 history_info_map_.erase(row_id);
357 // This invalidates the word cache. 452 // This invalidates the word cache.
358 search_term_cache_.clear(); 453 search_term_cache_.clear();
359 // TODO(mrossetti): Record this transaction in the cache. 454 // TODO(mrossetti): Record this transaction in the cache.
360 } 455 }
361 456
362 // Searching 457 // Searching
363 458
364 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms( 459 ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
365 const String16Vector& terms) { 460 const String16Vector& terms) {
366 ScoredHistoryMatches scored_items; 461 ScoredHistoryMatches scored_items;
462
463 // Do nothing if we have indexed no words (probably because we've not been
464 // initialized yet).
465 if (private_data_->word_list_.empty())
466 return scored_items;
467
367 if (!terms.empty()) { 468 if (!terms.empty()) {
368 // Reset used_ flags for search_term_cache_. We use a basic mark-and-sweep 469 // Reset used_ flags for search_term_cache_. We use a basic mark-and-sweep
369 // approach. 470 // approach.
370 ResetSearchTermCache(); 471 ResetSearchTermCache();
371 472
372 // Lowercase the terms. 473 // Lowercase the terms.
373 // TODO(mrossetti): Another opportunity for a transform algorithm. 474 // TODO(mrossetti): Another opportunity for a transform algorithm.
374 String16Vector lower_terms; 475 String16Vector lower_terms;
375 for (String16Vector::const_iterator term_iter = terms.begin(); 476 for (String16Vector::const_iterator term_iter = terms.begin();
376 term_iter != terms.end(); ++term_iter) 477 term_iter != terms.end(); ++term_iter)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 515
415 return scored_items; 516 return scored_items;
416 } 517 }
417 518
418 void InMemoryURLIndex::ResetSearchTermCache() { 519 void InMemoryURLIndex::ResetSearchTermCache() {
419 for (SearchTermCacheMap::iterator iter = search_term_cache_.begin(); 520 for (SearchTermCacheMap::iterator iter = search_term_cache_.begin();
420 iter != search_term_cache_.end(); ++iter) 521 iter != search_term_cache_.end(); ++iter)
421 iter->second.used_ = false; 522 iter->second.used_ = false;
422 } 523 }
423 524
424 InMemoryURLIndex::HistoryIDSet InMemoryURLIndex::HistoryIDSetFromWords( 525 HistoryIDSet InMemoryURLIndex::HistoryIDSetFromWords(
425 const string16& uni_string) { 526 const string16& uni_string) {
426 // Break the terms down into individual terms (words), get the candidate 527 // Break the terms down into individual terms (words), get the candidate
427 // set for each term, and intersect each to get a final candidate list. 528 // set for each term, and intersect each to get a final candidate list.
428 // Note that a single 'term' from the user's perspective might be 529 // Note that a single 'term' from the user's perspective might be
429 // a string like "http://www.somewebsite.com" which, from our perspective, 530 // a string like "http://www.somewebsite.com" which, from our perspective,
430 // is four words: 'http', 'www', 'somewebsite', and 'com'. 531 // is four words: 'http', 'www', 'somewebsite', and 'com'.
431 HistoryIDSet history_id_set; 532 HistoryIDSet history_id_set;
432 String16Vector terms = WordVectorFromString16(uni_string, true); 533 String16Vector terms = String16VectorFromString16(uni_string, true);
433 // Sort the terms into the longest first as such are likely to narrow down 534 // Sort the terms into the longest first as such are likely to narrow down
434 // the results quicker. Also, single character terms are the most expensive 535 // the results quicker. Also, single character terms are the most expensive
435 // to process so save them for last. 536 // to process so save them for last.
436 std::sort(terms.begin(), terms.end(), LengthGreater); 537 std::sort(terms.begin(), terms.end(), LengthGreater);
437 for (String16Vector::iterator iter = terms.begin(); iter != terms.end(); 538 for (String16Vector::iterator iter = terms.begin(); iter != terms.end();
438 ++iter) { 539 ++iter) {
439 string16 uni_word = *iter; 540 string16 uni_word = *iter;
440 HistoryIDSet term_history_set = HistoryIDsForTerm(uni_word); 541 HistoryIDSet term_history_set = HistoryIDsForTerm(uni_word);
441 if (term_history_set.empty()) { 542 if (term_history_set.empty()) {
442 history_id_set.clear(); 543 history_id_set.clear();
443 break; 544 break;
444 } 545 }
445 if (iter == terms.begin()) { 546 if (iter == terms.begin()) {
446 history_id_set.swap(term_history_set); 547 history_id_set.swap(term_history_set);
447 } else { 548 } else {
448 HistoryIDSet new_history_id_set; 549 HistoryIDSet new_history_id_set;
449 std::set_intersection(history_id_set.begin(), history_id_set.end(), 550 std::set_intersection(history_id_set.begin(), history_id_set.end(),
450 term_history_set.begin(), term_history_set.end(), 551 term_history_set.begin(), term_history_set.end(),
451 std::inserter(new_history_id_set, 552 std::inserter(new_history_id_set,
452 new_history_id_set.begin())); 553 new_history_id_set.begin()));
453 history_id_set.swap(new_history_id_set); 554 history_id_set.swap(new_history_id_set);
454 } 555 }
455 } 556 }
456 return history_id_set; 557 return history_id_set;
457 } 558 }
458 559
459 InMemoryURLIndex::HistoryIDSet InMemoryURLIndex::HistoryIDsForTerm( 560 HistoryIDSet InMemoryURLIndex::HistoryIDsForTerm(
460 const string16& term) { 561 const string16& term) {
461 if (term.empty()) 562 if (term.empty())
462 return HistoryIDSet(); 563 return HistoryIDSet();
463 564
464 // TODO(mrossetti): Consider optimizing for very common terms such as 565 // TODO(mrossetti): Consider optimizing for very common terms such as
465 // 'http[s]', 'www', 'com', etc. Or collect the top 100 more frequently 566 // 'http[s]', 'www', 'com', etc. Or collect the top 100 more frequently
466 // occuring words in the user's searches. 567 // occuring words in the user's searches.
467 568
468 size_t term_length = term.length(); 569 size_t term_length = term.length();
469 InMemoryURLIndex::WordIDSet word_id_set; 570 WordIDSet word_id_set;
470 if (term_length > 1) { 571 if (term_length > 1) {
471 // See if this term or a prefix thereof is present in the cache. 572 // See if this term or a prefix thereof is present in the cache.
472 SearchTermCacheMap::iterator best_prefix(search_term_cache_.end()); 573 SearchTermCacheMap::iterator best_prefix(search_term_cache_.end());
473 for (SearchTermCacheMap::iterator cache_iter = search_term_cache_.begin(); 574 for (SearchTermCacheMap::iterator cache_iter = search_term_cache_.begin();
474 cache_iter != search_term_cache_.end(); ++cache_iter) { 575 cache_iter != search_term_cache_.end(); ++cache_iter) {
475 if (StartsWith(term, cache_iter->first, false) && 576 if (StartsWith(term, cache_iter->first, false) &&
476 (best_prefix == search_term_cache_.end() || 577 (best_prefix == search_term_cache_.end() ||
477 cache_iter->first.length() > best_prefix->first.length())) 578 cache_iter->first.length() > best_prefix->first.length()))
478 best_prefix = cache_iter; 579 best_prefix = cache_iter;
479 } 580 }
(...skipping 25 matching lines...) Expand all
505 606
506 // Filter for each remaining, unique character in the term. 607 // Filter for each remaining, unique character in the term.
507 Char16Set leftover_chars = Char16SetFromString16(leftovers); 608 Char16Set leftover_chars = Char16SetFromString16(leftovers);
508 Char16Set unique_chars; 609 Char16Set unique_chars;
509 std::set_difference(leftover_chars.begin(), leftover_chars.end(), 610 std::set_difference(leftover_chars.begin(), leftover_chars.end(),
510 prefix_chars.begin(), prefix_chars.end(), 611 prefix_chars.begin(), prefix_chars.end(),
511 std::inserter(unique_chars, unique_chars.begin())); 612 std::inserter(unique_chars, unique_chars.begin()));
512 613
513 // Reduce the word set with any leftover, unprocessed characters. 614 // Reduce the word set with any leftover, unprocessed characters.
514 if (!unique_chars.empty()) { 615 if (!unique_chars.empty()) {
515 WordIDSet leftover_set(WordIDSetForTermChars(unique_chars)); 616 WordIDSet leftover_set(
617 private_data_->WordIDSetForTermChars(unique_chars));
516 // We might come up empty on the leftovers. 618 // We might come up empty on the leftovers.
517 if (leftover_set.empty()) { 619 if (leftover_set.empty()) {
518 search_term_cache_[term] = SearchTermCacheItem(); 620 search_term_cache_[term] = SearchTermCacheItem();
519 return HistoryIDSet(); 621 return HistoryIDSet();
520 } 622 }
521 // Or there may not have been a prefix from which to start. 623 // Or there may not have been a prefix from which to start.
522 if (prefix_chars.empty()) { 624 if (prefix_chars.empty()) {
523 word_id_set.swap(leftover_set); 625 word_id_set.swap(leftover_set);
524 } else { 626 } else {
525 WordIDSet new_word_id_set; 627 WordIDSet new_word_id_set;
526 std::set_intersection(word_id_set.begin(), word_id_set.end(), 628 std::set_intersection(word_id_set.begin(), word_id_set.end(),
527 leftover_set.begin(), leftover_set.end(), 629 leftover_set.begin(), leftover_set.end(),
528 std::inserter(new_word_id_set, 630 std::inserter(new_word_id_set,
529 new_word_id_set.begin())); 631 new_word_id_set.begin()));
530 word_id_set.swap(new_word_id_set); 632 word_id_set.swap(new_word_id_set);
531 } 633 }
532 } 634 }
533 635
534 // We must filter the word list because the resulting word set surely 636 // We must filter the word list because the resulting word set surely
535 // contains words which do not have the search term as a proper subset. 637 // contains words which do not have the search term as a proper subset.
536 for (WordIDSet::iterator word_set_iter = word_id_set.begin(); 638 for (WordIDSet::iterator word_set_iter = word_id_set.begin();
537 word_set_iter != word_id_set.end(); ) { 639 word_set_iter != word_id_set.end(); ) {
538 if (word_list_[*word_set_iter].find(term) == string16::npos) 640 if (private_data_->word_list_[*word_set_iter].find(term) ==
641 string16::npos)
539 word_id_set.erase(word_set_iter++); 642 word_id_set.erase(word_set_iter++);
540 else 643 else
541 ++word_set_iter; 644 ++word_set_iter;
542 } 645 }
543 } else { 646 } else {
544 word_id_set = WordIDSetForTermChars(Char16SetFromString16(term)); 647 word_id_set =
648 private_data_->WordIDSetForTermChars(Char16SetFromString16(term));
545 } 649 }
546 650
547 // If any words resulted then we can compose a set of history IDs by unioning 651 // If any words resulted then we can compose a set of history IDs by unioning
548 // the sets from each word. 652 // the sets from each word.
549 HistoryIDSet history_id_set; 653 HistoryIDSet history_id_set;
550 if (!word_id_set.empty()) { 654 if (!word_id_set.empty()) {
551 for (WordIDSet::iterator word_id_iter = word_id_set.begin(); 655 for (WordIDSet::iterator word_id_iter = word_id_set.begin();
552 word_id_iter != word_id_set.end(); ++word_id_iter) { 656 word_id_iter != word_id_set.end(); ++word_id_iter) {
553 WordID word_id = *word_id_iter; 657 WordID word_id = *word_id_iter;
554 WordIDHistoryMap::iterator word_iter = word_id_history_map_.find(word_id); 658 WordIDHistoryMap::iterator word_iter =
555 if (word_iter != word_id_history_map_.end()) { 659 private_data_->word_id_history_map_.find(word_id);
660 if (word_iter != private_data_->word_id_history_map_.end()) {
556 HistoryIDSet& word_history_id_set(word_iter->second); 661 HistoryIDSet& word_history_id_set(word_iter->second);
557 history_id_set.insert(word_history_id_set.begin(), 662 history_id_set.insert(word_history_id_set.begin(),
558 word_history_id_set.end()); 663 word_history_id_set.end());
559 } 664 }
560 } 665 }
561 } 666 }
562 667
563 // Record a new cache entry for this word if the term is longer than 668 // Record a new cache entry for this word if the term is longer than
564 // a single character. 669 // a single character.
565 if (term_length > 1) 670 if (term_length > 1)
566 search_term_cache_[term] = SearchTermCacheItem(word_id_set, history_id_set); 671 search_term_cache_[term] = SearchTermCacheItem(word_id_set, history_id_set);
567 672
568 return history_id_set; 673 return history_id_set;
569 } 674 }
570 675
571 // Utility Functions 676 // Utility Functions
572 677
573 // static
574 InMemoryURLIndex::String16Set InMemoryURLIndex::WordSetFromString16(
575 const string16& uni_string) {
576 const size_t kMaxWordLength = 64;
577 String16Vector words = WordVectorFromString16(uni_string, false);
578 String16Set word_set;
579 for (String16Vector::const_iterator iter = words.begin(); iter != words.end();
580 ++iter)
581 word_set.insert(base::i18n::ToLower(*iter).substr(0, kMaxWordLength));
582 return word_set;
583 }
584
585 // static
586 InMemoryURLIndex::String16Vector InMemoryURLIndex::WordVectorFromString16(
587 const string16& uni_string,
588 bool break_on_space) {
589 base::i18n::BreakIterator iter(
590 uni_string,
591 break_on_space ? base::i18n::BreakIterator::BREAK_SPACE
592 : base::i18n::BreakIterator::BREAK_WORD);
593 String16Vector words;
594 if (!iter.Init())
595 return words;
596 while (iter.Advance()) {
597 if (break_on_space || iter.IsWord()) {
598 string16 word = iter.GetString();
599 if (break_on_space)
600 TrimWhitespace(word, TRIM_ALL, &word);
601 if (!word.empty())
602 words.push_back(word);
603 }
604 }
605 return words;
606 }
607
608 // static
609 InMemoryURLIndex::Char16Set InMemoryURLIndex::Char16SetFromString16(
610 const string16& term) {
611 Char16Set characters;
612 for (string16::const_iterator iter = term.begin(); iter != term.end();
613 ++iter)
614 characters.insert(*iter);
615 return characters;
616 }
617
618 void InMemoryURLIndex::AddWordToIndex(const string16& term, 678 void InMemoryURLIndex::AddWordToIndex(const string16& term,
619 HistoryID history_id) { 679 HistoryID history_id) {
620 WordMap::iterator word_pos = word_map_.find(term); 680 WordMap::iterator word_pos = private_data_->word_map_.find(term);
621 if (word_pos != word_map_.end()) 681 if (word_pos != private_data_->word_map_.end())
622 UpdateWordHistory(word_pos->second, history_id); 682 UpdateWordHistory(word_pos->second, history_id);
623 else 683 else
624 AddWordHistory(term, history_id); 684 AddWordHistory(term, history_id);
625 } 685 }
626 686
627 void InMemoryURLIndex::UpdateWordHistory(WordID word_id, HistoryID history_id) { 687 void InMemoryURLIndex::UpdateWordHistory(WordID word_id, HistoryID history_id) {
628 WordIDHistoryMap::iterator history_pos = word_id_history_map_.find(word_id); 688 WordIDHistoryMap::iterator history_pos =
629 DCHECK(history_pos != word_id_history_map_.end()); 689 private_data_->word_id_history_map_.find(word_id);
630 HistoryIDSet& history_id_set(history_pos->second); 690 DCHECK(history_pos != private_data_->word_id_history_map_.end());
631 history_id_set.insert(history_id); 691 HistoryIDSet& history_id_set(history_pos->second);
692 history_id_set.insert(history_id);
693 private_data_->AddToHistoryIDWordMap(history_id, word_id);
632 } 694 }
633 695
634 // Add a new word to the word list and the word map, and then create a 696 // Add a new word to the word list and the word map, and then create a
635 // new entry in the word/history map. 697 // new entry in the word/history map.
636 void InMemoryURLIndex::AddWordHistory(const string16& term, 698 void InMemoryURLIndex::AddWordHistory(const string16& term,
637 HistoryID history_id) { 699 HistoryID history_id) {
638 word_list_.push_back(term); 700 URLIndexPrivateData& private_data(*(private_data_.get()));
639 WordID word_id = word_list_.size() - 1; 701 WordID word_id = private_data.word_list_.size();
640 word_map_[term] = word_id; 702 if (private_data.available_words_.empty()) {
703 private_data.word_list_.push_back(term);
704 } else {
705 word_id = *(private_data.available_words_.begin());
706 private_data.word_list_[word_id] = term;
707 private_data.available_words_.erase(word_id);
708 }
709 private_data.word_map_[term] = word_id;
710
641 HistoryIDSet history_id_set; 711 HistoryIDSet history_id_set;
642 history_id_set.insert(history_id); 712 history_id_set.insert(history_id);
643 word_id_history_map_[word_id] = history_id_set; 713 private_data.word_id_history_map_[word_id] = history_id_set;
714 private_data_->AddToHistoryIDWordMap(history_id, word_id);
715
644 // For each character in the newly added word (i.e. a word that is not 716 // For each character in the newly added word (i.e. a word that is not
645 // already in the word index), add the word to the character index. 717 // already in the word index), add the word to the character index.
646 Char16Set characters = Char16SetFromString16(term); 718 Char16Set characters = Char16SetFromString16(term);
647 for (Char16Set::iterator uni_char_iter = characters.begin(); 719 for (Char16Set::iterator uni_char_iter = characters.begin();
648 uni_char_iter != characters.end(); ++uni_char_iter) { 720 uni_char_iter != characters.end(); ++uni_char_iter) {
649 char16 uni_char = *uni_char_iter; 721 char16 uni_char = *uni_char_iter;
650 CharWordIDMap::iterator char_iter = char_word_map_.find(uni_char); 722 CharWordIDMap::iterator char_iter =
651 if (char_iter != char_word_map_.end()) { 723 private_data.char_word_map_.find(uni_char);
724 if (char_iter != private_data.char_word_map_.end()) {
652 // Update existing entry in the char/word index. 725 // Update existing entry in the char/word index.
653 WordIDSet& word_id_set(char_iter->second); 726 WordIDSet& word_id_set(char_iter->second);
654 word_id_set.insert(word_id); 727 word_id_set.insert(word_id);
655 } else { 728 } else {
656 // Create a new entry in the char/word index. 729 // Create a new entry in the char/word index.
657 WordIDSet word_id_set; 730 WordIDSet word_id_set;
658 word_id_set.insert(word_id); 731 word_id_set.insert(word_id);
659 char_word_map_[uni_char] = word_id_set; 732 private_data.char_word_map_[uni_char] = word_id_set;
660 } 733 }
661 } 734 }
662 } 735 }
663 736
664 InMemoryURLIndex::WordIDSet InMemoryURLIndex::WordIDSetForTermChars(
665 const Char16Set& term_chars) {
666 WordIDSet word_id_set;
667 for (Char16Set::const_iterator c_iter = term_chars.begin();
668 c_iter != term_chars.end(); ++c_iter) {
669 CharWordIDMap::iterator char_iter = char_word_map_.find(*c_iter);
670 if (char_iter == char_word_map_.end()) {
671 // A character was not found so there are no matching results: bail.
672 word_id_set.clear();
673 break;
674 }
675 WordIDSet& char_word_id_set(char_iter->second);
676 // It is possible for there to no longer be any words associated with
677 // a particular character. Give up in that case.
678 if (char_word_id_set.empty()) {
679 word_id_set.clear();
680 break;
681 }
682
683 if (c_iter == term_chars.begin()) {
684 // First character results becomes base set of results.
685 word_id_set = char_word_id_set;
686 } else {
687 // Subsequent character results get intersected in.
688 WordIDSet new_word_id_set;
689 std::set_intersection(word_id_set.begin(), word_id_set.end(),
690 char_word_id_set.begin(), char_word_id_set.end(),
691 std::inserter(new_word_id_set,
692 new_word_id_set.begin()));
693 word_id_set.swap(new_word_id_set);
694 }
695 }
696 return word_id_set;
697 }
698
699 // static 737 // static
700 TermMatches InMemoryURLIndex::MatchTermInString(const string16& term, 738 // TODO(mrossetti): This can be made a ctor for ScoredHistoryMatch.
701 const string16& string,
702 int term_num) {
703 const size_t kMaxCompareLength = 2048;
704 const string16& short_string = (string.length() > kMaxCompareLength) ?
705 string.substr(0, kMaxCompareLength) : string;
706 TermMatches matches;
707 for (size_t location = short_string.find(term); location != string16::npos;
708 location = short_string.find(term, location + 1)) {
709 matches.push_back(TermMatch(term_num, location, term.length()));
710 }
711 return matches;
712 }
713
714 // static
715 TermMatches InMemoryURLIndex::SortAndDeoverlap(const TermMatches& matches) {
716 if (matches.empty())
717 return matches;
718 TermMatches sorted_matches = matches;
719 std::sort(sorted_matches.begin(), sorted_matches.end(), MatchOffsetLess);
720 TermMatches clean_matches;
721 TermMatch last_match = sorted_matches[0];
722 clean_matches.push_back(last_match);
723 for (TermMatches::const_iterator iter = sorted_matches.begin() + 1;
724 iter != sorted_matches.end(); ++iter) {
725 if (iter->offset >= last_match.offset + last_match.length) {
726 last_match = *iter;
727 clean_matches.push_back(last_match);
728 }
729 }
730 return clean_matches;
731 }
732
733 // static
734 std::vector<size_t> InMemoryURLIndex::OffsetsFromTermMatches(
735 const TermMatches& matches) {
736 std::vector<size_t> offsets;
737 for (TermMatches::const_iterator i = matches.begin(); i != matches.end(); ++i)
738 offsets.push_back(i->offset);
739 return offsets;
740 }
741
742 // static
743 TermMatches InMemoryURLIndex::ReplaceOffsetsInTermMatches(
744 const TermMatches& matches,
745 const std::vector<size_t>& offsets) {
746 DCHECK_EQ(matches.size(), offsets.size());
747 TermMatches new_matches;
748 std::vector<size_t>::const_iterator offset_iter = offsets.begin();
749 for (TermMatches::const_iterator term_iter = matches.begin();
750 term_iter != matches.end(); ++term_iter, ++offset_iter) {
751 if (*offset_iter != string16::npos) {
752 TermMatch new_match(*term_iter);
753 new_match.offset = *offset_iter;
754 new_matches.push_back(new_match);
755 }
756 }
757 return new_matches;
758 }
759
760 // static
761 ScoredHistoryMatch InMemoryURLIndex::ScoredMatchForURL( 739 ScoredHistoryMatch InMemoryURLIndex::ScoredMatchForURL(
762 const URLRow& row, 740 const URLRow& row,
763 const String16Vector& terms) { 741 const String16Vector& terms) {
764 ScoredHistoryMatch match(row); 742 ScoredHistoryMatch match(row);
765 GURL gurl = row.url(); 743 GURL gurl = row.url();
766 if (!gurl.is_valid()) 744 if (!gurl.is_valid())
767 return match; 745 return match;
768 746
769 // Figure out where each search term appears in the URL and/or page title 747 // Figure out where each search term appears in the URL and/or page title
770 // so that we can score as well as provide autocomplete highlighting. 748 // so that we can score as well as provide autocomplete highlighting.
771 string16 url = base::i18n::ToLower(UTF8ToUTF16(gurl.spec())); 749 string16 url = base::i18n::ToLower(UTF8ToUTF16(gurl.spec()));
772 string16 title = base::i18n::ToLower(row.title()); 750 string16 title = base::i18n::ToLower(row.title());
773 int term_num = 0; 751 int term_num = 0;
774 for (String16Vector::const_iterator iter = terms.begin(); iter != terms.end(); 752 for (String16Vector::const_iterator iter = terms.begin(); iter != terms.end();
775 ++iter, ++term_num) { 753 ++iter, ++term_num) {
776 string16 term = *iter; 754 string16 term = *iter;
777 TermMatches url_term_matches = MatchTermInString(term, url, term_num); 755 TermMatches url_term_matches = MatchTermInString(term, url, term_num);
778 TermMatches title_term_matches = MatchTermInString(term, title, term_num); 756 TermMatches title_term_matches = MatchTermInString(term, title, term_num);
779 if (url_term_matches.empty() && title_term_matches.empty()) 757 if (url_term_matches.empty() && title_term_matches.empty())
780 return match; // A term was not found in either URL or title - reject. 758 return match; // A term was not found in either URL or title - reject.
781 match.url_matches.insert(match.url_matches.end(), url_term_matches.begin(), 759 match.url_matches.insert(match.url_matches.end(), url_term_matches.begin(),
782 url_term_matches.end()); 760 url_term_matches.end());
783 match.title_matches.insert(match.title_matches.end(), 761 match.title_matches.insert(match.title_matches.end(),
784 title_term_matches.begin(), 762 title_term_matches.begin(),
785 title_term_matches.end()); 763 title_term_matches.end());
786 } 764 }
787 765
788 // Sort matches by offset and eliminate any which overlap. 766 // Sort matches by offset and eliminate any which overlap.
789 match.url_matches = SortAndDeoverlap(match.url_matches); 767 match.url_matches = SortAndDeoverlapMatches(match.url_matches);
790 match.title_matches = SortAndDeoverlap(match.title_matches); 768 match.title_matches = SortAndDeoverlapMatches(match.title_matches);
791 769
792 // We should not (currently) inline autocomplete a result unless both of the 770 // We should not (currently) inline autocomplete a result unless both of the
793 // following are true: 771 // following are true:
794 // * There is exactly one substring matches in the URL, and 772 // * There is exactly one substring matches in the URL, and
795 // * The one URL match starts at the beginning of the URL. 773 // * The one URL match starts at the beginning of the URL.
796 match.can_inline = 774 match.can_inline =
797 match.url_matches.size() == 1 && match.url_matches[0].offset == 0; 775 match.url_matches.size() == 1 && match.url_matches[0].offset == 0;
798 776
799 // Get partial scores based on term matching. Note that the score for 777 // Get partial scores based on term matching. Note that the score for
800 // each of the URL and title are adjusted by the fraction of the 778 // each of the URL and title are adjusted by the fraction of the
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 872
895 // Scale the sum of the three components above into a single score component 873 // Scale the sum of the three components above into a single score component
896 // on the same scale as that used in ScoredMatchForURL(). 874 // on the same scale as that used in ScoredMatchForURL().
897 return ScoreForValue(raw_score, kTermScoreLevel); 875 return ScoreForValue(raw_score, kTermScoreLevel);
898 } 876 }
899 877
900 InMemoryURLIndex::AddHistoryMatch::AddHistoryMatch( 878 InMemoryURLIndex::AddHistoryMatch::AddHistoryMatch(
901 const InMemoryURLIndex& index, 879 const InMemoryURLIndex& index,
902 const String16Vector& lower_terms) 880 const String16Vector& lower_terms)
903 : index_(index), 881 : index_(index),
904 lower_terms_(lower_terms) { 882 lower_terms_(lower_terms) {}
905 }
906 883
907 InMemoryURLIndex::AddHistoryMatch::~AddHistoryMatch() {} 884 InMemoryURLIndex::AddHistoryMatch::~AddHistoryMatch() {}
908 885
909 void InMemoryURLIndex::AddHistoryMatch::operator()( 886 void InMemoryURLIndex::AddHistoryMatch::operator()(const HistoryID history_id) {
910 const InMemoryURLIndex::HistoryID history_id) {
911 HistoryInfoMap::const_iterator hist_pos = 887 HistoryInfoMap::const_iterator hist_pos =
912 index_.history_info_map_.find(history_id); 888 index_.private_data_->history_info_map_.find(history_id);
913 // Note that a history_id may be present in the word_id_history_map_ yet not 889 // Note that a history_id may be present in the word_id_history_map_ yet not
914 // be found in the history_info_map_. This occurs when an item has been 890 // be found in the history_info_map_. This occurs when an item has been
915 // deleted by the user or the item no longer qualifies as a quick result. 891 // deleted by the user or the item no longer qualifies as a quick result.
916 if (hist_pos != index_.history_info_map_.end()) { 892 if (hist_pos != index_.private_data_->history_info_map_.end()) {
917 const URLRow& hist_item = hist_pos->second; 893 const URLRow& hist_item = hist_pos->second;
918 ScoredHistoryMatch match(ScoredMatchForURL(hist_item, lower_terms_)); 894 ScoredHistoryMatch match(ScoredMatchForURL(hist_item, lower_terms_));
919 if (match.raw_score > 0) 895 if (match.raw_score > 0)
920 scored_matches_.push_back(match); 896 scored_matches_.push_back(match);
921 } 897 }
922 } 898 }
923 899
924 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) { 900 bool InMemoryURLIndex::GetCacheFilePath(FilePath* file_path) {
925 if (history_dir_.empty()) 901 if (history_dir_.empty())
926 return false; 902 return false;
927 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache")); 903 *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
928 return true; 904 return true;
929 } 905 }
930 906
931 bool InMemoryURLIndex::URLSchemeIsWhitelisted(const GURL& gurl) const { 907 bool InMemoryURLIndex::URLSchemeIsWhitelisted(const GURL& gurl) const {
932 return scheme_whitelist_.find(gurl.scheme()) != scheme_whitelist_.end(); 908 return scheme_whitelist_.find(gurl.scheme()) != scheme_whitelist_.end();
933 } 909 }
934 910
935 void InMemoryURLIndex::SavePrivateData(InMemoryURLIndexCacheItem* cache) const { 911 void InMemoryURLIndex::SavePrivateData(InMemoryURLIndexCacheItem* cache) const {
936 DCHECK(cache); 912 DCHECK(cache);
937 cache->set_timestamp(base::Time::Now().ToInternalValue()); 913 cache->set_timestamp(base::Time::Now().ToInternalValue());
938 cache->set_history_item_count(history_item_count_); 914 cache->set_history_item_count(private_data_->history_item_count_);
939 SaveWordList(cache); 915 SaveWordList(cache);
940 SaveWordMap(cache); 916 SaveWordMap(cache);
941 SaveCharWordMap(cache); 917 SaveCharWordMap(cache);
942 SaveWordIDHistoryMap(cache); 918 SaveWordIDHistoryMap(cache);
943 SaveHistoryInfoMap(cache); 919 SaveHistoryInfoMap(cache);
944 } 920 }
945 921
946 bool InMemoryURLIndex::RestorePrivateData( 922 bool InMemoryURLIndex::RestorePrivateData(
947 const InMemoryURLIndexCacheItem& cache) { 923 const InMemoryURLIndexCacheItem& cache) {
948 last_saved_ = base::Time::FromInternalValue(cache.timestamp()); 924 last_saved_ = base::Time::FromInternalValue(cache.timestamp());
949 history_item_count_ = cache.history_item_count(); 925 private_data_->history_item_count_ = cache.history_item_count();
950 return (history_item_count_ == 0) || (RestoreWordList(cache) && 926 return (private_data_->history_item_count_ == 0) || (RestoreWordList(cache) &&
951 RestoreWordMap(cache) && RestoreCharWordMap(cache) && 927 RestoreWordMap(cache) && RestoreCharWordMap(cache) &&
952 RestoreWordIDHistoryMap(cache) && RestoreHistoryInfoMap(cache)); 928 RestoreWordIDHistoryMap(cache) && RestoreHistoryInfoMap(cache));
953 } 929 }
954 930
955
956 void InMemoryURLIndex::SaveWordList(InMemoryURLIndexCacheItem* cache) const { 931 void InMemoryURLIndex::SaveWordList(InMemoryURLIndexCacheItem* cache) const {
957 if (word_list_.empty()) 932 if (private_data_->word_list_.empty())
958 return; 933 return;
959 WordListItem* list_item = cache->mutable_word_list(); 934 WordListItem* list_item = cache->mutable_word_list();
960 list_item->set_word_count(word_list_.size()); 935 list_item->set_word_count(private_data_->word_list_.size());
961 for (String16Vector::const_iterator iter = word_list_.begin(); 936 for (String16Vector::const_iterator iter = private_data_->word_list_.begin();
962 iter != word_list_.end(); ++iter) 937 iter != private_data_->word_list_.end(); ++iter)
963 list_item->add_word(UTF16ToUTF8(*iter)); 938 list_item->add_word(UTF16ToUTF8(*iter));
964 } 939 }
965 940
966 bool InMemoryURLIndex::RestoreWordList(const InMemoryURLIndexCacheItem& cache) { 941 bool InMemoryURLIndex::RestoreWordList(const InMemoryURLIndexCacheItem& cache) {
967 if (!cache.has_word_list()) 942 if (!cache.has_word_list())
968 return false; 943 return false;
969 const WordListItem& list_item(cache.word_list()); 944 const WordListItem& list_item(cache.word_list());
970 uint32 expected_item_count = list_item.word_count(); 945 uint32 expected_item_count = list_item.word_count();
971 uint32 actual_item_count = list_item.word_size(); 946 uint32 actual_item_count = list_item.word_size();
972 if (actual_item_count == 0 || actual_item_count != expected_item_count) 947 if (actual_item_count == 0 || actual_item_count != expected_item_count)
973 return false; 948 return false;
974 const RepeatedPtrField<std::string>& words(list_item.word()); 949 const RepeatedPtrField<std::string>& words(list_item.word());
975 for (RepeatedPtrField<std::string>::const_iterator iter = words.begin(); 950 for (RepeatedPtrField<std::string>::const_iterator iter = words.begin();
976 iter != words.end(); ++iter) 951 iter != words.end(); ++iter)
977 word_list_.push_back(UTF8ToUTF16(*iter)); 952 private_data_->word_list_.push_back(UTF8ToUTF16(*iter));
978 return true; 953 return true;
979 } 954 }
980 955
981 void InMemoryURLIndex::SaveWordMap(InMemoryURLIndexCacheItem* cache) const { 956 void InMemoryURLIndex::SaveWordMap(InMemoryURLIndexCacheItem* cache) const {
982 if (word_map_.empty()) 957 if (private_data_->word_map_.empty())
983 return; 958 return;
984 WordMapItem* map_item = cache->mutable_word_map(); 959 WordMapItem* map_item = cache->mutable_word_map();
985 map_item->set_item_count(word_map_.size()); 960 map_item->set_item_count(private_data_->word_map_.size());
986 for (WordMap::const_iterator iter = word_map_.begin(); 961 for (WordMap::const_iterator iter = private_data_->word_map_.begin();
987 iter != word_map_.end(); ++iter) { 962 iter != private_data_->word_map_.end(); ++iter) {
988 WordMapEntry* map_entry = map_item->add_word_map_entry(); 963 WordMapEntry* map_entry = map_item->add_word_map_entry();
989 map_entry->set_word(UTF16ToUTF8(iter->first)); 964 map_entry->set_word(UTF16ToUTF8(iter->first));
990 map_entry->set_word_id(iter->second); 965 map_entry->set_word_id(iter->second);
991 } 966 }
992 } 967 }
993 968
994 bool InMemoryURLIndex::RestoreWordMap(const InMemoryURLIndexCacheItem& cache) { 969 bool InMemoryURLIndex::RestoreWordMap(const InMemoryURLIndexCacheItem& cache) {
995 if (!cache.has_word_map()) 970 if (!cache.has_word_map())
996 return false; 971 return false;
997 const WordMapItem& list_item(cache.word_map()); 972 const WordMapItem& list_item(cache.word_map());
998 uint32 expected_item_count = list_item.item_count(); 973 uint32 expected_item_count = list_item.item_count();
999 uint32 actual_item_count = list_item.word_map_entry_size(); 974 uint32 actual_item_count = list_item.word_map_entry_size();
1000 if (actual_item_count == 0 || actual_item_count != expected_item_count) 975 if (actual_item_count == 0 || actual_item_count != expected_item_count)
1001 return false; 976 return false;
1002 const RepeatedPtrField<WordMapEntry>& entries(list_item.word_map_entry()); 977 const RepeatedPtrField<WordMapEntry>& entries(list_item.word_map_entry());
1003 for (RepeatedPtrField<WordMapEntry>::const_iterator iter = entries.begin(); 978 for (RepeatedPtrField<WordMapEntry>::const_iterator iter = entries.begin();
1004 iter != entries.end(); ++iter) 979 iter != entries.end(); ++iter)
1005 word_map_[UTF8ToUTF16(iter->word())] = iter->word_id(); 980 private_data_->word_map_[UTF8ToUTF16(iter->word())] = iter->word_id();
1006 return true; 981 return true;
1007 } 982 }
1008 983
1009 void InMemoryURLIndex::SaveCharWordMap(InMemoryURLIndexCacheItem* cache) const { 984 void InMemoryURLIndex::SaveCharWordMap(InMemoryURLIndexCacheItem* cache) const {
1010 if (char_word_map_.empty()) 985 if (private_data_->char_word_map_.empty())
1011 return; 986 return;
1012 CharWordMapItem* map_item = cache->mutable_char_word_map(); 987 CharWordMapItem* map_item = cache->mutable_char_word_map();
1013 map_item->set_item_count(char_word_map_.size()); 988 map_item->set_item_count(private_data_->char_word_map_.size());
1014 for (CharWordIDMap::const_iterator iter = char_word_map_.begin(); 989 for (CharWordIDMap::const_iterator iter =
1015 iter != char_word_map_.end(); ++iter) { 990 private_data_->char_word_map_.begin();
991 iter != private_data_->char_word_map_.end(); ++iter) {
1016 CharWordMapEntry* map_entry = map_item->add_char_word_map_entry(); 992 CharWordMapEntry* map_entry = map_item->add_char_word_map_entry();
1017 map_entry->set_char_16(iter->first); 993 map_entry->set_char_16(iter->first);
1018 const WordIDSet& word_id_set(iter->second); 994 const WordIDSet& word_id_set(iter->second);
1019 map_entry->set_item_count(word_id_set.size()); 995 map_entry->set_item_count(word_id_set.size());
1020 for (WordIDSet::const_iterator set_iter = word_id_set.begin(); 996 for (WordIDSet::const_iterator set_iter = word_id_set.begin();
1021 set_iter != word_id_set.end(); ++set_iter) 997 set_iter != word_id_set.end(); ++set_iter)
1022 map_entry->add_word_id(*set_iter); 998 map_entry->add_word_id(*set_iter);
1023 } 999 }
1024 } 1000 }
1025 1001
(...skipping 13 matching lines...) Expand all
1039 expected_item_count = iter->item_count(); 1015 expected_item_count = iter->item_count();
1040 actual_item_count = iter->word_id_size(); 1016 actual_item_count = iter->word_id_size();
1041 if (actual_item_count == 0 || actual_item_count != expected_item_count) 1017 if (actual_item_count == 0 || actual_item_count != expected_item_count)
1042 return false; 1018 return false;
1043 char16 uni_char = static_cast<char16>(iter->char_16()); 1019 char16 uni_char = static_cast<char16>(iter->char_16());
1044 WordIDSet word_id_set; 1020 WordIDSet word_id_set;
1045 const RepeatedField<int32>& word_ids(iter->word_id()); 1021 const RepeatedField<int32>& word_ids(iter->word_id());
1046 for (RepeatedField<int32>::const_iterator jiter = word_ids.begin(); 1022 for (RepeatedField<int32>::const_iterator jiter = word_ids.begin();
1047 jiter != word_ids.end(); ++jiter) 1023 jiter != word_ids.end(); ++jiter)
1048 word_id_set.insert(*jiter); 1024 word_id_set.insert(*jiter);
1049 char_word_map_[uni_char] = word_id_set; 1025 private_data_->char_word_map_[uni_char] = word_id_set;
1050 } 1026 }
1051 return true; 1027 return true;
1052 } 1028 }
1053 1029
1054 void InMemoryURLIndex::SaveWordIDHistoryMap(InMemoryURLIndexCacheItem* cache) 1030 void InMemoryURLIndex::SaveWordIDHistoryMap(InMemoryURLIndexCacheItem* cache)
1055 const { 1031 const {
1056 if (word_id_history_map_.empty()) 1032 if (private_data_->word_id_history_map_.empty())
1057 return; 1033 return;
1058 WordIDHistoryMapItem* map_item = cache->mutable_word_id_history_map(); 1034 WordIDHistoryMapItem* map_item = cache->mutable_word_id_history_map();
1059 map_item->set_item_count(word_id_history_map_.size()); 1035 map_item->set_item_count(private_data_->word_id_history_map_.size());
1060 for (WordIDHistoryMap::const_iterator iter = word_id_history_map_.begin(); 1036 for (WordIDHistoryMap::const_iterator iter =
1061 iter != word_id_history_map_.end(); ++iter) { 1037 private_data_->word_id_history_map_.begin();
1038 iter != private_data_->word_id_history_map_.end(); ++iter) {
1062 WordIDHistoryMapEntry* map_entry = 1039 WordIDHistoryMapEntry* map_entry =
1063 map_item->add_word_id_history_map_entry(); 1040 map_item->add_word_id_history_map_entry();
1064 map_entry->set_word_id(iter->first); 1041 map_entry->set_word_id(iter->first);
1065 const HistoryIDSet& history_id_set(iter->second); 1042 const HistoryIDSet& history_id_set(iter->second);
1066 map_entry->set_item_count(history_id_set.size()); 1043 map_entry->set_item_count(history_id_set.size());
1067 for (HistoryIDSet::const_iterator set_iter = history_id_set.begin(); 1044 for (HistoryIDSet::const_iterator set_iter = history_id_set.begin();
1068 set_iter != history_id_set.end(); ++set_iter) 1045 set_iter != history_id_set.end(); ++set_iter)
1069 map_entry->add_history_id(*set_iter); 1046 map_entry->add_history_id(*set_iter);
1070 } 1047 }
1071 } 1048 }
(...skipping 12 matching lines...) Expand all
1084 for (RepeatedPtrField<WordIDHistoryMapEntry>::const_iterator iter = 1061 for (RepeatedPtrField<WordIDHistoryMapEntry>::const_iterator iter =
1085 entries.begin(); iter != entries.end(); ++iter) { 1062 entries.begin(); iter != entries.end(); ++iter) {
1086 expected_item_count = iter->item_count(); 1063 expected_item_count = iter->item_count();
1087 actual_item_count = iter->history_id_size(); 1064 actual_item_count = iter->history_id_size();
1088 if (actual_item_count == 0 || actual_item_count != expected_item_count) 1065 if (actual_item_count == 0 || actual_item_count != expected_item_count)
1089 return false; 1066 return false;
1090 WordID word_id = iter->word_id(); 1067 WordID word_id = iter->word_id();
1091 HistoryIDSet history_id_set; 1068 HistoryIDSet history_id_set;
1092 const RepeatedField<int64>& history_ids(iter->history_id()); 1069 const RepeatedField<int64>& history_ids(iter->history_id());
1093 for (RepeatedField<int64>::const_iterator jiter = history_ids.begin(); 1070 for (RepeatedField<int64>::const_iterator jiter = history_ids.begin();
1094 jiter != history_ids.end(); ++jiter) 1071 jiter != history_ids.end(); ++jiter) {
1095 history_id_set.insert(*jiter); 1072 history_id_set.insert(*jiter);
1096 word_id_history_map_[word_id] = history_id_set; 1073 private_data_->AddToHistoryIDWordMap(*jiter, word_id);
1074 }
1075 private_data_->word_id_history_map_[word_id] = history_id_set;
1097 } 1076 }
1098 return true; 1077 return true;
1099 } 1078 }
1100 1079
1101 void InMemoryURLIndex::SaveHistoryInfoMap( 1080 void InMemoryURLIndex::SaveHistoryInfoMap(
1102 InMemoryURLIndexCacheItem* cache) const { 1081 InMemoryURLIndexCacheItem* cache) const {
1103 if (history_info_map_.empty()) 1082 if (private_data_->history_info_map_.empty())
1104 return; 1083 return;
1105 HistoryInfoMapItem* map_item = cache->mutable_history_info_map(); 1084 HistoryInfoMapItem* map_item = cache->mutable_history_info_map();
1106 map_item->set_item_count(history_info_map_.size()); 1085 map_item->set_item_count(private_data_->history_info_map_.size());
1107 for (HistoryInfoMap::const_iterator iter = history_info_map_.begin(); 1086 for (HistoryInfoMap::const_iterator iter =
1108 iter != history_info_map_.end(); ++iter) { 1087 private_data_->history_info_map_.begin();
1088 iter != private_data_->history_info_map_.end(); ++iter) {
1109 HistoryInfoMapEntry* map_entry = map_item->add_history_info_map_entry(); 1089 HistoryInfoMapEntry* map_entry = map_item->add_history_info_map_entry();
1110 map_entry->set_history_id(iter->first); 1090 map_entry->set_history_id(iter->first);
1111 const URLRow& url_row(iter->second); 1091 const URLRow& url_row(iter->second);
1112 // Note: We only save information that contributes to the index so there 1092 // Note: We only save information that contributes to the index so there
1113 // is no need to save search_term_cache_ (not persistent), 1093 // is no need to save search_term_cache_ (not persistent),
1114 // languages_, etc. 1094 // languages_, etc.
1115 map_entry->set_visit_count(url_row.visit_count()); 1095 map_entry->set_visit_count(url_row.visit_count());
1116 map_entry->set_typed_count(url_row.typed_count()); 1096 map_entry->set_typed_count(url_row.typed_count());
1117 map_entry->set_last_visit(url_row.last_visit().ToInternalValue()); 1097 map_entry->set_last_visit(url_row.last_visit().ToInternalValue());
1118 map_entry->set_url(url_row.url().spec()); 1098 map_entry->set_url(url_row.url().spec());
(...skipping 17 matching lines...) Expand all
1136 HistoryID history_id = iter->history_id(); 1116 HistoryID history_id = iter->history_id();
1137 GURL url(iter->url()); 1117 GURL url(iter->url());
1138 URLRow url_row(url, history_id); 1118 URLRow url_row(url, history_id);
1139 url_row.set_visit_count(iter->visit_count()); 1119 url_row.set_visit_count(iter->visit_count());
1140 url_row.set_typed_count(iter->typed_count()); 1120 url_row.set_typed_count(iter->typed_count());
1141 url_row.set_last_visit(base::Time::FromInternalValue(iter->last_visit())); 1121 url_row.set_last_visit(base::Time::FromInternalValue(iter->last_visit()));
1142 if (iter->has_title()) { 1122 if (iter->has_title()) {
1143 string16 title(UTF8ToUTF16(iter->title())); 1123 string16 title(UTF8ToUTF16(iter->title()));
1144 url_row.set_title(title); 1124 url_row.set_title(title);
1145 } 1125 }
1146 history_info_map_[history_id] = url_row; 1126 private_data_->history_info_map_[history_id] = url_row;
1147 } 1127 }
1148 return true; 1128 return true;
1149 } 1129 }
1150 1130
1151 } // namespace history 1131 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698