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_LIKELY_IMPL_H_
      6 #define CHROME_BROWSER_HISTORY_TOP_SITES_LIKELY_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/time/time.h"
     20 #include "base/timer/timer.h"
     21 #include "chrome/browser/common/cancelable_request.h"
     22 #include "chrome/browser/history/history_service.h"
     23 #include "chrome/browser/history/history_types.h"
     24 #include "chrome/browser/history/page_usage_data.h"
     25 #include "chrome/browser/history/top_sites.h"
     26 #include "chrome/browser/history/top_sites_backend.h"
     27 #include "chrome/common/cancelable_task_tracker.h"
     28 #include "chrome/common/thumbnail_score.h"
     29 #include "third_party/skia/include/core/SkColor.h"
     30 #include "ui/gfx/image/image.h"
     31 #include "url/gurl.h"
     32 
     33 class Profile;
     34 
     35 namespace base {
     36 class FilePath;
     37 class RefCountedBytes;
     38 class RefCountedMemory;
     39 }
     40 
     41 namespace history {
     42 
     43 class TopSitesCache;
     44 class TopSitesLikelyImplTest;
     45 
     46 
     47 // This class allows requests for most visited urls and thumbnails on any
     48 // thread. All other methods must be invoked on the UI thread. All mutations
     49 // to internal state happen on the UI thread and are scheduled to update the
     50 // db using TopSitesBackend.
     51 class TopSitesLikelyImpl : public TopSites {
     52  public:
     53   explicit TopSitesLikelyImpl(Profile* profile);
     54 
     55   // Initializes TopSitesLikelyImpl.
     56   void Init(const base::FilePath& db_name);
     57 
     58   virtual bool SetPageThumbnail(const GURL& url,
     59                         const gfx::Image& thumbnail,
     60                         const ThumbnailScore& score) OVERRIDE;
     61   virtual bool SetPageThumbnailToJPEGBytes(
     62       const GURL& url,
     63       const base::RefCountedMemory* memory,
     64       const ThumbnailScore& score) OVERRIDE;
     65   virtual void GetMostVisitedURLs(
     66       const GetMostVisitedURLsCallback& callback) OVERRIDE;
     67   virtual bool GetPageThumbnail(
     68       const GURL& url, scoped_refptr<base::RefCountedMemory>* bytes) OVERRIDE;
     69   virtual bool GetPageThumbnailScore(const GURL& url,
     70                                      ThumbnailScore* score) OVERRIDE;
     71   virtual bool GetTemporaryPageThumbnailScore(const GURL& url,
     72                                               ThumbnailScore* score) OVERRIDE;
     73   virtual void MigrateFromHistory() OVERRIDE;
     74   virtual void FinishHistoryMigration(const ThumbnailMigration& data) OVERRIDE;
     75   virtual void HistoryLoaded() OVERRIDE;
     76   virtual void SyncWithHistory() OVERRIDE;
     77   virtual bool HasBlacklistedItems() const OVERRIDE;
     78   virtual void AddBlacklistedURL(const GURL& url) OVERRIDE;
     79   virtual void RemoveBlacklistedURL(const GURL& url) OVERRIDE;
     80   virtual bool IsBlacklisted(const GURL& url) OVERRIDE;
     81   virtual void ClearBlacklistedURLs() OVERRIDE;
     82   virtual void Shutdown() OVERRIDE;
     83   virtual CancelableRequestProvider::Handle StartQueryForMostVisited() OVERRIDE;
     84   virtual bool IsKnownURL(const GURL& url) OVERRIDE;
     85   virtual const std::string& GetCanonicalURLString(
     86       const GURL& url) const OVERRIDE;
     87   virtual bool IsFull() OVERRIDE;
     88   virtual MostVisitedURLList GetPrepopulatePages() OVERRIDE;
     89   virtual bool loaded() const OVERRIDE;
     90 
     91  protected:
     92   virtual ~TopSitesLikelyImpl();
     93 
     94  private:
     95   friend class TopSitesLikelyImplTest;
     96   FRIEND_TEST_ALL_PREFIXES(TopSitesLikelyImplTest, DiffMostVisited);
     97 
     98   typedef std::pair<GURL, Images> TempImage;
     99   typedef std::list<TempImage> TempImages;
    100 
    101   // Generates the diff of things that happened between "old" and "new."
    102   //
    103   // The URLs that are in "new" but not "old" will be have their index into
    104   // "new" put in |added_urls|. The URLs that are in "old" but not "new" will
    105   // have their index into "old" put into |deleted_urls|.
    106   //
    107   // URLs appearing in both old and new lists but having different indices will
    108   // have their index into "new" be put into |moved_urls|.
    109   static void DiffMostVisited(const MostVisitedURLList& old_list,
    110                               const MostVisitedURLList& new_list,
    111                               TopSitesDelta* delta);
    112 
    113   // Enumeration of the possible states history can be in. These values do not
    114   // necessarily reflect the loaded state of history. In particular if the
    115   // history backend is unloaded |history_state_| may be HISTORY_LOADED.
    116   enum HistoryLoadState {
    117     // We're waiting for history to finish loading.
    118     HISTORY_LOADING,
    119 
    120     // History finished loading and we need to migrate top sites out of history.
    121     HISTORY_MIGRATING,
    122 
    123     // History is loaded.
    124     HISTORY_LOADED
    125   };
    126 
    127   // Enumeration of possible states the top sites backend can be in.
    128   enum TopSitesLoadState {
    129     // We're waiting for the backend to finish loading.
    130     TOP_SITES_LOADING,
    131 
    132     // The backend finished loading, but we may need to migrate. This is true if
    133     // the top sites db didn't exist, or if the db existed but is from an old
    134     // version.
    135     TOP_SITES_LOADED_WAITING_FOR_HISTORY,
    136 
    137     // Top sites is loaded.
    138     TOP_SITES_LOADED
    139   };
    140 
    141   // Sets the thumbnail without writing to the database. Useful when
    142   // reading last known top sites from the DB.
    143   // Returns true if the thumbnail was set, false if the existing one is better.
    144   bool SetPageThumbnailNoDB(const GURL& url,
    145                             const base::RefCountedMemory* thumbnail_data,
    146                             const ThumbnailScore& score);
    147 
    148   // A version of SetPageThumbnail that takes RefCountedBytes as
    149   // returned by HistoryService.
    150   bool SetPageThumbnailEncoded(const GURL& url,
    151                                const base::RefCountedMemory* thumbnail,
    152                                const ThumbnailScore& score);
    153 
    154   // Encodes the bitmap to bytes for storage to the db. Returns true if the
    155   // bitmap was successfully encoded.
    156   static bool EncodeBitmap(const gfx::Image& bitmap,
    157                            scoped_refptr<base::RefCountedBytes>* bytes);
    158 
    159   // Removes the cached thumbnail for url. Does nothing if |url| if not cached
    160   // in |temp_images_|.
    161   void RemoveTemporaryThumbnailByURL(const GURL& url);
    162 
    163   // Add a thumbnail for an unknown url. See temp_thumbnails_map_.
    164   void AddTemporaryThumbnail(const GURL& url,
    165                              const base::RefCountedMemory* thumbnail,
    166                              const ThumbnailScore& score);
    167 
    168   // Called by our timer. Starts the query for the most visited sites.
    169   void TimerFired();
    170 
    171   // Finds the given URL in the redirect chain for the given TopSite, and
    172   // returns the distance from the destination in hops that the given URL is.
    173   // The URL is assumed to be in the list. The destination is 0.
    174   static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
    175                                        const GURL& url);
    176 
    177   // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
    178   // Returns true if any pages were added.
    179   bool AddPrepopulatedPages(MostVisitedURLList* urls);
    180 
    181   // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs.
    182   void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out);
    183 
    184   // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
    185   std::string GetURLHash(const GURL& url);
    186 
    187   // Returns the delay until the next update of history is needed.
    188   // Uses num_urls_changed
    189   base::TimeDelta GetUpdateDelay();
    190 
    191   // Implementation of content::NotificationObserver.
    192   virtual void Observe(int type,
    193                        const content::NotificationSource& source,
    194                        const content::NotificationDetails& details) OVERRIDE;
    195 
    196   // Resets top_sites_ and updates the db (in the background). All mutations to
    197   // top_sites_ *must* go through this. Should be called from the UI thread.
    198   void SetTopSites(const MostVisitedURLList& new_top_sites);
    199 
    200   // Returns the number of most visted results to request from history. This
    201   // changes depending upon how many urls have been blacklisted. Should be
    202   // called from the UI thread.
    203   int num_results_to_request_from_history() const;
    204 
    205   // Invoked when transitioning to LOADED. Notifies any queued up callbacks.
    206   // Should be called from the UI thread.
    207   void MoveStateToLoaded();
    208 
    209   void ResetThreadSafeCache();
    210 
    211   void ResetThreadSafeImageCache();
    212 
    213   void NotifyTopSitesChanged();
    214 
    215   // Stops and starts timer with a delay of |delta|.
    216   void RestartQueryForTopSitesTimer(base::TimeDelta delta);
    217 
    218   // Callback after TopSitesBackend has finished migration. This tells history
    219   // to finish it's side of migration (nuking thumbnails on disk). Should be
    220   // called from the UI thread.
    221   void OnHistoryMigrationWrittenToDisk();
    222 
    223   // Callback from TopSites with the top sites/thumbnails. Should be called
    224   // from the UI thread.
    225   void OnGotMostVisitedThumbnails(
    226       const scoped_refptr<MostVisitedThumbnails>& thumbnails,
    227       const bool* need_history_migration);
    228 
    229   // Called when history service returns a list of top URLs.
    230   void OnTopSitesAvailableFromHistory(CancelableRequestProvider::Handle handle,
    231                                       MostVisitedURLList data);
    232 
    233   scoped_refptr<TopSitesBackend> backend_;
    234 
    235   // The top sites data.
    236   scoped_ptr<TopSitesCache> cache_;
    237 
    238   // Copy of the top sites data that may be accessed on any thread (assuming
    239   // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and
    240   // pinned urls applied (|cache_| does not).
    241   scoped_ptr<TopSitesCache> thread_safe_cache_;
    242 
    243   Profile* profile_;
    244 
    245   // Lock used to access |thread_safe_cache_|.
    246   mutable base::Lock lock_;
    247 
    248   // Need a separate consumer for each CancelableRequestProvider we interact
    249   // with (HistoryService and TopSitesBackend).
    250   CancelableRequestConsumer history_consumer_;
    251   CancelableTaskTracker cancelable_task_tracker_;
    252 
    253   // Timer that asks history for the top sites. This is used to make sure our
    254   // data stays in sync with history.
    255   base::OneShotTimer<TopSitesLikelyImpl> timer_;
    256 
    257   // The time we started |timer_| at. Only valid if |timer_| is running.
    258   base::TimeTicks timer_start_time_;
    259 
    260   content::NotificationRegistrar registrar_;
    261 
    262   // The number of URLs changed on the last update.
    263   size_t last_num_urls_changed_;
    264 
    265   // The pending requests for the top sites list. Can only be non-empty at
    266   // startup. After we read the top sites from the DB, we'll always have a
    267   // cached list and be able to run callbacks immediately.
    268   PendingCallbacks pending_callbacks_;
    269 
    270   // Stores thumbnails for unknown pages. When SetPageThumbnail is
    271   // called, if we don't know about that URL yet and we don't have
    272   // enough Top Sites (new profile), we store it until the next
    273   // SetTopSites call.
    274   TempImages temp_images_;
    275 
    276   // See description above HistoryLoadState.
    277   HistoryLoadState history_state_;
    278 
    279   // See description above TopSitesLoadState.
    280   TopSitesLoadState top_sites_state_;
    281 
    282   // URL List of prepopulated page.
    283   std::vector<GURL> prepopulated_page_urls_;
    284 
    285   // Are we loaded?
    286   bool loaded_;
    287 
    288   DISALLOW_COPY_AND_ASSIGN(TopSitesLikelyImpl);
    289 };
    290 
    291 }  // namespace history
    292 
    293 #endif  // CHROME_BROWSER_HISTORY_TOP_SITES_LIKELY_IMPL_H_
    294