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