// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_ #define CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_ #include #include #include #include #include #include "base/basictypes.h" #include "base/callback.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/task/cancelable_task_tracker.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/history/history_service.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/history/top_sites.h" #include "chrome/browser/history/top_sites_backend.h" #include "components/history/core/browser/page_usage_data.h" #include "components/history/core/common/thumbnail_score.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/image/image.h" #include "url/gurl.h" class Profile; namespace base { class FilePath; class RefCountedBytes; class RefCountedMemory; } namespace history { class TopSitesCache; class TopSitesImplTest; // This class allows requests for most visited urls and thumbnails on any // thread. All other methods must be invoked on the UI thread. All mutations // to internal state happen on the UI thread and are scheduled to update the // db using TopSitesBackend. class TopSitesImpl : public TopSites { public: explicit TopSitesImpl(Profile* profile); // Initializes TopSitesImpl. void Init(const base::FilePath& db_name); virtual bool SetPageThumbnail(const GURL& url, const gfx::Image& thumbnail, const ThumbnailScore& score) OVERRIDE; virtual bool SetPageThumbnailToJPEGBytes( const GURL& url, const base::RefCountedMemory* memory, const ThumbnailScore& score) OVERRIDE; virtual void GetMostVisitedURLs( const GetMostVisitedURLsCallback& callback, bool include_forced_urls) OVERRIDE; virtual bool GetPageThumbnail( const GURL& url, bool prefix_match, scoped_refptr* bytes) OVERRIDE; virtual bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score) OVERRIDE; virtual bool GetTemporaryPageThumbnailScore(const GURL& url, ThumbnailScore* score) OVERRIDE; virtual void SyncWithHistory() OVERRIDE; virtual bool HasBlacklistedItems() const OVERRIDE; virtual void AddBlacklistedURL(const GURL& url) OVERRIDE; virtual void RemoveBlacklistedURL(const GURL& url) OVERRIDE; virtual bool IsBlacklisted(const GURL& url) OVERRIDE; virtual void ClearBlacklistedURLs() OVERRIDE; virtual void Shutdown() OVERRIDE; virtual base::CancelableTaskTracker::TaskId StartQueryForMostVisited() OVERRIDE; virtual bool IsKnownURL(const GURL& url) OVERRIDE; virtual const std::string& GetCanonicalURLString( const GURL& url) const OVERRIDE; virtual bool IsNonForcedFull() OVERRIDE; virtual bool IsForcedFull() OVERRIDE; virtual MostVisitedURLList GetPrepopulatePages() OVERRIDE; virtual bool loaded() const OVERRIDE; virtual bool AddForcedURL(const GURL& url, const base::Time& time) OVERRIDE; protected: virtual ~TopSitesImpl(); private: friend class TopSitesImplTest; FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited); FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced); typedef base::Callback PendingCallback; typedef std::pair TempImage; typedef std::list TempImages; typedef std::vector PendingCallbacks; // Generates the diff of things that happened between "old" and "new." // // This treats forced URLs separately than non-forced URLs. // // The URLs that are in "new" but not "old" will be have their index into // "new" put in |added_urls|. The non-forced URLs that are in "old" but not // "new" will have their index into "old" put into |deleted_urls|. // // URLs appearing in both old and new lists but having different indices will // have their index into "new" be put into |moved_urls|. static void DiffMostVisited(const MostVisitedURLList& old_list, const MostVisitedURLList& new_list, TopSitesDelta* delta); // Sets the thumbnail without writing to the database. Useful when // reading last known top sites from the DB. // Returns true if the thumbnail was set, false if the existing one is better. bool SetPageThumbnailNoDB(const GURL& url, const base::RefCountedMemory* thumbnail_data, const ThumbnailScore& score); // A version of SetPageThumbnail that takes RefCountedBytes as // returned by HistoryService. bool SetPageThumbnailEncoded(const GURL& url, const base::RefCountedMemory* thumbnail, const ThumbnailScore& score); // Encodes the bitmap to bytes for storage to the db. Returns true if the // bitmap was successfully encoded. static bool EncodeBitmap(const gfx::Image& bitmap, scoped_refptr* bytes); // Removes the cached thumbnail for url. Does nothing if |url| if not cached // in |temp_images_|. void RemoveTemporaryThumbnailByURL(const GURL& url); // Add a thumbnail for an unknown url. See temp_thumbnails_map_. void AddTemporaryThumbnail(const GURL& url, const base::RefCountedMemory* thumbnail, const ThumbnailScore& score); // Called by our timer. Starts the query for the most visited sites. void TimerFired(); // Finds the given URL in the redirect chain for the given TopSite, and // returns the distance from the destination in hops that the given URL is. // The URL is assumed to be in the list. The destination is 0. static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited, const GURL& url); // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|. // Returns true if any pages were added. bool AddPrepopulatedPages(MostVisitedURLList* urls, size_t num_forced_urls); // Add all the forced URLs from |cache_| into |new_list|, making sure not to // add any URL that's already in |new_list|'s non-forced URLs. The forced URLs // in |cache_| and |new_list| are assumed to appear at the front of the list // and be sorted in increasing |last_forced_time|. This will still be true // after the call. If the list of forced URLs overflows the older ones are // dropped. Returns the number of forced URLs after the merge. size_t MergeCachedForcedURLs(MostVisitedURLList* new_list); // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. // Also ensures we respect the maximum number of forced URLs and non-forced // URLs. void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. std::string GetURLHash(const GURL& url); // Returns the delay until the next update of history is needed. // Uses num_urls_changed base::TimeDelta GetUpdateDelay(); // Implementation of content::NotificationObserver. virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; // Updates URLs in |cache_| and the db (in the background). // The non-forced URLs in |new_top_sites| replace those in |cache_|. // The forced URLs of |new_top_sites| are merged with those in |cache_|, // if the list of forced URLs overflows, the oldest ones are dropped. // All mutations to cache_ *must* go through this. Should // be called from the UI thread. void SetTopSites(const MostVisitedURLList& new_top_sites); // Returns the number of most visited results to request from history. This // changes depending upon how many urls have been blacklisted. Should be // called from the UI thread. int num_results_to_request_from_history() const; // Invoked when transitioning to LOADED. Notifies any queued up callbacks. // Should be called from the UI thread. void MoveStateToLoaded(); void ResetThreadSafeCache(); void ResetThreadSafeImageCache(); void NotifyTopSitesChanged(); // Stops and starts timer with a delay of |delta|. void RestartQueryForTopSitesTimer(base::TimeDelta delta); // Callback from TopSites with the top sites/thumbnails. Should be called // from the UI thread. void OnGotMostVisitedThumbnails( const scoped_refptr& thumbnails); // Called when history service returns a list of top URLs. void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data); scoped_refptr backend_; // The top sites data. scoped_ptr cache_; // Copy of the top sites data that may be accessed on any thread (assuming // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and // pinned urls applied (|cache_| does not). scoped_ptr thread_safe_cache_; Profile* profile_; // Lock used to access |thread_safe_cache_|. mutable base::Lock lock_; // Task tracker for history and backend requests. base::CancelableTaskTracker cancelable_task_tracker_; // Timer that asks history for the top sites. This is used to make sure our // data stays in sync with history. base::OneShotTimer timer_; // The time we started |timer_| at. Only valid if |timer_| is running. base::TimeTicks timer_start_time_; content::NotificationRegistrar registrar_; // The number of URLs changed on the last update. size_t last_num_urls_changed_; // The pending requests for the top sites list. Can only be non-empty at // startup. After we read the top sites from the DB, we'll always have a // cached list and be able to run callbacks immediately. PendingCallbacks pending_callbacks_; // Stores thumbnails for unknown pages. When SetPageThumbnail is // called, if we don't know about that URL yet and we don't have // enough Top Sites (new profile), we store it until the next // SetNonForcedTopSites call. TempImages temp_images_; // URL List of prepopulated page. std::vector prepopulated_page_urls_; // Are we loaded? bool loaded_; DISALLOW_COPY_AND_ASSIGN(TopSitesImpl); }; } // namespace history #endif // CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_