history_types.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/history/history_types.h" 6 7#include <limits> 8 9#include "base/logging.h" 10#include "base/stl_util-inl.h" 11 12namespace history { 13 14// URLRow ---------------------------------------------------------------------- 15 16URLRow::URLRow() { 17 Initialize(); 18} 19 20URLRow::URLRow(const GURL& url) : url_(url) { 21 // Initialize will not set the URL, so our initialization above will stay. 22 Initialize(); 23} 24 25URLRow::URLRow(const GURL& url, URLID id) : url_(url) { 26 // Initialize will not set the URL, so our initialization above will stay. 27 Initialize(); 28 // Initialize will zero the id_, so set it here. 29 id_ = id; 30} 31 32URLRow::~URLRow() { 33} 34 35URLRow& URLRow::operator=(const URLRow& other) { 36 id_ = other.id_; 37 url_ = other.url_; 38 title_ = other.title_; 39 visit_count_ = other.visit_count_; 40 typed_count_ = other.typed_count_; 41 last_visit_ = other.last_visit_; 42 hidden_ = other.hidden_; 43 favicon_id_ = other.favicon_id_; 44 return *this; 45} 46 47void URLRow::Swap(URLRow* other) { 48 std::swap(id_, other->id_); 49 url_.Swap(&other->url_); 50 title_.swap(other->title_); 51 std::swap(visit_count_, other->visit_count_); 52 std::swap(typed_count_, other->typed_count_); 53 std::swap(last_visit_, other->last_visit_); 54 std::swap(hidden_, other->hidden_); 55 std::swap(favicon_id_, other->favicon_id_); 56} 57 58void URLRow::Initialize() { 59 id_ = 0; 60 visit_count_ = 0; 61 typed_count_ = 0; 62 last_visit_ = base::Time(); 63 hidden_ = false; 64 favicon_id_ = 0; 65} 66 67// VisitRow -------------------------------------------------------------------- 68 69VisitRow::VisitRow() 70 : visit_id(0), 71 url_id(0), 72 referring_visit(0), 73 transition(PageTransition::LINK), 74 segment_id(0), 75 is_indexed(false) { 76} 77 78VisitRow::VisitRow(URLID arg_url_id, 79 base::Time arg_visit_time, 80 VisitID arg_referring_visit, 81 PageTransition::Type arg_transition, 82 SegmentID arg_segment_id) 83 : visit_id(0), 84 url_id(arg_url_id), 85 visit_time(arg_visit_time), 86 referring_visit(arg_referring_visit), 87 transition(arg_transition), 88 segment_id(arg_segment_id), 89 is_indexed(false) { 90} 91 92VisitRow::~VisitRow() { 93} 94 95// Favicons ------------------------------------------------------------------- 96 97ImportedFavIconUsage::ImportedFavIconUsage() { 98} 99 100ImportedFavIconUsage::~ImportedFavIconUsage() { 101} 102 103// StarredEntry ---------------------------------------------------------------- 104 105StarredEntry::StarredEntry() 106 : id(0), 107 parent_group_id(0), 108 group_id(0), 109 visual_order(0), 110 type(URL), 111 url_id(0) { 112} 113 114StarredEntry::~StarredEntry() { 115} 116 117void StarredEntry::Swap(StarredEntry* other) { 118 std::swap(id, other->id); 119 title.swap(other->title); 120 std::swap(date_added, other->date_added); 121 std::swap(parent_group_id, other->parent_group_id); 122 std::swap(group_id, other->group_id); 123 std::swap(visual_order, other->visual_order); 124 std::swap(type, other->type); 125 url.Swap(&other->url); 126 std::swap(url_id, other->url_id); 127 std::swap(date_group_modified, other->date_group_modified); 128} 129 130// URLResult ------------------------------------------------------------------- 131 132URLResult::URLResult() { 133} 134 135URLResult::URLResult(const GURL& url, base::Time visit_time) 136 : URLRow(url), 137 visit_time_(visit_time) { 138} 139 140URLResult::URLResult(const GURL& url, 141 const Snippet::MatchPositions& title_matches) 142 : URLRow(url) { 143 title_match_positions_ = title_matches; 144} 145 146URLResult::~URLResult() { 147} 148 149void URLResult::SwapResult(URLResult* other) { 150 URLRow::Swap(other); 151 std::swap(visit_time_, other->visit_time_); 152 snippet_.Swap(&other->snippet_); 153 title_match_positions_.swap(other->title_match_positions_); 154} 155 156// QueryResults ---------------------------------------------------------------- 157 158QueryResults::QueryResults() : reached_beginning_(false) { 159} 160 161QueryResults::~QueryResults() { 162 // Free all the URL objects. 163 STLDeleteContainerPointers(results_.begin(), results_.end()); 164} 165 166const size_t* QueryResults::MatchesForURL(const GURL& url, 167 size_t* num_matches) const { 168 URLToResultIndices::const_iterator found = url_to_results_.find(url); 169 if (found == url_to_results_.end()) { 170 if (num_matches) 171 *num_matches = 0; 172 return NULL; 173 } 174 175 // All entries in the map should have at least one index, otherwise it 176 // shouldn't be in the map. 177 DCHECK(!found->second->empty()); 178 if (num_matches) 179 *num_matches = found->second->size(); 180 return &found->second->front(); 181} 182 183void QueryResults::Swap(QueryResults* other) { 184 std::swap(first_time_searched_, other->first_time_searched_); 185 std::swap(reached_beginning_, other->reached_beginning_); 186 results_.swap(other->results_); 187 url_to_results_.swap(other->url_to_results_); 188} 189 190void QueryResults::AppendURLBySwapping(URLResult* result) { 191 URLResult* new_result = new URLResult; 192 new_result->SwapResult(result); 193 194 results_.push_back(new_result); 195 AddURLUsageAtIndex(new_result->url(), results_.size() - 1); 196} 197 198void QueryResults::AppendResultsBySwapping(QueryResults* other, 199 bool remove_dupes) { 200 if (remove_dupes) { 201 // Delete all entries in the other array that are already in this one. 202 for (size_t i = 0; i < results_.size(); i++) 203 other->DeleteURL(results_[i]->url()); 204 } 205 206 if (first_time_searched_ > other->first_time_searched_) 207 std::swap(first_time_searched_, other->first_time_searched_); 208 209 if (reached_beginning_ != other->reached_beginning_) 210 std::swap(reached_beginning_, other->reached_beginning_); 211 212 for (size_t i = 0; i < other->results_.size(); i++) { 213 // Just transfer pointer ownership. 214 results_.push_back(other->results_[i]); 215 AddURLUsageAtIndex(results_.back()->url(), results_.size() - 1); 216 } 217 218 // We just took ownership of all the results in the input vector. 219 other->results_.clear(); 220 other->url_to_results_.clear(); 221} 222 223void QueryResults::DeleteURL(const GURL& url) { 224 // Delete all instances of this URL. We re-query each time since each 225 // mutation will cause the indices to change. 226 while (const size_t* match_indices = MatchesForURL(url, NULL)) 227 DeleteRange(*match_indices, *match_indices); 228} 229 230void QueryResults::DeleteRange(size_t begin, size_t end) { 231 DCHECK(begin <= end && begin < size() && end < size()); 232 233 // First delete the pointers in the given range and store all the URLs that 234 // were modified. We will delete references to these later. 235 std::set<GURL> urls_modified; 236 for (size_t i = begin; i <= end; i++) { 237 urls_modified.insert(results_[i]->url()); 238 delete results_[i]; 239 results_[i] = NULL; 240 } 241 242 // Now just delete that range in the vector en masse (the STL ending is 243 // exclusive, while ours is inclusive, hence the +1). 244 results_.erase(results_.begin() + begin, results_.begin() + end + 1); 245 246 // Delete the indicies referencing the deleted entries. 247 for (std::set<GURL>::const_iterator url = urls_modified.begin(); 248 url != urls_modified.end(); ++url) { 249 URLToResultIndices::iterator found = url_to_results_.find(*url); 250 if (found == url_to_results_.end()) { 251 NOTREACHED(); 252 continue; 253 } 254 255 // Need a signed loop type since we do -- which may take us to -1. 256 for (int match = 0; match < static_cast<int>(found->second->size()); 257 match++) { 258 if (found->second[match] >= begin && found->second[match] <= end) { 259 // Remove this referece from the list. 260 found->second->erase(found->second->begin() + match); 261 match--; 262 } 263 } 264 265 // Clear out an empty lists if we just made one. 266 if (found->second->empty()) 267 url_to_results_.erase(found); 268 } 269 270 // Shift all other indices over to account for the removed ones. 271 AdjustResultMap(end + 1, std::numeric_limits<size_t>::max(), 272 -static_cast<ptrdiff_t>(end - begin + 1)); 273} 274 275void QueryResults::AddURLUsageAtIndex(const GURL& url, size_t index) { 276 URLToResultIndices::iterator found = url_to_results_.find(url); 277 if (found != url_to_results_.end()) { 278 // The URL is already in the list, so we can just append the new index. 279 found->second->push_back(index); 280 return; 281 } 282 283 // Need to add a new entry for this URL. 284 StackVector<size_t, 4> new_list; 285 new_list->push_back(index); 286 url_to_results_[url] = new_list; 287} 288 289void QueryResults::AdjustResultMap(size_t begin, size_t end, ptrdiff_t delta) { 290 for (URLToResultIndices::iterator i = url_to_results_.begin(); 291 i != url_to_results_.end(); ++i) { 292 for (size_t match = 0; match < i->second->size(); match++) { 293 size_t match_index = i->second[match]; 294 if (match_index >= begin && match_index <= end) 295 i->second[match] += delta; 296 } 297 } 298} 299 300// QueryOptions ---------------------------------------------------------------- 301 302QueryOptions::QueryOptions() : max_count(0) {} 303 304void QueryOptions::SetRecentDayRange(int days_ago) { 305 end_time = base::Time::Now(); 306 begin_time = end_time - base::TimeDelta::FromDays(days_ago); 307} 308 309// KeywordSearchTermVisit ----------------------------------------------------- 310 311KeywordSearchTermVisit::KeywordSearchTermVisit() {} 312 313KeywordSearchTermVisit::~KeywordSearchTermVisit() {} 314 315// KeywordSearchTermRow -------------------------------------------------------- 316 317KeywordSearchTermRow::KeywordSearchTermRow() : keyword_id(0), url_id(0) {} 318 319KeywordSearchTermRow::~KeywordSearchTermRow() {} 320 321// MostVisitedURL -------------------------------------------------------------- 322 323MostVisitedURL::MostVisitedURL() {} 324 325MostVisitedURL::MostVisitedURL(const GURL& in_url, 326 const GURL& in_favicon_url, 327 const string16& in_title) 328 : url(in_url), 329 favicon_url(in_favicon_url), 330 title(in_title) { 331} 332 333MostVisitedURL::~MostVisitedURL() {} 334 335// Images --------------------------------------------------------------------- 336 337Images::Images() {} 338 339Images::~Images() {} 340 341// TopSitesDelta -------------------------------------------------------------- 342 343TopSitesDelta::TopSitesDelta() {} 344 345TopSitesDelta::~TopSitesDelta() {} 346 347// HistoryAddPageArgs --------------------------------------------------------- 348 349HistoryAddPageArgs::HistoryAddPageArgs( 350 const GURL& arg_url, 351 base::Time arg_time, 352 const void* arg_id_scope, 353 int32 arg_page_id, 354 const GURL& arg_referrer, 355 const history::RedirectList& arg_redirects, 356 PageTransition::Type arg_transition, 357 VisitSource arg_source, 358 bool arg_did_replace_entry) 359 : url(arg_url), 360 time(arg_time), 361 id_scope(arg_id_scope), 362 page_id(arg_page_id), 363 referrer(arg_referrer), 364 redirects(arg_redirects), 365 transition(arg_transition), 366 visit_source(arg_source), 367 did_replace_entry(arg_did_replace_entry) { 368} 369 370HistoryAddPageArgs::~HistoryAddPageArgs() {} 371 372HistoryAddPageArgs* HistoryAddPageArgs::Clone() const { 373 return new HistoryAddPageArgs( 374 url, time, id_scope, page_id, referrer, redirects, transition, 375 visit_source, did_replace_entry); 376} 377 378ThumbnailMigration::ThumbnailMigration() {} 379 380ThumbnailMigration::~ThumbnailMigration() {} 381 382MostVisitedThumbnails::MostVisitedThumbnails() {} 383 384MostVisitedThumbnails::~MostVisitedThumbnails() {} 385 386// Autocomplete thresholds ----------------------------------------------------- 387 388const int kLowQualityMatchTypedLimit = 1; 389const int kLowQualityMatchVisitLimit = 3; 390const int kLowQualityMatchAgeLimitInDays = 3; 391 392base::Time AutocompleteAgeThreshold() { 393 return (base::Time::Now() - 394 base::TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays)); 395} 396 397bool RowQualifiesAsSignificant(const URLRow& row, 398 const base::Time& threshold) { 399 const base::Time& real_threshold = 400 threshold.is_null() ? AutocompleteAgeThreshold() : threshold; 401 return (row.typed_count() > kLowQualityMatchTypedLimit) || 402 (row.visit_count() > kLowQualityMatchVisitLimit) || 403 (row.last_visit() >= real_threshold); 404} 405 406} // namespace history 407