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