OLD | NEW |
| (Empty) |
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/scoped_observer.h" | |
19 #include "base/synchronization/lock.h" | |
20 #include "base/task/cancelable_task_tracker.h" | |
21 #include "base/threading/thread_checker.h" | |
22 #include "base/time/time.h" | |
23 #include "base/timer/timer.h" | |
24 #include "components/history/core/browser/history_service.h" | |
25 #include "components/history/core/browser/history_service_observer.h" | |
26 #include "components/history/core/browser/history_types.h" | |
27 #include "components/history/core/browser/page_usage_data.h" | |
28 #include "components/history/core/browser/top_sites.h" | |
29 #include "components/history/core/browser/top_sites_backend.h" | |
30 #include "components/history/core/common/thumbnail_score.h" | |
31 #include "third_party/skia/include/core/SkColor.h" | |
32 #include "ui/gfx/image/image.h" | |
33 #include "url/gurl.h" | |
34 | |
35 class PrefService; | |
36 | |
37 namespace base { | |
38 class FilePath; | |
39 class RefCountedBytes; | |
40 class RefCountedMemory; | |
41 class SingleThreadTaskRunner; | |
42 } | |
43 | |
44 namespace history { | |
45 | |
46 class HistoryService; | |
47 class TopSitesCache; | |
48 class TopSitesImplTest; | |
49 | |
50 // This class allows requests for most visited urls and thumbnails on any | |
51 // thread. All other methods must be invoked on the UI thread. All mutations | |
52 // to internal state happen on the UI thread and are scheduled to update the | |
53 // db using TopSitesBackend. | |
54 class TopSitesImpl : public TopSites, public HistoryServiceObserver { | |
55 public: | |
56 TopSitesImpl(PrefService* pref_service, | |
57 HistoryService* history_service, | |
58 const char* blacklist_pref_name, | |
59 const PrepopulatedPageList& prepopulated_pages); | |
60 | |
61 // Initializes TopSitesImpl. | |
62 void Init(const base::FilePath& db_name, | |
63 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner); | |
64 | |
65 // TopSites implementation. | |
66 bool SetPageThumbnail(const GURL& url, | |
67 const gfx::Image& thumbnail, | |
68 const ThumbnailScore& score) override; | |
69 bool SetPageThumbnailToJPEGBytes(const GURL& url, | |
70 const base::RefCountedMemory* memory, | |
71 const ThumbnailScore& score) override; | |
72 void GetMostVisitedURLs(const GetMostVisitedURLsCallback& callback, | |
73 bool include_forced_urls) override; | |
74 bool GetPageThumbnail(const GURL& url, | |
75 bool prefix_match, | |
76 scoped_refptr<base::RefCountedMemory>* bytes) override; | |
77 bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score) override; | |
78 bool GetTemporaryPageThumbnailScore(const GURL& url, | |
79 ThumbnailScore* score) override; | |
80 void SyncWithHistory() override; | |
81 bool HasBlacklistedItems() const override; | |
82 void AddBlacklistedURL(const GURL& url) override; | |
83 void RemoveBlacklistedURL(const GURL& url) override; | |
84 bool IsBlacklisted(const GURL& url) override; | |
85 void ClearBlacklistedURLs() override; | |
86 base::CancelableTaskTracker::TaskId StartQueryForMostVisited() override; | |
87 bool IsKnownURL(const GURL& url) override; | |
88 const std::string& GetCanonicalURLString(const GURL& url) const override; | |
89 bool IsNonForcedFull() override; | |
90 bool IsForcedFull() override; | |
91 PrepopulatedPageList GetPrepopulatedPages() override; | |
92 bool loaded() const override; | |
93 bool AddForcedURL(const GURL& url, const base::Time& time) override; | |
94 void OnNavigationCommitted(const GURL& url) override; | |
95 | |
96 // RefcountedKeyedService: | |
97 void ShutdownOnUIThread() override; | |
98 | |
99 protected: | |
100 ~TopSitesImpl() override; | |
101 | |
102 private: | |
103 // TODO(yiyaoliu): Remove the enums and related code when crbug/223430 is | |
104 // fixed. | |
105 // An enum representing different situations under which function | |
106 // SetTopSites can be initiated. | |
107 // This is needed because a histogram is used to record speed related metrics | |
108 // when SetTopSites are initiated from OnGotMostVisitedThumbnails, which | |
109 // usually happens early and might affect Chrome startup speed. | |
110 enum CallLocation { | |
111 // SetTopSites is called from function OnGotMostVisitedThumbnails. | |
112 CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS, | |
113 // All other situations. | |
114 CALL_LOCATION_FROM_OTHER_PLACES | |
115 }; | |
116 | |
117 friend class TopSitesImplTest; | |
118 FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited); | |
119 FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced); | |
120 | |
121 typedef base::Callback<void(const MostVisitedURLList&, | |
122 const MostVisitedURLList&)> PendingCallback; | |
123 | |
124 typedef std::pair<GURL, Images> TempImage; | |
125 typedef std::list<TempImage> TempImages; | |
126 typedef std::vector<PendingCallback> PendingCallbacks; | |
127 | |
128 // Generates the diff of things that happened between "old" and "new." | |
129 // | |
130 // This treats forced URLs separately than non-forced URLs. | |
131 // | |
132 // The URLs that are in "new" but not "old" will be have their index into | |
133 // "new" put in |added_urls|. The non-forced URLs that are in "old" but not | |
134 // "new" will have their index into "old" put into |deleted_urls|. | |
135 // | |
136 // URLs appearing in both old and new lists but having different indices will | |
137 // have their index into "new" be put into |moved_urls|. | |
138 static void DiffMostVisited(const MostVisitedURLList& old_list, | |
139 const MostVisitedURLList& new_list, | |
140 TopSitesDelta* delta); | |
141 | |
142 // Sets the thumbnail without writing to the database. Useful when | |
143 // reading last known top sites from the DB. | |
144 // Returns true if the thumbnail was set, false if the existing one is better. | |
145 bool SetPageThumbnailNoDB(const GURL& url, | |
146 const base::RefCountedMemory* thumbnail_data, | |
147 const ThumbnailScore& score); | |
148 | |
149 // A version of SetPageThumbnail that takes RefCountedBytes as | |
150 // returned by HistoryService. | |
151 bool SetPageThumbnailEncoded(const GURL& url, | |
152 const base::RefCountedMemory* thumbnail, | |
153 const ThumbnailScore& score); | |
154 | |
155 // Encodes the bitmap to bytes for storage to the db. Returns true if the | |
156 // bitmap was successfully encoded. | |
157 static bool EncodeBitmap(const gfx::Image& bitmap, | |
158 scoped_refptr<base::RefCountedBytes>* bytes); | |
159 | |
160 // Removes the cached thumbnail for url. Does nothing if |url| if not cached | |
161 // in |temp_images_|. | |
162 void RemoveTemporaryThumbnailByURL(const GURL& url); | |
163 | |
164 // Add a thumbnail for an unknown url. See temp_thumbnails_map_. | |
165 void AddTemporaryThumbnail(const GURL& url, | |
166 const base::RefCountedMemory* thumbnail, | |
167 const ThumbnailScore& score); | |
168 | |
169 // Called by our timer. Starts the query for the most visited sites. | |
170 void TimerFired(); | |
171 | |
172 // Finds the given URL in the redirect chain for the given TopSite, and | |
173 // returns the distance from the destination in hops that the given URL is. | |
174 // The URL is assumed to be in the list. The destination is 0. | |
175 static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited, | |
176 const GURL& url); | |
177 | |
178 // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|. | |
179 // Returns true if any pages were added. | |
180 bool AddPrepopulatedPages(MostVisitedURLList* urls, | |
181 size_t num_forced_urls); | |
182 | |
183 // Add all the forced URLs from |cache_| into |new_list|, making sure not to | |
184 // add any URL that's already in |new_list|'s non-forced URLs. The forced URLs | |
185 // in |cache_| and |new_list| are assumed to appear at the front of the list | |
186 // and be sorted in increasing |last_forced_time|. This will still be true | |
187 // after the call. If the list of forced URLs overflows the older ones are | |
188 // dropped. Returns the number of forced URLs after the merge. | |
189 size_t MergeCachedForcedURLs(MostVisitedURLList* new_list); | |
190 | |
191 // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. | |
192 // Also ensures we respect the maximum number of forced URLs and non-forced | |
193 // URLs. | |
194 void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); | |
195 | |
196 // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. | |
197 std::string GetURLHash(const GURL& url); | |
198 | |
199 // Returns the delay until the next update of history is needed. | |
200 // Uses num_urls_changed | |
201 base::TimeDelta GetUpdateDelay(); | |
202 | |
203 // Updates URLs in |cache_| and the db (in the background). | |
204 // The non-forced URLs in |new_top_sites| replace those in |cache_|. | |
205 // The forced URLs of |new_top_sites| are merged with those in |cache_|, | |
206 // if the list of forced URLs overflows, the oldest ones are dropped. | |
207 // All mutations to cache_ *must* go through this. Should | |
208 // be called from the UI thread. | |
209 void SetTopSites(const MostVisitedURLList& new_top_sites, | |
210 const CallLocation location); | |
211 | |
212 // Returns the number of most visited results to request from history. This | |
213 // changes depending upon how many urls have been blacklisted. Should be | |
214 // called from the UI thread. | |
215 int num_results_to_request_from_history() const; | |
216 | |
217 // Invoked when transitioning to LOADED. Notifies any queued up callbacks. | |
218 // Should be called from the UI thread. | |
219 void MoveStateToLoaded(); | |
220 | |
221 void ResetThreadSafeCache(); | |
222 | |
223 void ResetThreadSafeImageCache(); | |
224 | |
225 // Stops and starts timer with a delay of |delta|. | |
226 void RestartQueryForTopSitesTimer(base::TimeDelta delta); | |
227 | |
228 // Callback from TopSites with the top sites/thumbnails. Should be called | |
229 // from the UI thread. | |
230 void OnGotMostVisitedThumbnails( | |
231 const scoped_refptr<MostVisitedThumbnails>& thumbnails); | |
232 | |
233 // Called when history service returns a list of top URLs. | |
234 void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data); | |
235 | |
236 // history::HistoryServiceObserver: | |
237 void OnURLsDeleted(HistoryService* history_service, | |
238 bool all_history, | |
239 bool expired, | |
240 const URLRows& deleted_rows, | |
241 const std::set<GURL>& favicon_urls) override; | |
242 | |
243 // Ensures that non thread-safe methods are called on the correct thread. | |
244 base::ThreadChecker thread_checker_; | |
245 | |
246 scoped_refptr<TopSitesBackend> backend_; | |
247 | |
248 // The top sites data. | |
249 scoped_ptr<TopSitesCache> cache_; | |
250 | |
251 // Copy of the top sites data that may be accessed on any thread (assuming | |
252 // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and | |
253 // pinned urls applied (|cache_| does not). | |
254 scoped_ptr<TopSitesCache> thread_safe_cache_; | |
255 | |
256 // Lock used to access |thread_safe_cache_|. | |
257 mutable base::Lock lock_; | |
258 | |
259 // Task tracker for history and backend requests. | |
260 base::CancelableTaskTracker cancelable_task_tracker_; | |
261 | |
262 // Timer that asks history for the top sites. This is used to make sure our | |
263 // data stays in sync with history. | |
264 base::OneShotTimer<TopSitesImpl> timer_; | |
265 | |
266 // The time we started |timer_| at. Only valid if |timer_| is running. | |
267 base::TimeTicks timer_start_time_; | |
268 | |
269 // The number of URLs changed on the last update. | |
270 size_t last_num_urls_changed_; | |
271 | |
272 // The pending requests for the top sites list. Can only be non-empty at | |
273 // startup. After we read the top sites from the DB, we'll always have a | |
274 // cached list and be able to run callbacks immediately. | |
275 PendingCallbacks pending_callbacks_; | |
276 | |
277 // Stores thumbnails for unknown pages. When SetPageThumbnail is | |
278 // called, if we don't know about that URL yet and we don't have | |
279 // enough Top Sites (new profile), we store it until the next | |
280 // SetNonForcedTopSites call. | |
281 TempImages temp_images_; | |
282 | |
283 // URL List of prepopulated page. | |
284 PrepopulatedPageList prepopulated_pages_; | |
285 | |
286 // PrefService holding the NTP URL blacklist dictionary. Must outlive | |
287 // TopSitesImpl. | |
288 PrefService* pref_service_; | |
289 | |
290 // Key for the NTP URL blacklist dictionary in PrefService. | |
291 const char* blacklist_pref_name_; | |
292 | |
293 // HistoryService that TopSitesImpl can query. May be null, but if defined it | |
294 // must outlive TopSitesImpl. | |
295 HistoryService* history_service_; | |
296 | |
297 // Are we loaded? | |
298 bool loaded_; | |
299 | |
300 // Have the SetTopSites execution time related histograms been recorded? | |
301 // The histogram should only be recorded once for each Chrome execution. | |
302 static bool histogram_recorded_; | |
303 | |
304 ScopedObserver<HistoryService, HistoryServiceObserver> | |
305 history_service_observer_; | |
306 | |
307 DISALLOW_COPY_AND_ASSIGN(TopSitesImpl); | |
308 }; | |
309 | |
310 } // namespace history | |
311 | |
312 #endif // CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_ | |
OLD | NEW |