summaryrefslogtreecommitdiffstats
path: root/chrome/browser/thumbnail_store.h
blob: ed95a0241831faf06c6c48bfea159c8045744982 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_THUMBNAIL_STORE_H_
#define CHROME_BROWSER_THUMBNAIL_STORE_H_

#include <map>
#include <string>
#include <vector>

#include "app/sql/connection.h"
#include "base/file_path.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
#include "base/timer.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/url_database.h"  // For DBCloseScoper
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/ref_counted_util.h"
#include "chrome/common/thumbnail_score.h"
#include "testing/gtest/include/gtest/gtest_prod.h"

class DictionaryValue;
class GURL;
class HistoryService;
class Profile;
class SkBitmap;
struct sqlite3;
namespace base {
class Time;
}

// This storage interface provides storage for the thumbnails used
// by the new_tab_ui.
class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
                       public NotificationObserver {
 public:
  ThumbnailStore();

  // Must be called before {Set,Get}PageThumbnail.  |db_name| is the location
  // of an existing ThumbnailStore database or where to create a new one.
  void Init(const FilePath& db_name, Profile* profile);

  // Is the ThumbnailStore ready for GetPageThumbnail requests?
  bool IsReady() { return disk_data_loaded_ && redirect_urls_.get(); }

  // Stores the given thumbnail and score with the associated url in the cache.
  bool SetPageThumbnail(const GURL& url,
                        const SkBitmap& thumbnail,
                        const ThumbnailScore& score,
                        bool fetch_redirects);  // for debugging

  // Sets *data to point to the thumbnail for the given url.
  // Returns false if no thumbnail available.
  bool GetPageThumbnail(const GURL& url, RefCountedBytes** data);

  // This is called when the browser is shutting down to write all dirty cache
  // entries to disk.
  void Shutdown();

 private:
  friend class base::RefCountedThreadSafe<ThumbnailStore>;
  FRIEND_TEST(ThumbnailStoreTest, RetrieveFromCache);
  FRIEND_TEST(ThumbnailStoreTest, RetrieveFromDisk);
  FRIEND_TEST(ThumbnailStoreTest, UpdateThumbnail);
  FRIEND_TEST(ThumbnailStoreTest, FollowRedirects);
  friend class ThumbnailStoreTest;

  ~ThumbnailStore();

  struct CacheEntry {
    scoped_refptr<RefCountedBytes> data_;
    ThumbnailScore score_;
    bool dirty_;

    CacheEntry() : data_(NULL), score_(ThumbnailScore()), dirty_(false) {}
    CacheEntry(RefCountedBytes* data,
               const ThumbnailScore& score,
               bool dirty)
        : data_(data),
          score_(score),
          dirty_(dirty) {}
  };

  // Data structure used to store thumbnail data in memory.
  typedef std::map<GURL, CacheEntry> Cache;

  // Data structre used to store the top visited URLs. It maps the end of a
  // redirect chain to the beginning. If A -> B -> C is a redirect chain and C
  // is a top visited url, then this map will contain an entry C => A.
  typedef std::map<GURL, GURL> MostVisitedMap;

  // NotificationObserver implementation
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // Notify anyone listening that the ThumbnailStore is ready to be used.
  void NotifyThumbnailStoreReady();

  // Most visited URLs and their redirect lists -------------------------------

  // Query the HistoryService for the most visited URLs and the most recent
  // redirect lists for those URLs.  This happens in the background and the
  // callback is OnURLDataAvailable.
  void UpdateURLData();

  // The callback for UpdateURLData.
  void OnURLDataAvailable(HistoryService::Handle handle,
                          bool success,
                          std::vector<GURL>* urls,
                          history::RedirectMap* redirects);

  // The callback for the redirects request to the HistoryService made in
  // SetPageThumbnail. If we have a redirect chain A -> B -> C, this function
  // will be called with url=C and redirects = {B -> A}.  This information gets
  // inserted into the RedirectMap as A => {B -> C}.
  void OnRedirectsForURLAvailable(HistoryService::Handle handle,
                                  GURL url,
                                  bool success,
                                  history::RedirectList* redirects);

  // Search the RedirectMap for a redirect chain ending at |url|.  Returns an
  // iterator to an entry in redirect_urls_ if found or redirect_urls_->end().
  history::RedirectMap::iterator GetRedirectIteratorForURL(
      const GURL& url) const;

  // Remove stale data --------------------------------------------------------

  // Remove entries from the in memory thumbnail cache cache that have been
  // blacklisted or are not in the top kMaxCacheSize visited sites.  Call
  // CommitCacheToDB on the file_thread to remove these entries from disk and
  // to also write new entries to disk.
  void CleanCacheData();

  // Disk operations ----------------------------------------------------------

  // Initialize |db_| to the database specified in |db_name|.  If |cb_loop|
  // is non-null, calls GetAllThumbnailsFromDisk.  Done on the file_thread.
  void InitializeFromDB(const FilePath& db_name, MessageLoop* cb_loop);

  // Read all thumbnail data from the specified FilePath into a Cache object.
  // Done on the file_thread and returns to OnDiskDataAvailable on the thread
  // owning the specified MessageLoop.
  void GetAllThumbnailsFromDisk(MessageLoop* cb_loop);

  // Once thumbnail data from the disk is available from the file_thread,
  // this function is invoked on the main thread.  It takes ownership of the
  // Cache* passed in and retains this Cache* for the lifetime of the object.
  void OnDiskDataAvailable(Cache* cache);

  // Delete each URL in the given vector from the DB and write all dirty
  // cache entries to the DB.
  void CommitCacheToDB(
      scoped_refptr<RefCountedVector<GURL> > urls_to_delete,
      Cache* data);

  // Decide whether to store data ---------------------------------------------

  bool ShouldStoreThumbnailForURL(const GURL& url) const;

  bool IsURLBlacklisted(const GURL& url) const;

  std::wstring GetDictionaryKeyForURL(const std::string& url) const;

  // Returns true if url is in most_visited_urls_.
  bool IsPopular(const GURL& url) const;



  // Member variables ---------------------------------------------------------

  // The Cache maintained by the object.
  scoped_ptr<Cache> cache_;

  // The database holding the thumbnails on disk.
  sql::Connection db_;

  // We hold a reference to the history service to query for most visited URLs
  // and redirect information.
  scoped_refptr<HistoryService> hs_;

  // The most visited urls refreshed every kUpdateIntervalSecs from the
  // HistoryService.
  scoped_ptr<MostVisitedMap> most_visited_urls_;

  // A pointer to the persistent URL blacklist for this profile.
  const DictionaryValue* url_blacklist_;

  // A map pairing the URL that a user typed to a list of URLs it was
  // redirected to. Ex:
  // google.com => { http://www.google.com/ }
  scoped_ptr<history::RedirectMap> redirect_urls_;

  // Timer on which UpdateURLData runs.
  base::RepeatingTimer<ThumbnailStore> timer_;

  // Consumer for queries to the HistoryService.
  CancelableRequestConsumer consumer_;

  // Registrar to get notified when the history is cleared.
  NotificationRegistrar registrar_;

  static const unsigned int kMaxCacheSize = 24;
  static const int64 kUpdateIntervalSecs = 360;

  // Has the data from disk been read?
  bool disk_data_loaded_;

  DISALLOW_COPY_AND_ASSIGN(ThumbnailStore);
};

#endif  // CHROME_BROWSER_THUMBNAIL_STORE_H_