• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CHROME_BROWSER_HISTORY_TOP_SITES_H_
6 #define CHROME_BROWSER_HISTORY_TOP_SITES_H_
7 #pragma once
8 
9 #include <list>
10 #include <set>
11 #include <string>
12 #include <utility>
13 
14 #include "base/basictypes.h"
15 #include "base/gtest_prod_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/ref_counted_memory.h"
18 #include "base/synchronization/lock.h"
19 #include "base/time.h"
20 #include "base/timer.h"
21 #include "chrome/browser/history/history_types.h"
22 #include "chrome/browser/history/history.h"
23 #include "chrome/browser/history/page_usage_data.h"
24 #include "chrome/common/thumbnail_score.h"
25 #include "content/browser/cancelable_request.h"
26 #include "googleurl/src/gurl.h"
27 
28 class DictionaryValue;
29 class FilePath;
30 class SkBitmap;
31 class Profile;
32 
33 namespace history {
34 
35 class TopSitesCache;
36 class TopSitesBackend;
37 class TopSitesTest;
38 
39 // Stores the data for the top "most visited" sites. This includes a cache of
40 // the most visited data from history, as well as the corresponding thumbnails
41 // of those sites.
42 //
43 // This class allows requests for most visited urls and thumbnails on any
44 // thread. All other methods must be invoked on the UI thread. All mutations
45 // to internal state happen on the UI thread and are scheduled to update the
46 // db using TopSitesBackend.
47 class TopSites
48     : public base::RefCountedThreadSafe<TopSites>,
49       public NotificationObserver,
50       public CancelableRequestProvider {
51  public:
52   explicit TopSites(Profile* profile);
53 
54   // Initializes TopSites.
55   void Init(const FilePath& db_name);
56 
57   // Sets the given thumbnail for the given URL. Returns true if the thumbnail
58   // was updated. False means either the URL wasn't known to us, or we felt
59   // that our current thumbnail was superior to the given one.
60   bool SetPageThumbnail(const GURL& url,
61                         const SkBitmap& thumbnail,
62                         const ThumbnailScore& score);
63 
64   // Callback for GetMostVisitedURLs.
65   typedef Callback1<const MostVisitedURLList&>::Type GetTopSitesCallback;
66   typedef std::set<scoped_refptr<CancelableRequest<GetTopSitesCallback> > >
67       PendingCallbackSet;
68 
69   // Returns a list of most visited URLs via a callback.
70   // This may be invoked on any thread.
71   // NOTE: the callback may be called immediately if we have the data cached.
72   void GetMostVisitedURLs(CancelableRequestConsumer* consumer,
73                           GetTopSitesCallback* callback);
74 
75   // Get a thumbnail for a given page. Returns true iff we have the thumbnail.
76   // This may be invoked on any thread.
77   // As this method may be invoked on any thread the ref count needs to be
78   // upped before this method returns, so this takes a scoped_refptr*.
79   bool GetPageThumbnail(const GURL& url,
80                         scoped_refptr<RefCountedBytes>* bytes);
81 
82   // Get a thumbnail score for a given page. Returns true iff we have the
83   // thumbnail score.  This may be invoked on any thread. The score will
84   // be copied to |score|.
85   virtual bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score);
86 
87   // Get a temporary thumbnail score for a given page. Returns true iff we
88   // have the thumbnail score. Useful when checking if we should update a
89   // thumbnail for a given page. The score will be copied to |score|.
90   bool GetTemporaryPageThumbnailScore(const GURL& url, ThumbnailScore* score);
91 
92   // Invoked from History if migration is needed. If this is invoked it will
93   // be before HistoryLoaded is invoked.
94   void MigrateFromHistory();
95 
96   // Invoked with data from migrating thumbnails out of history.
97   void FinishHistoryMigration(const ThumbnailMigration& data);
98 
99   // Invoked from history when it finishes loading. If MigrateFromHistory was
100   // not invoked at this point then we load from the top sites service.
101   void HistoryLoaded();
102 
103   // Blacklisted URLs
104 
105   // Returns true if there is at least one item in the blacklist.
106   bool HasBlacklistedItems() const;
107 
108   // Add a  URL to the blacklist.
109   void AddBlacklistedURL(const GURL& url);
110 
111   // Removes a URL from the blacklist.
112   void RemoveBlacklistedURL(const GURL& url);
113 
114   // Returns true if the URL is blacklisted.
115   bool IsBlacklisted(const GURL& url);
116 
117   // Clear the blacklist.
118   void ClearBlacklistedURLs();
119 
120   // Pinned URLs
121 
122   // Pin a URL at |index|.
123   void AddPinnedURL(const GURL& url, size_t index);
124 
125   // Returns true if a URL is pinned.
126   bool IsURLPinned(const GURL& url);
127 
128   // Unpin a URL.
129   void RemovePinnedURL(const GURL& url);
130 
131   // Return a URL pinned at |index| via |out|. Returns true if there
132   // is a URL pinned at |index|.
133   bool GetPinnedURLAtIndex(size_t index, GURL* out);
134 
135   // Shuts down top sites.
136   void Shutdown();
137 
138   // Generates the diff of things that happened between "old" and "new."
139   //
140   // The URLs that are in "new" but not "old" will be have their index into
141   // "new" put in |added_urls|. The URLs that are in "old" but not "new" will
142   // have their index into "old" put into |deleted_urls|.
143   //
144   // URLs appearing in both old and new lists but having different indices will
145   // have their index into "new" be put into |moved_urls|.
146   static void DiffMostVisited(const MostVisitedURLList& old_list,
147                               const MostVisitedURLList& new_list,
148                               TopSitesDelta* delta);
149 
150   // Query history service for the list of available thumbnails. Returns the
151   // handle for the request, or NULL if a request could not be made.
152   // Public only for testing purposes.
153   CancelableRequestProvider::Handle StartQueryForMostVisited();
154 
loaded()155   bool loaded() const { return loaded_; }
156 
157   // Returns true if the given URL is known to the top sites service.
158   // This function also returns false if TopSites isn't loaded yet.
159   virtual bool IsKnownURL(const GURL& url);
160 
161   // Returns true if the top sites list is full (i.e. we already have the
162   // maximum number of top sites).  This function also returns false if
163   // TopSites isn't loaded yet.
164   virtual bool IsFull();
165 
166  protected:
167   // For allowing inheritance.
168   virtual ~TopSites();
169 
170  private:
171   friend class base::RefCountedThreadSafe<TopSites>;
172   friend class TopSitesTest;
173 
174   typedef std::pair<GURL, Images> TempImage;
175   typedef std::list<TempImage> TempImages;
176 
177   // Enumeration of the possible states history can be in.
178   enum HistoryLoadState {
179     // We're waiting for history to finish loading.
180     HISTORY_LOADING,
181 
182     // History finished loading and we need to migrate top sites out of history.
183     HISTORY_MIGRATING,
184 
185     // History is loaded.
186     HISTORY_LOADED
187   };
188 
189   // Enumeration of possible states the top sites backend can be in.
190   enum TopSitesLoadState {
191     // We're waiting for the backend to finish loading.
192     TOP_SITES_LOADING,
193 
194     // The backend finished loading, but we may need to migrate. This is true if
195     // the top sites db didn't exist, or if the db existed but is from an old
196     // version.
197     TOP_SITES_LOADED_WAITING_FOR_HISTORY,
198 
199     // Top sites is loaded.
200     TOP_SITES_LOADED
201   };
202 
203   // Sets the thumbnail without writing to the database. Useful when
204   // reading last known top sites from the DB.
205   // Returns true if the thumbnail was set, false if the existing one is better.
206   bool SetPageThumbnailNoDB(const GURL& url,
207                             const RefCountedBytes* thumbnail_data,
208                             const ThumbnailScore& score);
209 
210   // A version of SetPageThumbnail that takes RefCountedBytes as
211   // returned by HistoryService.
212   bool SetPageThumbnailEncoded(const GURL& url,
213                                const RefCountedBytes* thumbnail,
214                                const ThumbnailScore& score);
215 
216   // Encodes the bitmap to bytes for storage to the db. Returns true if the
217   // bitmap was successfully encoded.
218   static bool EncodeBitmap(const SkBitmap& bitmap,
219                            scoped_refptr<RefCountedBytes>* bytes);
220 
221   // Removes the cached thumbnail for url. Does nothing if |url| if not cached
222   // in |temp_images_|.
223   void RemoveTemporaryThumbnailByURL(const GURL& url);
224 
225   // Add a thumbnail for an unknown url. See temp_thumbnails_map_.
226   void AddTemporaryThumbnail(const GURL& url,
227                              const RefCountedBytes* thumbnail,
228                              const ThumbnailScore& score);
229 
230   // Called by our timer. Starts the query for the most visited sites.
231   void TimerFired();
232 
233   // Finds the given URL in the redirect chain for the given TopSite, and
234   // returns the distance from the destination in hops that the given URL is.
235   // The URL is assumed to be in the list. The destination is 0.
236   static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
237                                        const GURL& url);
238 
239   // Returns the set of prepopulate pages.
240   static MostVisitedURLList GetPrepopulatePages();
241 
242   // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
243   // Returns true if any pages were added.
244   static bool AddPrepopulatedPages(MostVisitedURLList* urls);
245 
246   // Convert pinned_urls_ dictionary to the new format. Use URLs as
247   // dictionary keys.
248   void MigratePinnedURLs();
249 
250   // Takes |urls|, produces it's copy in |out| after removing
251   // blacklisted URLs and reordering pinned URLs.
252   void ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls,
253                                    MostVisitedURLList* out);
254 
255   // Converts a url into a canonical string representation.
256   std::string GetURLString(const GURL& url);
257 
258   // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
259   std::string GetURLHash(const GURL& url);
260 
261   // Returns the delay until the next update of history is needed.
262   // Uses num_urls_changed
263   base::TimeDelta GetUpdateDelay();
264 
265   // Executes all of the callbacks in |pending_callbacks|. This is used after
266   // we finish loading if any requests came in before we loaded.
267   static void ProcessPendingCallbacks(
268       const PendingCallbackSet& pending_callbacks,
269       const MostVisitedURLList& urls);
270 
271   // Implementation of NotificationObserver.
272   virtual void Observe(NotificationType type,
273                        const NotificationSource& source,
274                        const NotificationDetails& details);
275 
276   // Resets top_sites_ and updates the db (in the background). All mutations to
277   // top_sites_ *must* go through this.
278   void SetTopSites(const MostVisitedURLList& new_top_sites);
279 
280   // Returns the number of most visted results to request from history. This
281   // changes depending upon how many urls have been blacklisted.
282   int num_results_to_request_from_history() const;
283 
284   // Invoked when transitioning to LOADED. Notifies any queued up callbacks.
285   void MoveStateToLoaded();
286 
287   void ResetThreadSafeCache();
288 
289   void ResetThreadSafeImageCache();
290 
291   // Stops and starts timer with a delay of |delta|.
292   void RestartQueryForTopSitesTimer(base::TimeDelta delta);
293 
294   // Callback after TopSitesBackend has finished migration. This tells history
295   // to finish it's side of migration (nuking thumbnails on disk).
296   void OnHistoryMigrationWrittenToDisk(
297       CancelableRequestProvider::Handle handle);
298 
299   // Callback from TopSites with the top sites/thumbnails.
300   void OnGotMostVisitedThumbnails(CancelableRequestProvider::Handle handle,
301                                   scoped_refptr<MostVisitedThumbnails> data,
302                                   bool may_need_history_migration);
303 
304   // Called when history service returns a list of top URLs.
305   void OnTopSitesAvailableFromHistory(CancelableRequestProvider::Handle handle,
306                                       MostVisitedURLList data);
307 
308   scoped_refptr<TopSitesBackend> backend_;
309 
310   // The top sites data.
311   scoped_ptr<TopSitesCache> cache_;
312 
313   // Copy of the top sites data that may be accessed on any thread (assuming
314   // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and
315   // pinned urls applied (|cache_| does not).
316   scoped_ptr<TopSitesCache> thread_safe_cache_;
317 
318   Profile* profile_;
319 
320   // Lock used to access |thread_safe_cache_|.
321   mutable base::Lock lock_;
322 
323   CancelableRequestConsumer cancelable_consumer_;
324 
325   // Timer that asks history for the top sites. This is used to make sure our
326   // data stays in sync with history.
327   base::OneShotTimer<TopSites> timer_;
328 
329   // The time we started |timer_| at. Only valid if |timer_| is running.
330   base::TimeTicks timer_start_time_;
331 
332   NotificationRegistrar registrar_;
333 
334   // The number of URLs changed on the last update.
335   size_t last_num_urls_changed_;
336 
337   // The map of requests for the top sites list. Can only be
338   // non-empty at startup. After we read the top sites from the DB, we'll
339   // always have a cached list.
340   PendingCallbackSet pending_callbacks_;
341 
342   // Stores thumbnails for unknown pages. When SetPageThumbnail is
343   // called, if we don't know about that URL yet and we don't have
344   // enough Top Sites (new profile), we store it until the next
345   // SetTopSites call.
346   TempImages temp_images_;
347 
348   // Blacklisted and pinned URLs are stored in Preferences.
349 
350   // Blacklisted URLs. They are filtered out from the list of Top
351   // Sites when GetMostVisitedURLs is called. Note that we are still
352   // storing all URLs, but filtering on access. It is a dictionary,
353   // key is the URL, value is a dummy value. This is owned by the
354   // PrefService.
355   const DictionaryValue* blacklist_;
356 
357   // This is a dictionary for the pinned URLs for the the most visited part of
358   // the new tab page. Key is the URL, value is index where it is pinned at (may
359   // be the same as key). This is owned by the PrefService.
360   const DictionaryValue* pinned_urls_;
361 
362   // See description above HistoryLoadState.
363   HistoryLoadState history_state_;
364 
365   // See description above TopSitesLoadState.
366   TopSitesLoadState top_sites_state_;
367 
368   // Are we loaded?
369   bool loaded_;
370 
371   DISALLOW_COPY_AND_ASSIGN(TopSites);
372 };
373 
374 }  // namespace history
375 
376 #endif  // CHROME_BROWSER_HISTORY_TOP_SITES_H_
377