1// Copyright 2014 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 "components/history/core/browser/history_types.h"
6
7#include <limits>
8
9#include "base/logging.h"
10#include "base/stl_util.h"
11#include "components/history/core/browser/page_usage_data.h"
12
13namespace history {
14
15// VisitRow --------------------------------------------------------------------
16
17VisitRow::VisitRow()
18    : visit_id(0),
19      url_id(0),
20      referring_visit(0),
21      transition(ui::PAGE_TRANSITION_LINK),
22      segment_id(0) {
23}
24
25VisitRow::VisitRow(URLID arg_url_id,
26                   base::Time arg_visit_time,
27                   VisitID arg_referring_visit,
28                   ui::PageTransition arg_transition,
29                   SegmentID arg_segment_id)
30    : visit_id(0),
31      url_id(arg_url_id),
32      visit_time(arg_visit_time),
33      referring_visit(arg_referring_visit),
34      transition(arg_transition),
35      segment_id(arg_segment_id) {
36}
37
38VisitRow::~VisitRow() {
39}
40
41// QueryResults ----------------------------------------------------------------
42
43QueryResults::QueryResults() : reached_beginning_(false) {
44}
45
46QueryResults::~QueryResults() {}
47
48const size_t* QueryResults::MatchesForURL(const GURL& url,
49                                          size_t* num_matches) const {
50  URLToResultIndices::const_iterator found = url_to_results_.find(url);
51  if (found == url_to_results_.end()) {
52    if (num_matches)
53      *num_matches = 0;
54    return NULL;
55  }
56
57  // All entries in the map should have at least one index, otherwise it
58  // shouldn't be in the map.
59  DCHECK(!found->second->empty());
60  if (num_matches)
61    *num_matches = found->second->size();
62  return &found->second->front();
63}
64
65void QueryResults::Swap(QueryResults* other) {
66  std::swap(first_time_searched_, other->first_time_searched_);
67  std::swap(reached_beginning_, other->reached_beginning_);
68  results_.swap(other->results_);
69  url_to_results_.swap(other->url_to_results_);
70}
71
72void QueryResults::AppendURLBySwapping(URLResult* result) {
73  URLResult* new_result = new URLResult;
74  new_result->SwapResult(result);
75
76  results_.push_back(new_result);
77  AddURLUsageAtIndex(new_result->url(), results_.size() - 1);
78}
79
80void QueryResults::DeleteURL(const GURL& url) {
81  // Delete all instances of this URL. We re-query each time since each
82  // mutation will cause the indices to change.
83  while (const size_t* match_indices = MatchesForURL(url, NULL))
84    DeleteRange(*match_indices, *match_indices);
85}
86
87void QueryResults::DeleteRange(size_t begin, size_t end) {
88  DCHECK(begin <= end && begin < size() && end < size());
89
90  // First delete the pointers in the given range and store all the URLs that
91  // were modified. We will delete references to these later.
92  std::set<GURL> urls_modified;
93  for (size_t i = begin; i <= end; i++) {
94    urls_modified.insert(results_[i]->url());
95  }
96
97  // Now just delete that range in the vector en masse (the STL ending is
98  // exclusive, while ours is inclusive, hence the +1).
99  results_.erase(results_.begin() + begin, results_.begin() + end + 1);
100
101  // Delete the indicies referencing the deleted entries.
102  for (std::set<GURL>::const_iterator url = urls_modified.begin();
103       url != urls_modified.end(); ++url) {
104    URLToResultIndices::iterator found = url_to_results_.find(*url);
105    if (found == url_to_results_.end()) {
106      NOTREACHED();
107      continue;
108    }
109
110    // Need a signed loop type since we do -- which may take us to -1.
111    for (int match = 0; match < static_cast<int>(found->second->size());
112         match++) {
113      if (found->second[match] >= begin && found->second[match] <= end) {
114        // Remove this referece from the list.
115        found->second->erase(found->second->begin() + match);
116        match--;
117      }
118    }
119
120    // Clear out an empty lists if we just made one.
121    if (found->second->empty())
122      url_to_results_.erase(found);
123  }
124
125  // Shift all other indices over to account for the removed ones.
126  AdjustResultMap(end + 1, std::numeric_limits<size_t>::max(),
127                  -static_cast<ptrdiff_t>(end - begin + 1));
128}
129
130void QueryResults::AddURLUsageAtIndex(const GURL& url, size_t index) {
131  URLToResultIndices::iterator found = url_to_results_.find(url);
132  if (found != url_to_results_.end()) {
133    // The URL is already in the list, so we can just append the new index.
134    found->second->push_back(index);
135    return;
136  }
137
138  // Need to add a new entry for this URL.
139  base::StackVector<size_t, 4> new_list;
140  new_list->push_back(index);
141  url_to_results_[url] = new_list;
142}
143
144void QueryResults::AdjustResultMap(size_t begin, size_t end, ptrdiff_t delta) {
145  for (URLToResultIndices::iterator i = url_to_results_.begin();
146       i != url_to_results_.end(); ++i) {
147    for (size_t match = 0; match < i->second->size(); match++) {
148      size_t match_index = i->second[match];
149      if (match_index >= begin && match_index <= end)
150        i->second[match] += delta;
151    }
152  }
153}
154
155// QueryOptions ----------------------------------------------------------------
156
157QueryOptions::QueryOptions()
158    : max_count(0),
159      duplicate_policy(QueryOptions::REMOVE_ALL_DUPLICATES) {
160}
161
162void QueryOptions::SetRecentDayRange(int days_ago) {
163  end_time = base::Time::Now();
164  begin_time = end_time - base::TimeDelta::FromDays(days_ago);
165}
166
167int64 QueryOptions::EffectiveBeginTime() const {
168  return begin_time.ToInternalValue();
169}
170
171int64 QueryOptions::EffectiveEndTime() const {
172  return end_time.is_null() ?
173      std::numeric_limits<int64>::max() : end_time.ToInternalValue();
174}
175
176int QueryOptions::EffectiveMaxCount() const {
177  return max_count ? max_count : std::numeric_limits<int>::max();
178}
179
180// QueryURLResult -------------------------------------------------------------
181
182QueryURLResult::QueryURLResult() : success(false) {
183}
184
185QueryURLResult::~QueryURLResult() {
186}
187
188// MostVisitedURL --------------------------------------------------------------
189
190MostVisitedURL::MostVisitedURL() {}
191
192MostVisitedURL::MostVisitedURL(const GURL& url,
193                               const base::string16& title)
194    : url(url),
195      title(title) {
196}
197
198MostVisitedURL::MostVisitedURL(const GURL& url,
199                               const base::string16& title,
200                               const base::Time& last_forced_time)
201    : url(url),
202      title(title),
203      last_forced_time(last_forced_time) {
204}
205
206MostVisitedURL::~MostVisitedURL() {}
207
208// FilteredURL -----------------------------------------------------------------
209
210FilteredURL::FilteredURL() : score(0.0) {}
211
212FilteredURL::FilteredURL(const PageUsageData& page_data)
213    : url(page_data.GetURL()),
214      title(page_data.GetTitle()),
215      score(page_data.GetScore()) {
216}
217
218FilteredURL::~FilteredURL() {}
219
220// FilteredURL::ExtendedInfo ---------------------------------------------------
221
222FilteredURL::ExtendedInfo::ExtendedInfo()
223    : total_visits(0),
224      visits(0),
225      duration_opened(0) {
226}
227
228// Images ---------------------------------------------------------------------
229
230Images::Images() {}
231
232Images::~Images() {}
233
234// TopSitesDelta --------------------------------------------------------------
235
236TopSitesDelta::TopSitesDelta() {}
237
238TopSitesDelta::~TopSitesDelta() {}
239
240// HistoryAddPageArgs ---------------------------------------------------------
241
242HistoryAddPageArgs::HistoryAddPageArgs()
243    : context_id(NULL),
244      page_id(0),
245      transition(ui::PAGE_TRANSITION_LINK),
246      visit_source(SOURCE_BROWSED),
247      did_replace_entry(false) {}
248
249HistoryAddPageArgs::HistoryAddPageArgs(
250    const GURL& url,
251    base::Time time,
252    ContextID context_id,
253    int32 page_id,
254    const GURL& referrer,
255    const history::RedirectList& redirects,
256    ui::PageTransition transition,
257    VisitSource source,
258    bool did_replace_entry)
259      : url(url),
260        time(time),
261        context_id(context_id),
262        page_id(page_id),
263        referrer(referrer),
264        redirects(redirects),
265        transition(transition),
266        visit_source(source),
267        did_replace_entry(did_replace_entry) {
268}
269
270HistoryAddPageArgs::~HistoryAddPageArgs() {}
271
272// ThumbnailMigration ---------------------------------------------------------
273
274ThumbnailMigration::ThumbnailMigration() {}
275
276ThumbnailMigration::~ThumbnailMigration() {}
277
278// MostVisitedThumbnails ------------------------------------------------------
279
280MostVisitedThumbnails::MostVisitedThumbnails() {}
281
282MostVisitedThumbnails::~MostVisitedThumbnails() {}
283
284// IconMapping ----------------------------------------------------------------
285
286IconMapping::IconMapping()
287    : mapping_id(0), icon_id(0), icon_type(favicon_base::INVALID_ICON) {}
288
289IconMapping::~IconMapping() {}
290
291// FaviconBitmapIDSize ---------------------------------------------------------
292
293FaviconBitmapIDSize::FaviconBitmapIDSize()
294    : bitmap_id(0) {
295}
296
297FaviconBitmapIDSize::~FaviconBitmapIDSize() {
298}
299
300// FaviconBitmap --------------------------------------------------------------
301
302FaviconBitmap::FaviconBitmap()
303    : bitmap_id(0),
304      icon_id(0) {
305}
306
307FaviconBitmap::~FaviconBitmap() {
308}
309
310// VisitDatabaseObserver -------------------------------------------------------
311
312VisitDatabaseObserver::~VisitDatabaseObserver() {}
313
314// ExpireHistoryArgs ----------------------------------------------------------
315
316ExpireHistoryArgs::ExpireHistoryArgs() {
317}
318
319ExpireHistoryArgs::~ExpireHistoryArgs() {
320}
321
322void ExpireHistoryArgs::SetTimeRangeForOneDay(base::Time time) {
323  begin_time = time.LocalMidnight();
324
325  // Due to DST, leap seconds, etc., the next day at midnight may be more than
326  // 24 hours away, so add 36 hours and round back down to midnight.
327  end_time = (begin_time + base::TimeDelta::FromHours(36)).LocalMidnight();
328}
329
330}  // namespace history
331