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