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
URLRow()16 URLRow::URLRow() {
17 Initialize();
18 }
19
URLRow(const GURL & url)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
URLRow(const GURL & url,URLID id)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
~URLRow()32 URLRow::~URLRow() {
33 }
34
operator =(const URLRow & other)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
Swap(URLRow * other)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
Initialize()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
VisitRow()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
VisitRow(URLID arg_url_id,base::Time arg_visit_time,VisitID arg_referring_visit,PageTransition::Type arg_transition,SegmentID arg_segment_id)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
~VisitRow()89 VisitRow::~VisitRow() {
90 }
91
92 // Favicons -------------------------------------------------------------------
93
ImportedFaviconUsage()94 ImportedFaviconUsage::ImportedFaviconUsage() {
95 }
96
~ImportedFaviconUsage()97 ImportedFaviconUsage::~ImportedFaviconUsage() {
98 }
99
100 // StarredEntry ----------------------------------------------------------------
101
StarredEntry()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
~StarredEntry()111 StarredEntry::~StarredEntry() {
112 }
113
Swap(StarredEntry * other)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
URLResult()129 URLResult::URLResult() {
130 }
131
URLResult(const GURL & url,base::Time visit_time)132 URLResult::URLResult(const GURL& url, base::Time visit_time)
133 : URLRow(url),
134 visit_time_(visit_time) {
135 }
136
URLResult(const GURL & url,const Snippet::MatchPositions & title_matches)137 URLResult::URLResult(const GURL& url,
138 const Snippet::MatchPositions& title_matches)
139 : URLRow(url) {
140 title_match_positions_ = title_matches;
141 }
142
~URLResult()143 URLResult::~URLResult() {
144 }
145
SwapResult(URLResult * other)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
QueryResults()155 QueryResults::QueryResults() : reached_beginning_(false) {
156 }
157
~QueryResults()158 QueryResults::~QueryResults() {
159 // Free all the URL objects.
160 STLDeleteContainerPointers(results_.begin(), results_.end());
161 }
162
MatchesForURL(const GURL & url,size_t * num_matches) const163 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
Swap(QueryResults * other)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
AppendURLBySwapping(URLResult * result)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
AppendResultsBySwapping(QueryResults * other,bool remove_dupes)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
DeleteURL(const GURL & url)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
DeleteRange(size_t begin,size_t end)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
AddURLUsageAtIndex(const GURL & url,size_t index)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
AdjustResultMap(size_t begin,size_t end,ptrdiff_t delta)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
QueryOptions()299 QueryOptions::QueryOptions() : max_count(0) {}
300
SetRecentDayRange(int days_ago)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
KeywordSearchTermVisit()308 KeywordSearchTermVisit::KeywordSearchTermVisit() {}
309
~KeywordSearchTermVisit()310 KeywordSearchTermVisit::~KeywordSearchTermVisit() {}
311
312 // KeywordSearchTermRow --------------------------------------------------------
313
KeywordSearchTermRow()314 KeywordSearchTermRow::KeywordSearchTermRow() : keyword_id(0), url_id(0) {}
315
~KeywordSearchTermRow()316 KeywordSearchTermRow::~KeywordSearchTermRow() {}
317
318 // MostVisitedURL --------------------------------------------------------------
319
MostVisitedURL()320 MostVisitedURL::MostVisitedURL() {}
321
MostVisitedURL(const GURL & in_url,const GURL & in_favicon_url,const string16 & in_title)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
~MostVisitedURL()330 MostVisitedURL::~MostVisitedURL() {}
331
332 // Images ---------------------------------------------------------------------
333
Images()334 Images::Images() {}
335
~Images()336 Images::~Images() {}
337
338 // TopSitesDelta --------------------------------------------------------------
339
TopSitesDelta()340 TopSitesDelta::TopSitesDelta() {}
341
~TopSitesDelta()342 TopSitesDelta::~TopSitesDelta() {}
343
344 // HistoryAddPageArgs ---------------------------------------------------------
345
HistoryAddPageArgs(const GURL & arg_url,base::Time arg_time,const void * arg_id_scope,int32 arg_page_id,const GURL & arg_referrer,const history::RedirectList & arg_redirects,PageTransition::Type arg_transition,VisitSource arg_source,bool arg_did_replace_entry)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
~HistoryAddPageArgs()367 HistoryAddPageArgs::~HistoryAddPageArgs() {}
368
Clone() const369 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
ThumbnailMigration()375 ThumbnailMigration::ThumbnailMigration() {}
376
~ThumbnailMigration()377 ThumbnailMigration::~ThumbnailMigration() {}
378
MostVisitedThumbnails()379 MostVisitedThumbnails::MostVisitedThumbnails() {}
380
~MostVisitedThumbnails()381 MostVisitedThumbnails::~MostVisitedThumbnails() {}
382
383 // Autocomplete thresholds -----------------------------------------------------
384
385 const int kLowQualityMatchTypedLimit = 1;
386 const int kLowQualityMatchVisitLimit = 3;
387 const int kLowQualityMatchAgeLimitInDays = 3;
388
AutocompleteAgeThreshold()389 base::Time AutocompleteAgeThreshold() {
390 return (base::Time::Now() -
391 base::TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays));
392 }
393
RowQualifiesAsSignificant(const URLRow & row,const base::Time & threshold)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
IconMapping()405 IconMapping::IconMapping()
406 : mapping_id(0),
407 icon_id(0),
408 icon_type(INVALID_ICON) {
409 }
410
~IconMapping()411 IconMapping::~IconMapping() {}
412
413
FaviconData()414 FaviconData::FaviconData()
415 : known_icon(false),
416 expired(false),
417 icon_type(history::INVALID_ICON) {
418 }
419
~FaviconData()420 FaviconData::~FaviconData() {}
421
is_valid()422 bool FaviconData::is_valid() {
423 return known_icon && image_data.get() && image_data->size();
424 }
425
426 } // namespace history
427