1 // Copyright (c) 2012 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.h" 11 #include "chrome/browser/history/page_usage_data.h" 12 13 namespace history { 14 15 // URLRow ---------------------------------------------------------------------- 16 17 URLRow::URLRow() { 18 Initialize(); 19 } 20 21 URLRow::URLRow(const GURL& url) : url_(url) { 22 // Initialize will not set the URL, so our initialization above will stay. 23 Initialize(); 24 } 25 26 URLRow::URLRow(const GURL& url, URLID id) : url_(url) { 27 // Initialize will not set the URL, so our initialization above will stay. 28 Initialize(); 29 // Initialize will zero the id_, so set it here. 30 id_ = id; 31 } 32 33 URLRow::~URLRow() { 34 } 35 36 URLRow& URLRow::operator=(const URLRow& other) { 37 id_ = other.id_; 38 url_ = other.url_; 39 title_ = other.title_; 40 visit_count_ = other.visit_count_; 41 typed_count_ = other.typed_count_; 42 last_visit_ = other.last_visit_; 43 hidden_ = other.hidden_; 44 return *this; 45 } 46 47 void 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 } 56 57 void URLRow::Initialize() { 58 id_ = 0; 59 visit_count_ = 0; 60 typed_count_ = 0; 61 last_visit_ = base::Time(); 62 hidden_ = false; 63 } 64 65 // VisitRow -------------------------------------------------------------------- 66 67 VisitRow::VisitRow() 68 : visit_id(0), 69 url_id(0), 70 referring_visit(0), 71 transition(content::PAGE_TRANSITION_LINK), 72 segment_id(0) { 73 } 74 75 VisitRow::VisitRow(URLID arg_url_id, 76 base::Time arg_visit_time, 77 VisitID arg_referring_visit, 78 content::PageTransition 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 } 87 88 VisitRow::~VisitRow() { 89 } 90 91 // URLResult ------------------------------------------------------------------- 92 93 URLResult::URLResult() 94 : blocked_visit_(false) { 95 } 96 97 URLResult::URLResult(const GURL& url, base::Time visit_time) 98 : URLRow(url), 99 visit_time_(visit_time), 100 blocked_visit_(false) { 101 } 102 103 URLResult::URLResult(const GURL& url, 104 const query_parser::Snippet::MatchPositions& title_matches) 105 : URLRow(url) { 106 title_match_positions_ = title_matches; 107 } 108 URLResult::URLResult(const URLRow& url_row) 109 : URLRow(url_row), 110 blocked_visit_(false) { 111 } 112 113 URLResult::~URLResult() { 114 } 115 116 void URLResult::SwapResult(URLResult* other) { 117 URLRow::Swap(other); 118 std::swap(visit_time_, other->visit_time_); 119 snippet_.Swap(&other->snippet_); 120 title_match_positions_.swap(other->title_match_positions_); 121 std::swap(blocked_visit_, other->blocked_visit_); 122 } 123 124 // static 125 bool URLResult::CompareVisitTime(const URLResult& lhs, const URLResult& rhs) { 126 return lhs.visit_time() > rhs.visit_time(); 127 } 128 129 // QueryResults ---------------------------------------------------------------- 130 131 QueryResults::QueryResults() : reached_beginning_(false) { 132 } 133 134 QueryResults::~QueryResults() {} 135 136 const size_t* QueryResults::MatchesForURL(const GURL& url, 137 size_t* num_matches) const { 138 URLToResultIndices::const_iterator found = url_to_results_.find(url); 139 if (found == url_to_results_.end()) { 140 if (num_matches) 141 *num_matches = 0; 142 return NULL; 143 } 144 145 // All entries in the map should have at least one index, otherwise it 146 // shouldn't be in the map. 147 DCHECK(!found->second->empty()); 148 if (num_matches) 149 *num_matches = found->second->size(); 150 return &found->second->front(); 151 } 152 153 void QueryResults::Swap(QueryResults* other) { 154 std::swap(first_time_searched_, other->first_time_searched_); 155 std::swap(reached_beginning_, other->reached_beginning_); 156 results_.swap(other->results_); 157 url_to_results_.swap(other->url_to_results_); 158 } 159 160 void QueryResults::AppendURLBySwapping(URLResult* result) { 161 URLResult* new_result = new URLResult; 162 new_result->SwapResult(result); 163 164 results_.push_back(new_result); 165 AddURLUsageAtIndex(new_result->url(), results_.size() - 1); 166 } 167 168 void QueryResults::DeleteURL(const GURL& url) { 169 // Delete all instances of this URL. We re-query each time since each 170 // mutation will cause the indices to change. 171 while (const size_t* match_indices = MatchesForURL(url, NULL)) 172 DeleteRange(*match_indices, *match_indices); 173 } 174 175 void QueryResults::DeleteRange(size_t begin, size_t end) { 176 DCHECK(begin <= end && begin < size() && end < size()); 177 178 // First delete the pointers in the given range and store all the URLs that 179 // were modified. We will delete references to these later. 180 std::set<GURL> urls_modified; 181 for (size_t i = begin; i <= end; i++) { 182 urls_modified.insert(results_[i]->url()); 183 } 184 185 // Now just delete that range in the vector en masse (the STL ending is 186 // exclusive, while ours is inclusive, hence the +1). 187 results_.erase(results_.begin() + begin, results_.begin() + end + 1); 188 189 // Delete the indicies referencing the deleted entries. 190 for (std::set<GURL>::const_iterator url = urls_modified.begin(); 191 url != urls_modified.end(); ++url) { 192 URLToResultIndices::iterator found = url_to_results_.find(*url); 193 if (found == url_to_results_.end()) { 194 NOTREACHED(); 195 continue; 196 } 197 198 // Need a signed loop type since we do -- which may take us to -1. 199 for (int match = 0; match < static_cast<int>(found->second->size()); 200 match++) { 201 if (found->second[match] >= begin && found->second[match] <= end) { 202 // Remove this referece from the list. 203 found->second->erase(found->second->begin() + match); 204 match--; 205 } 206 } 207 208 // Clear out an empty lists if we just made one. 209 if (found->second->empty()) 210 url_to_results_.erase(found); 211 } 212 213 // Shift all other indices over to account for the removed ones. 214 AdjustResultMap(end + 1, std::numeric_limits<size_t>::max(), 215 -static_cast<ptrdiff_t>(end - begin + 1)); 216 } 217 218 void QueryResults::AddURLUsageAtIndex(const GURL& url, size_t index) { 219 URLToResultIndices::iterator found = url_to_results_.find(url); 220 if (found != url_to_results_.end()) { 221 // The URL is already in the list, so we can just append the new index. 222 found->second->push_back(index); 223 return; 224 } 225 226 // Need to add a new entry for this URL. 227 base::StackVector<size_t, 4> new_list; 228 new_list->push_back(index); 229 url_to_results_[url] = new_list; 230 } 231 232 void QueryResults::AdjustResultMap(size_t begin, size_t end, ptrdiff_t delta) { 233 for (URLToResultIndices::iterator i = url_to_results_.begin(); 234 i != url_to_results_.end(); ++i) { 235 for (size_t match = 0; match < i->second->size(); match++) { 236 size_t match_index = i->second[match]; 237 if (match_index >= begin && match_index <= end) 238 i->second[match] += delta; 239 } 240 } 241 } 242 243 // QueryOptions ---------------------------------------------------------------- 244 245 QueryOptions::QueryOptions() 246 : max_count(0), 247 duplicate_policy(QueryOptions::REMOVE_ALL_DUPLICATES) { 248 } 249 250 void QueryOptions::SetRecentDayRange(int days_ago) { 251 end_time = base::Time::Now(); 252 begin_time = end_time - base::TimeDelta::FromDays(days_ago); 253 } 254 255 int64 QueryOptions::EffectiveBeginTime() const { 256 return begin_time.ToInternalValue(); 257 } 258 259 int64 QueryOptions::EffectiveEndTime() const { 260 return end_time.is_null() ? 261 std::numeric_limits<int64>::max() : end_time.ToInternalValue(); 262 } 263 264 int QueryOptions::EffectiveMaxCount() const { 265 return max_count ? max_count : std::numeric_limits<int>::max(); 266 } 267 268 // KeywordSearchTermVisit ----------------------------------------------------- 269 270 KeywordSearchTermVisit::KeywordSearchTermVisit() : visits(0) {} 271 272 KeywordSearchTermVisit::~KeywordSearchTermVisit() {} 273 274 // KeywordSearchTermRow -------------------------------------------------------- 275 276 KeywordSearchTermRow::KeywordSearchTermRow() : keyword_id(0), url_id(0) {} 277 278 KeywordSearchTermRow::~KeywordSearchTermRow() {} 279 280 // MostVisitedURL -------------------------------------------------------------- 281 282 MostVisitedURL::MostVisitedURL() {} 283 284 MostVisitedURL::MostVisitedURL(const GURL& url, 285 const base::string16& title) 286 : url(url), 287 title(title) { 288 } 289 290 MostVisitedURL::MostVisitedURL(const GURL& url, 291 const base::string16& title, 292 const base::Time& last_forced_time) 293 : url(url), 294 title(title), 295 last_forced_time(last_forced_time) { 296 } 297 298 MostVisitedURL::~MostVisitedURL() {} 299 300 // FilteredURL ----------------------------------------------------------------- 301 302 FilteredURL::FilteredURL() : score(0.0) {} 303 304 FilteredURL::FilteredURL(const PageUsageData& page_data) 305 : url(page_data.GetURL()), 306 title(page_data.GetTitle()), 307 score(page_data.GetScore()) { 308 } 309 310 FilteredURL::~FilteredURL() {} 311 312 // FilteredURL::ExtendedInfo --------------------------------------------------- 313 314 FilteredURL::ExtendedInfo::ExtendedInfo() 315 : total_visits(0), 316 visits(0), 317 duration_opened(0) { 318 } 319 320 // Images --------------------------------------------------------------------- 321 322 Images::Images() {} 323 324 Images::~Images() {} 325 326 // TopSitesDelta -------------------------------------------------------------- 327 328 TopSitesDelta::TopSitesDelta() {} 329 330 TopSitesDelta::~TopSitesDelta() {} 331 332 // HistoryAddPageArgs --------------------------------------------------------- 333 334 HistoryAddPageArgs::HistoryAddPageArgs() 335 : context_id(NULL), 336 page_id(0), 337 transition(content::PAGE_TRANSITION_LINK), 338 visit_source(SOURCE_BROWSED), 339 did_replace_entry(false) {} 340 341 HistoryAddPageArgs::HistoryAddPageArgs( 342 const GURL& url, 343 base::Time time, 344 ContextID context_id, 345 int32 page_id, 346 const GURL& referrer, 347 const history::RedirectList& redirects, 348 content::PageTransition transition, 349 VisitSource source, 350 bool did_replace_entry) 351 : url(url), 352 time(time), 353 context_id(context_id), 354 page_id(page_id), 355 referrer(referrer), 356 redirects(redirects), 357 transition(transition), 358 visit_source(source), 359 did_replace_entry(did_replace_entry) { 360 } 361 362 HistoryAddPageArgs::~HistoryAddPageArgs() {} 363 364 ThumbnailMigration::ThumbnailMigration() {} 365 366 ThumbnailMigration::~ThumbnailMigration() {} 367 368 MostVisitedThumbnails::MostVisitedThumbnails() {} 369 370 MostVisitedThumbnails::~MostVisitedThumbnails() {} 371 372 // Autocomplete thresholds ----------------------------------------------------- 373 374 const int kLowQualityMatchTypedLimit = 1; 375 const int kLowQualityMatchVisitLimit = 4; 376 const int kLowQualityMatchAgeLimitInDays = 3; 377 378 base::Time AutocompleteAgeThreshold() { 379 return (base::Time::Now() - 380 base::TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays)); 381 } 382 383 bool RowQualifiesAsSignificant(const URLRow& row, 384 const base::Time& threshold) { 385 const base::Time& real_threshold = 386 threshold.is_null() ? AutocompleteAgeThreshold() : threshold; 387 return (row.typed_count() >= kLowQualityMatchTypedLimit) || 388 (row.visit_count() >= kLowQualityMatchVisitLimit) || 389 (row.last_visit() >= real_threshold); 390 } 391 392 // IconMapping ---------------------------------------------------------------- 393 394 IconMapping::IconMapping() 395 : mapping_id(0), icon_id(0), icon_type(favicon_base::INVALID_ICON) {} 396 397 IconMapping::~IconMapping() {} 398 399 // FaviconBitmapIDSize --------------------------------------------------------- 400 401 FaviconBitmapIDSize::FaviconBitmapIDSize() 402 : bitmap_id(0) { 403 } 404 405 FaviconBitmapIDSize::~FaviconBitmapIDSize() { 406 } 407 408 // FaviconBitmap -------------------------------------------------------------- 409 410 FaviconBitmap::FaviconBitmap() 411 : bitmap_id(0), 412 icon_id(0) { 413 } 414 415 FaviconBitmap::~FaviconBitmap() { 416 } 417 418 // VisitDatabaseObserver ------------------------------------------------------- 419 420 VisitDatabaseObserver::~VisitDatabaseObserver() {} 421 422 ExpireHistoryArgs::ExpireHistoryArgs() { 423 } 424 425 ExpireHistoryArgs::~ExpireHistoryArgs() { 426 } 427 428 void ExpireHistoryArgs::SetTimeRangeForOneDay(base::Time time) { 429 begin_time = time.LocalMidnight(); 430 431 // Due to DST, leap seconds, etc., the next day at midnight may be more than 432 // 24 hours away, so add 36 hours and round back down to midnight. 433 end_time = (begin_time + base::TimeDelta::FromHours(36)).LocalMidnight(); 434 } 435 436 } // namespace history 437