Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2013 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_IMPL_H_
      6 #define CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_
      7 
      8 #include <list>
      9 #include <set>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/basictypes.h"
     15 #include "base/callback.h"
     16 #include "base/gtest_prod_util.h"
     17 #include "base/memory/ref_counted.h"
     18 #include "base/synchronization/lock.h"
     19 #include "base/task/cancelable_task_tracker.h"
     20 #include "base/time/time.h"
     21 #include "base/timer/timer.h"
     22 #include "chrome/browser/history/history_service.h"
     23 #include "chrome/browser/history/top_sites.h"
     24 #include "chrome/browser/history/top_sites_backend.h"
     25 #include "components/history/core/browser/history_types.h"
     26 #include "components/history/core/browser/page_usage_data.h"
     27 #include "components/history/core/common/thumbnail_score.h"
     28 #include "third_party/skia/include/core/SkColor.h"
     29 #include "ui/gfx/image/image.h"
     30 #include "url/gurl.h"
     31 
     32 class Profile;
     33 
     34 namespace base {
     35 class FilePath;
     36 class RefCountedBytes;
     37 class RefCountedMemory;
     38 }
     39 
     40 namespace history {
     41 
     42 class TopSitesCache;
     43 class TopSitesImplTest;
     44 
     45 // This class allows requests for most visited urls and thumbnails on any
     46 // thread. All other methods must be invoked on the UI thread. All mutations
     47 // to internal state happen on the UI thread and are scheduled to update the
     48 // db using TopSitesBackend.
     49 class TopSitesImpl : public TopSites {
     50  public:
     51   explicit TopSitesImpl(Profile* profile);
     52 
     53   // Initializes TopSitesImpl.
     54   void Init(const base::FilePath& db_name);
     55 
     56   virtual bool SetPageThumbnail(const GURL& url,
     57                                 const gfx::Image& thumbnail,
     58                                 const ThumbnailScore& score) OVERRIDE;
     59   virtual bool SetPageThumbnailToJPEGBytes(
     60       const GURL& url,
     61       const base::RefCountedMemory* memory,
     62       const ThumbnailScore& score) OVERRIDE;
     63   virtual void GetMostVisitedURLs(
     64       const GetMostVisitedURLsCallback& callback,
     65       bool include_forced_urls) OVERRIDE;
     66   virtual bool GetPageThumbnail(
     67       const GURL& url,
     68       bool prefix_match,
     69       scoped_refptr<base::RefCountedMemory>* bytes) OVERRIDE;
     70   virtual bool GetPageThumbnailScore(const GURL& url,
     71                                      ThumbnailScore* score) OVERRIDE;
     72   virtual bool GetTemporaryPageThumbnailScore(const GURL& url,
     73                                               ThumbnailScore* score) OVERRIDE;
     74   virtual void SyncWithHistory() OVERRIDE;
     75   virtual bool HasBlacklistedItems() const OVERRIDE;
     76   virtual void AddBlacklistedURL(const GURL& url) OVERRIDE;
     77   virtual void RemoveBlacklistedURL(const GURL& url) OVERRIDE;
     78   virtual bool IsBlacklisted(const GURL& url) OVERRIDE;
     79   virtual void ClearBlacklistedURLs() OVERRIDE;
     80   virtual void Shutdown() OVERRIDE;
     81   virtual base::CancelableTaskTracker::TaskId StartQueryForMostVisited()
     82       OVERRIDE;
     83   virtual bool IsKnownURL(const GURL& url) OVERRIDE;
     84   virtual const std::string& GetCanonicalURLString(
     85       const GURL& url) const OVERRIDE;
     86   virtual bool IsNonForcedFull() OVERRIDE;
     87   virtual bool IsForcedFull() OVERRIDE;
     88   virtual MostVisitedURLList GetPrepopulatePages() OVERRIDE;
     89   virtual bool loaded() const OVERRIDE;
     90   virtual bool AddForcedURL(const GURL& url, const base::Time& time) OVERRIDE;
     91 
     92  protected:
     93   virtual ~TopSitesImpl();
     94 
     95  private:
     96   friend class TopSitesImplTest;
     97   FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited);
     98   FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced);
     99 
    100   typedef base::Callback<void(const MostVisitedURLList&,
    101                               const MostVisitedURLList&)> PendingCallback;
    102 
    103   typedef std::pair<GURL, Images> TempImage;
    104   typedef std::list<TempImage> TempImages;
    105   typedef std::vector<PendingCallback> PendingCallbacks;
    106 
    107   // Generates the diff of things that happened between "old" and "new."
    108   //
    109   // This treats forced URLs separately than non-forced URLs.
    110   //
    111   // The URLs that are in "new" but not "old" will be have their index into
    112   // "new" put in |added_urls|. The non-forced URLs that are in "old" but not
    113   // "new" will have their index into "old" put into |deleted_urls|.
    114   //
    115   // URLs appearing in both old and new lists but having different indices will
    116   // have their index into "new" be put into |moved_urls|.
    117   static void DiffMostVisited(const MostVisitedURLList& old_list,
    118                               const MostVisitedURLList& new_list,
    119                               TopSitesDelta* delta);
    120 
    121   // Sets the thumbnail without writing to the database. Useful when
    122   // reading last known top sites from the DB.
    123   // Returns true if the thumbnail was set, false if the existing one is better.
    124   bool SetPageThumbnailNoDB(const GURL& url,
    125                             const base::RefCountedMemory* thumbnail_data,
    126                             const ThumbnailScore& score);
    127 
    128   // A version of SetPageThumbnail that takes RefCountedBytes as
    129   // returned by HistoryService.
    130   bool SetPageThumbnailEncoded(const GURL& url,
    131                                const base::RefCountedMemory* thumbnail,
    132                                const ThumbnailScore& score);
    133 
    134   // Encodes the bitmap to bytes for storage to the db. Returns true if the
    135   // bitmap was successfully encoded.
    136   static bool EncodeBitmap(const gfx::Image& bitmap,
    137                            scoped_refptr<base::RefCountedBytes>* bytes);
    138 
    139   // Removes the cached thumbnail for url. Does nothing if |url| if not cached
    140   // in |temp_images_|.
    141   void RemoveTemporaryThumbnailByURL(const GURL& url);
    142 
    143   // Add a thumbnail for an unknown url. See temp_thumbnails_map_.
    144   void AddTemporaryThumbnail(const GURL& url,
    145                              const base::RefCountedMemory* thumbnail,
    146                              const ThumbnailScore& score);
    147 
    148   // Called by our timer. Starts the query for the most visited sites.
    149   void TimerFired();
    150 
    151   // Finds the given URL in the redirect chain for the given TopSite, and
    152   // returns the distance from the destination in hops that the given URL is.
    153   // The URL is assumed to be in the list. The destination is 0.
    154   static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
    155                                        const GURL& url);
    156 
    157   // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
    158   // Returns true if any pages were added.
    159   bool AddPrepopulatedPages(MostVisitedURLList* urls,
    160                             size_t num_forced_urls);
    161 
    162   // Add all the forced URLs from |cache_| into |new_list|, making sure not to
    163   // add any URL that's already in |new_list|'s non-forced URLs. The forced URLs
    164   // in |cache_| and |new_list| are assumed to appear at the front of the list
    165   // and be sorted in increasing |last_forced_time|. This will still be true
    166   // after the call. If the list of forced URLs overflows the older ones are
    167   // dropped. Returns the number of forced URLs after the merge.
    168   size_t MergeCachedForcedURLs(MostVisitedURLList* new_list);
    169 
    170   // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs.
    171   // Also ensures we respect the maximum number of forced URLs and non-forced
    172   // URLs.
    173   void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out);
    174 
    175   // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
    176   std::string GetURLHash(const GURL& url);
    177 
    178   // Returns the delay until the next update of history is needed.
    179   // Uses num_urls_changed
    180   base::TimeDelta GetUpdateDelay();
    181 
    182   // Implementation of content::NotificationObserver.
    183   virtual void Observe(int type,
    184                        const content::NotificationSource& source,
    185                        const content::NotificationDetails& details) OVERRIDE;
    186 
    187   // Updates URLs in |cache_| and the db (in the background).
    188   // The non-forced URLs in |new_top_sites| replace those in |cache_|.
    189   // The forced URLs of |new_top_sites| are merged with those in |cache_|,
    190   // if the list of forced URLs overflows, the oldest ones are dropped.
    191   // All mutations to cache_ *must* go through this. Should
    192   // be called from the UI thread.
    193   void SetTopSites(const MostVisitedURLList& new_top_sites);
    194 
    195   // Returns the number of most visited results to request from history. This
    196   // changes depending upon how many urls have been blacklisted. Should be
    197   // called from the UI thread.
    198   int num_results_to_request_from_history() const;
    199 
    200   // Invoked when transitioning to LOADED. Notifies any queued up callbacks.
    201   // Should be called from the UI thread.
    202   void MoveStateToLoaded();
    203 
    204   void ResetThreadSafeCache();
    205 
    206   void ResetThreadSafeImageCache();
    207 
    208   // Stops and starts timer with a delay of |delta|.
    209   void RestartQueryForTopSitesTimer(base::TimeDelta delta);
    210 
    211   // Callback from TopSites with the top sites/thumbnails. Should be called
    212   // from the UI thread.
    213   void OnGotMostVisitedThumbnails(
    214       const scoped_refptr<MostVisitedThumbnails>& thumbnails);
    215 
    216   // Called when history service returns a list of top URLs.
    217   void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data);
    218 
    219   scoped_refptr<TopSitesBackend> backend_;
    220 
    221   // The top sites data.
    222   scoped_ptr<TopSitesCache> cache_;
    223 
    224   // Copy of the top sites data that may be accessed on any thread (assuming
    225   // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and
    226   // pinned urls applied (|cache_| does not).
    227   scoped_ptr<TopSitesCache> thread_safe_cache_;
    228 
    229   Profile* profile_;
    230 
    231   // Lock used to access |thread_safe_cache_|.
    232   mutable base::Lock lock_;
    233 
    234   // Task tracker for history and backend requests.
    235   base::CancelableTaskTracker cancelable_task_tracker_;
    236 
    237   // Timer that asks history for the top sites. This is used to make sure our
    238   // data stays in sync with history.
    239   base::OneShotTimer<TopSitesImpl> timer_;
    240 
    241   // The time we started |timer_| at. Only valid if |timer_| is running.
    242   base::TimeTicks timer_start_time_;
    243 
    244   content::NotificationRegistrar registrar_;
    245 
    246   // The number of URLs changed on the last update.
    247   size_t last_num_urls_changed_;
    248 
    249   // The pending requests for the top sites list. Can only be non-empty at
    250   // startup. After we read the top sites from the DB, we'll always have a
    251   // cached list and be able to run callbacks immediately.
    252   PendingCallbacks pending_callbacks_;
    253 
    254   // Stores thumbnails for unknown pages. When SetPageThumbnail is
    255   // called, if we don't know about that URL yet and we don't have
    256   // enough Top Sites (new profile), we store it until the next
    257   // SetNonForcedTopSites call.
    258   TempImages temp_images_;
    259 
    260   // URL List of prepopulated page.
    261   std::vector<GURL> prepopulated_page_urls_;
    262 
    263   // Are we loaded?
    264   bool loaded_;
    265 
    266   DISALLOW_COPY_AND_ASSIGN(TopSitesImpl);
    267 };
    268 
    269 }  // namespace history
    270 
    271 #endif  // CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_
    272