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/top_sites_cache.h"
6
7#include "base/logging.h"
8#include "base/memory/ref_counted_memory.h"
9
10namespace history {
11
12TopSitesCache::TopSitesCache() {
13}
14
15TopSitesCache::~TopSitesCache() {
16}
17
18void TopSitesCache::SetTopSites(const MostVisitedURLList& top_sites) {
19  top_sites_ = top_sites;
20  GenerateCanonicalURLs();
21}
22
23void TopSitesCache::SetThumbnails(const URLToImagesMap& images) {
24  images_ = images;
25}
26
27void TopSitesCache::SetPageThumbnail(const GURL& url,
28                                     RefCountedBytes* thumbnail,
29                                     const ThumbnailScore& score) {
30  Images& img = images_[GetCanonicalURL(url)];
31  img.thumbnail = thumbnail;
32  img.thumbnail_score = score;
33}
34
35Images* TopSitesCache::GetImage(const GURL& url) {
36  return &images_[GetCanonicalURL(url)];
37}
38
39bool TopSitesCache::GetPageThumbnail(const GURL& url,
40                                     scoped_refptr<RefCountedBytes>* bytes) {
41  std::map<GURL, Images>::const_iterator found =
42      images_.find(GetCanonicalURL(url));
43  if (found != images_.end()) {
44    *bytes = found->second.thumbnail.get();
45    return true;
46  }
47  return false;
48}
49
50bool TopSitesCache::GetPageThumbnailScore(const GURL& url,
51                                          ThumbnailScore* score) {
52  std::map<GURL, Images>::const_iterator found =
53      images_.find(GetCanonicalURL(url));
54  if (found != images_.end()) {
55    *score = found->second.thumbnail_score;
56    return true;
57  }
58  return false;
59}
60
61GURL TopSitesCache::GetCanonicalURL(const GURL& url) {
62  CanonicalURLs::iterator i = TopSitesCache::GetCanonicalURLsIterator(url);
63  return i == canonical_urls_.end() ? url : i->first.first->url;
64}
65
66bool TopSitesCache::IsKnownURL(const GURL& url) {
67  return GetCanonicalURLsIterator(url) != canonical_urls_.end();
68}
69
70size_t TopSitesCache::GetURLIndex(const GURL& url) {
71  DCHECK(IsKnownURL(url));
72  return GetCanonicalURLsIterator(url)->second;
73}
74
75void TopSitesCache::RemoveUnreferencedThumbnails() {
76  for (URLToImagesMap::iterator i = images_.begin(); i != images_.end(); ) {
77    if (IsKnownURL(i->first)) {
78      ++i;
79    } else {
80      URLToImagesMap::iterator next_i = i;
81      ++next_i;
82      images_.erase(i);
83      i = next_i;
84    }
85  }
86}
87
88void TopSitesCache::GenerateCanonicalURLs() {
89  canonical_urls_.clear();
90  for (size_t i = 0; i < top_sites_.size(); i++)
91    StoreRedirectChain(top_sites_[i].redirects, i);
92}
93
94void TopSitesCache::StoreRedirectChain(const RedirectList& redirects,
95                                       size_t destination) {
96  // redirects is empty if the user pinned a site and there are not enough top
97  // sites before the pinned site.
98
99  // Map all the redirected URLs to the destination.
100  for (size_t i = 0; i < redirects.size(); i++) {
101    // If this redirect is already known, don't replace it with a new one.
102    if (!IsKnownURL(redirects[i])) {
103      CanonicalURLEntry entry;
104      entry.first = &(top_sites_[destination]);
105      entry.second = i;
106      canonical_urls_[entry] = destination;
107    }
108  }
109}
110
111TopSitesCache::CanonicalURLs::iterator TopSitesCache::GetCanonicalURLsIterator(
112    const GURL& url) {
113  MostVisitedURL most_visited_url;
114  most_visited_url.redirects.push_back(url);
115  CanonicalURLEntry entry;
116  entry.first = &most_visited_url;
117  entry.second = 0u;
118  return canonical_urls_.find(entry);
119}
120
121}  // namespace history
122