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.
5 #ifndef CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_
6 #define CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_
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"
36 class RefCountedBytes;
37 class RefCountedMemory;
43 class TopSitesImplTest;
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 {
51 explicit TopSitesImpl(Profile* profile);
53 // Initializes TopSitesImpl.
54 void Init(const base::FilePath& db_name);
56 virtual bool SetPageThumbnail(const GURL& url,
57 const gfx::Image& thumbnail,
58 const ThumbnailScore& score) OVERRIDE;
59 virtual bool SetPageThumbnailToJPEGBytes(
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(
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()
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;
93 virtual ~TopSitesImpl();
96 friend class TopSitesImplTest;
97 FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited);
98 FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced);
100 typedef base::Callback<void(const MostVisitedURLList&,
101 const MostVisitedURLList&)> PendingCallback;
103 typedef std::pair<GURL, Images> TempImage;
104 typedef std::list<TempImage> TempImages;
105 typedef std::vector<PendingCallback> PendingCallbacks;
107 // Generates the diff of things that happened between "old" and "new."
109 // This treats forced URLs separately than non-forced URLs.
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|.
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);
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);
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);
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);
139 // Removes the cached thumbnail for url. Does nothing if |url| if not cached
140 // in |temp_images_|.
141 void RemoveTemporaryThumbnailByURL(const GURL& url);
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);
148 // Called by our timer. Starts the query for the most visited sites.
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,
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);
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);
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
173 void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out);
175 // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
176 std::string GetURLHash(const GURL& url);
178 // Returns the delay until the next update of history is needed.
179 // Uses num_urls_changed
180 base::TimeDelta GetUpdateDelay();
182 // Implementation of content::NotificationObserver.
183 virtual void Observe(int type,
184 const content::NotificationSource& source,
185 const content::NotificationDetails& details) OVERRIDE;
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);
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;
200 // Invoked when transitioning to LOADED. Notifies any queued up callbacks.
201 // Should be called from the UI thread.
202 void MoveStateToLoaded();
204 void ResetThreadSafeCache();
206 void ResetThreadSafeImageCache();
208 // Stops and starts timer with a delay of |delta|.
209 void RestartQueryForTopSitesTimer(base::TimeDelta delta);
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);
216 // Called when history service returns a list of top URLs.
217 void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data);
219 scoped_refptr<TopSitesBackend> backend_;
221 // The top sites data.
222 scoped_ptr<TopSitesCache> cache_;
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_;
231 // Lock used to access |thread_safe_cache_|.
232 mutable base::Lock lock_;
234 // Task tracker for history and backend requests.
235 base::CancelableTaskTracker cancelable_task_tracker_;
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_;
241 // The time we started |timer_| at. Only valid if |timer_| is running.
242 base::TimeTicks timer_start_time_;
244 content::NotificationRegistrar registrar_;
246 // The number of URLs changed on the last update.
247 size_t last_num_urls_changed_;
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_;
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_;
260 // URL List of prepopulated page.
261 std::vector<GURL> prepopulated_page_urls_;
266 DISALLOW_COPY_AND_ASSIGN(TopSitesImpl);
269 } // namespace history
271 #endif // CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_