• 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