top_sites.h revision 201ade2fbba22bfb27ae029f4d23fca6ded109a0
1// Copyright (c) 2010 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 13#include "base/basictypes.h" 14#include "base/gtest_prod_util.h" 15#include "base/lock.h" 16#include "base/ref_counted.h" 17#include "base/ref_counted_memory.h" 18#include "base/time.h" 19#include "base/timer.h" 20#include "chrome/browser/browser_thread.h" 21#include "chrome/browser/cancelable_request.h" 22#include "chrome/browser/history/history_types.h" 23#include "chrome/browser/history/history.h" 24#include "chrome/browser/history/page_usage_data.h" 25#include "chrome/common/notification_service.h" 26#include "chrome/common/thumbnail_score.h" 27#include "googleurl/src/gurl.h" 28 29class DictionaryValue; 30class FilePath; 31class SkBitmap; 32class Profile; 33 34namespace history { 35 36class TopSitesCache; 37class TopSitesBackend; 38class TopSitesTest; 39 40// Stores the data for the top "most visited" sites. This includes a cache of 41// the most visited data from history, as well as the corresponding thumbnails 42// of those sites. 43// 44// This class allows requests for most visited urls and thumbnails on any 45// thread. All other methods must be invoked on the UI thread. All mutations 46// to internal state happen on the UI thread and are scheduled to update the 47// db using TopSitesBackend. 48class TopSites 49 : public base::RefCountedThreadSafe<TopSites>, 50 public NotificationObserver, 51 public CancelableRequestProvider { 52 public: 53 explicit TopSites(Profile* profile); 54 55 // Returns whether top sites is enabled. 56 static bool IsEnabled(); 57 58 // Initializes TopSites. 59 void Init(const FilePath& db_name); 60 61 // Sets the given thumbnail for the given URL. Returns true if the thumbnail 62 // was updated. False means either the URL wasn't known to us, or we felt 63 // that our current thumbnail was superior to the given one. 64 bool SetPageThumbnail(const GURL& url, 65 const SkBitmap& thumbnail, 66 const ThumbnailScore& score); 67 68 // Callback for GetMostVisitedURLs. 69 typedef Callback1<const MostVisitedURLList&>::Type GetTopSitesCallback; 70 typedef std::set<scoped_refptr<CancelableRequest<GetTopSitesCallback> > > 71 PendingCallbackSet; 72 73 // Returns a list of most visited URLs via a callback. 74 // This may be invoked on any thread. 75 // NOTE: the callback may be called immediately if we have the data cached. 76 void GetMostVisitedURLs(CancelableRequestConsumer* consumer, 77 GetTopSitesCallback* callback); 78 79 // Get a thumbnail for a given page. Returns true iff we have the thumbnail. 80 // This may be invoked on any thread. 81 // As this method may be invoked on any thread the ref count needs to be 82 // upped before this method returns, so this takes a scoped_refptr*. 83 bool GetPageThumbnail(const GURL& url, 84 scoped_refptr<RefCountedBytes>* bytes); 85 86 // Invoked from History if migration is needed. If this is invoked it will 87 // be before HistoryLoaded is invoked. 88 void MigrateFromHistory(); 89 90 // Invoked with data from migrating thumbnails out of history. 91 void FinishHistoryMigration(const ThumbnailMigration& data); 92 93 // Invoked from history when it finishes loading. If MigrateFromHistory was 94 // not invoked at this point then we load from the top sites service. 95 void HistoryLoaded(); 96 97 // Blacklisted URLs 98 99 // Returns true if there is at least one item in the blacklist. 100 bool HasBlacklistedItems() const; 101 102 // Add a URL to the blacklist. 103 void AddBlacklistedURL(const GURL& url); 104 105 // Removes a URL from the blacklist. 106 void RemoveBlacklistedURL(const GURL& url); 107 108 // Returns true if the URL is blacklisted. 109 bool IsBlacklisted(const GURL& url); 110 111 // Clear the blacklist. 112 void ClearBlacklistedURLs(); 113 114 // Pinned URLs 115 116 // Pin a URL at |index|. 117 void AddPinnedURL(const GURL& url, size_t index); 118 119 // Returns true if a URL is pinned. 120 bool IsURLPinned(const GURL& url); 121 122 // Unpin a URL. 123 void RemovePinnedURL(const GURL& url); 124 125 // Return a URL pinned at |index| via |out|. Returns true if there 126 // is a URL pinned at |index|. 127 bool GetPinnedURLAtIndex(size_t index, GURL* out); 128 129 // Shuts down top sites. 130 void Shutdown(); 131 132 // Generates the diff of things that happened between "old" and "new." 133 // 134 // The URLs that are in "new" but not "old" will be have their index into 135 // "new" put in |added_urls|. The URLs that are in "old" but not "new" will 136 // have their index into "old" put into |deleted_urls|. 137 // 138 // URLs appearing in both old and new lists but having different indices will 139 // have their index into "new" be put into |moved_urls|. 140 static void DiffMostVisited(const MostVisitedURLList& old_list, 141 const MostVisitedURLList& new_list, 142 TopSitesDelta* delta); 143 144 // Query history service for the list of available thumbnails. Returns the 145 // handle for the request, or NULL if a request could not be made. 146 // Public only for testing purposes. 147 CancelableRequestProvider::Handle StartQueryForMostVisited(); 148 149 bool loaded() const { return loaded_; } 150 151 private: 152 friend class base::RefCountedThreadSafe<TopSites>; 153 friend class TopSitesTest; 154 155 typedef std::pair<GURL, Images> TempImage; 156 typedef std::list<TempImage> TempImages; 157 158 // Enumeration of the possible states history can be in. 159 enum HistoryLoadState { 160 // We're waiting for history to finish loading. 161 HISTORY_LOADING, 162 163 // History finished loading and we need to migrate top sites out of history. 164 HISTORY_MIGRATING, 165 166 // History is loaded. 167 HISTORY_LOADED 168 }; 169 170 // Enumeration of possible states the top sites backend can be in. 171 enum TopSitesLoadState { 172 // We're waiting for the backend to finish loading. 173 TOP_SITES_LOADING, 174 175 // The backend finished loading, but we may need to migrate. This is true if 176 // the top sites db didn't exist, or if the db existed but is from an old 177 // version. 178 TOP_SITES_LOADED_WAITING_FOR_HISTORY, 179 180 // Top sites is loaded. 181 TOP_SITES_LOADED 182 }; 183 184 ~TopSites(); 185 186 // Sets the thumbnail without writing to the database. Useful when 187 // reading last known top sites from the DB. 188 // Returns true if the thumbnail was set, false if the existing one is better. 189 bool SetPageThumbnailNoDB(const GURL& url, 190 const RefCountedBytes* thumbnail_data, 191 const ThumbnailScore& score); 192 193 // A version of SetPageThumbnail that takes RefCountedBytes as 194 // returned by HistoryService. 195 bool SetPageThumbnailEncoded(const GURL& url, 196 const RefCountedBytes* thumbnail, 197 const ThumbnailScore& score); 198 199 // Encodes the bitmap to bytes for storage to the db. Returns true if the 200 // bitmap was successfully encoded. 201 static bool EncodeBitmap(const SkBitmap& bitmap, 202 scoped_refptr<RefCountedBytes>* bytes); 203 204 // Removes the cached thumbnail for url. Does nothing if |url| if not cached 205 // in |temp_images_|. 206 void RemoveTemporaryThumbnailByURL(const GURL& url); 207 208 // Add a thumbnail for an unknown url. See temp_thumbnails_map_. 209 void AddTemporaryThumbnail(const GURL& url, 210 const RefCountedBytes* thumbnail, 211 const ThumbnailScore& score); 212 213 // Called by our timer. Starts the query for the most visited sites. 214 void TimerFired(); 215 216 // Finds the given URL in the redirect chain for the given TopSite, and 217 // returns the distance from the destination in hops that the given URL is. 218 // The URL is assumed to be in the list. The destination is 0. 219 static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited, 220 const GURL& url); 221 222 // Returns the set of prepopulate pages. 223 static MostVisitedURLList GetPrepopulatePages(); 224 225 // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|. 226 // Returns true if any pages were added. 227 static bool AddPrepopulatedPages(MostVisitedURLList* urls); 228 229 // Convert pinned_urls_ dictionary to the new format. Use URLs as 230 // dictionary keys. 231 void MigratePinnedURLs(); 232 233 // Takes |urls|, produces it's copy in |out| after removing 234 // blacklisted URLs and reordering pinned URLs. 235 void ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls, 236 MostVisitedURLList* out); 237 238 // Converts a url into a canonical string representation. 239 std::string GetURLString(const GURL& url); 240 241 // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. 242 std::string GetURLHash(const GURL& url); 243 244 // Returns the delay until the next update of history is needed. 245 // Uses num_urls_changed 246 base::TimeDelta GetUpdateDelay(); 247 248 // Executes all of the callbacks in |pending_callbacks|. This is used after 249 // we finish loading if any requests came in before we loaded. 250 static void ProcessPendingCallbacks( 251 const PendingCallbackSet& pending_callbacks, 252 const MostVisitedURLList& urls); 253 254 // Implementation of NotificationObserver. 255 virtual void Observe(NotificationType type, 256 const NotificationSource& source, 257 const NotificationDetails& details); 258 259 // Resets top_sites_ and updates the db (in the background). All mutations to 260 // top_sites_ *must* go through this. 261 void SetTopSites(const MostVisitedURLList& new_top_sites); 262 263 // Returns the number of most visted results to request from history. This 264 // changes depending upon how many urls have been blacklisted. 265 int num_results_to_request_from_history() const; 266 267 // Invoked when transitioning to LOADED. Notifies any queued up callbacks. 268 void MoveStateToLoaded(); 269 270 void ResetThreadSafeCache(); 271 272 void ResetThreadSafeImageCache(); 273 274 // Stops and starts timer with a delay of |delta|. 275 void RestartQueryForTopSitesTimer(base::TimeDelta delta); 276 277 // Callback after TopSitesBackend has finished migration. This tells history 278 // to finish it's side of migration (nuking thumbnails on disk). 279 void OnHistoryMigrationWrittenToDisk( 280 CancelableRequestProvider::Handle handle); 281 282 // Callback from TopSites with the top sites/thumbnails. 283 void OnGotMostVisitedThumbnails(CancelableRequestProvider::Handle handle, 284 scoped_refptr<MostVisitedThumbnails> data, 285 bool may_need_history_migration); 286 287 // Called when history service returns a list of top URLs. 288 void OnTopSitesAvailableFromHistory(CancelableRequestProvider::Handle handle, 289 MostVisitedURLList data); 290 291 scoped_refptr<TopSitesBackend> backend_; 292 293 // The top sites data. 294 scoped_ptr<TopSitesCache> cache_; 295 296 // Copy of the top sites data that may be accessed on any thread (assuming 297 // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and 298 // pinned urls applied (|cache_| does not). 299 scoped_ptr<TopSitesCache> thread_safe_cache_; 300 301 Profile* profile_; 302 303 // Lock used to access |thread_safe_cache_|. 304 mutable Lock lock_; 305 306 CancelableRequestConsumer cancelable_consumer_; 307 308 // Timer that asks history for the top sites. This is used to make sure our 309 // data stays in sync with history. 310 base::OneShotTimer<TopSites> timer_; 311 312 // The time we started |timer_| at. Only valid if |timer_| is running. 313 base::TimeTicks timer_start_time_; 314 315 NotificationRegistrar registrar_; 316 317 // The number of URLs changed on the last update. 318 size_t last_num_urls_changed_; 319 320 // The map of requests for the top sites list. Can only be 321 // non-empty at startup. After we read the top sites from the DB, we'll 322 // always have a cached list. 323 PendingCallbackSet pending_callbacks_; 324 325 // Stores thumbnails for unknown pages. When SetPageThumbnail is 326 // called, if we don't know about that URL yet and we don't have 327 // enough Top Sites (new profile), we store it until the next 328 // SetTopSites call. 329 TempImages temp_images_; 330 331 // Blacklisted and pinned URLs are stored in Preferences. 332 333 // Blacklisted URLs. They are filtered out from the list of Top 334 // Sites when GetMostVisitedURLs is called. Note that we are still 335 // storing all URLs, but filtering on access. It is a dictionary, 336 // key is the URL, value is a dummy value. This is owned by the 337 // PrefService. 338 DictionaryValue* blacklist_; 339 340 // This is a dictionary for the pinned URLs for the the most visited part of 341 // the new tab page. Key is the URL, value is index where it is pinned at (may 342 // be the same as key). This is owned by the PrefService. 343 DictionaryValue* pinned_urls_; 344 345 // See description above HistoryLoadState. 346 HistoryLoadState history_state_; 347 348 // See description above TopSitesLoadState. 349 TopSitesLoadState top_sites_state_; 350 351 // Are we loaded? 352 bool loaded_; 353 354 DISALLOW_COPY_AND_ASSIGN(TopSites); 355}; 356 357} // namespace history 358 359#endif // CHROME_BROWSER_HISTORY_TOP_SITES_H_ 360