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 12 namespace history { 13 14 // URLRow ---------------------------------------------------------------------- 15 16 URLRow::URLRow() { 17 Initialize(); 18 } 19 20 URLRow::URLRow(const GURL& url) : url_(url) { 21 // Initialize will not set the URL, so our initialization above will stay. 22 Initialize(); 23 } 24 25 URLRow::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 32 URLRow::~URLRow() { 33 } 34 35 URLRow& 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 46 void 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 56 void 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 66 VisitRow::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 75 VisitRow::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 89 VisitRow::~VisitRow() { 90 } 91 92 // Favicons ------------------------------------------------------------------- 93 94 ImportedFaviconUsage::ImportedFaviconUsage() { 95 } 96 97 ImportedFaviconUsage::~ImportedFaviconUsage() { 98 } 99 100 // StarredEntry ---------------------------------------------------------------- 101 102 StarredEntry::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 111 StarredEntry::~StarredEntry() { 112 } 113 114 void 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 129 URLResult::URLResult() { 130 } 131 132 URLResult::URLResult(const GURL& url, base::Time visit_time) 133 : URLRow(url), 134 visit_time_(visit_time) { 135 } 136 137 URLResult::URLResult(const GURL& url, 138 const Snippet::MatchPositions& title_matches) 139 : URLRow(url) { 140 title_match_positions_ = title_matches; 141 } 142 143 URLResult::~URLResult() { 144 } 145 146 void 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 155 QueryResults::QueryResults() : reached_beginning_(false) { 156 } 157 158 QueryResults::~QueryResults() { 159 // Free all the URL objects. 160 STLDeleteContainerPointers(results_.begin(), results_.end()); 161 } 162 163 const 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 180 void 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 187 void 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 195 void 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 220 void 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 227 void 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 272 void 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 286 void 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 299 QueryOptions::QueryOptions() : max_count(0) {} 300 301 void 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 308 KeywordSearchTermVisit::KeywordSearchTermVisit() {} 309 310 KeywordSearchTermVisit::~KeywordSearchTermVisit() {} 311 312 // KeywordSearchTermRow -------------------------------------------------------- 313 314 KeywordSearchTermRow::KeywordSearchTermRow() : keyword_id(0), url_id(0) {} 315 316 KeywordSearchTermRow::~KeywordSearchTermRow() {} 317 318 // MostVisitedURL -------------------------------------------------------------- 319 320 MostVisitedURL::MostVisitedURL() {} 321 322 MostVisitedURL::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 330 MostVisitedURL::~MostVisitedURL() {} 331 332 // Images --------------------------------------------------------------------- 333 334 Images::Images() {} 335 336 Images::~Images() {} 337 338 // TopSitesDelta -------------------------------------------------------------- 339 340 TopSitesDelta::TopSitesDelta() {} 341 342 TopSitesDelta::~TopSitesDelta() {} 343 344 // HistoryAddPageArgs --------------------------------------------------------- 345 346 HistoryAddPageArgs::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 367 HistoryAddPageArgs::~HistoryAddPageArgs() {} 368 369 HistoryAddPageArgs* 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 375 ThumbnailMigration::ThumbnailMigration() {} 376 377 ThumbnailMigration::~ThumbnailMigration() {} 378 379 MostVisitedThumbnails::MostVisitedThumbnails() {} 380 381 MostVisitedThumbnails::~MostVisitedThumbnails() {} 382 383 // Autocomplete thresholds ----------------------------------------------------- 384 385 const int kLowQualityMatchTypedLimit = 1; 386 const int kLowQualityMatchVisitLimit = 3; 387 const int kLowQualityMatchAgeLimitInDays = 3; 388 389 base::Time AutocompleteAgeThreshold() { 390 return (base::Time::Now() - 391 base::TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays)); 392 } 393 394 bool 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 405 IconMapping::IconMapping() 406 : mapping_id(0), 407 icon_id(0), 408 icon_type(INVALID_ICON) { 409 } 410 411 IconMapping::~IconMapping() {} 412 413 414 FaviconData::FaviconData() 415 : known_icon(false), 416 expired(false), 417 icon_type(history::INVALID_ICON) { 418 } 419 420 FaviconData::~FaviconData() {} 421 422 bool FaviconData::is_valid() { 423 return known_icon && image_data.get() && image_data->size(); 424 } 425 426 } // namespace history 427