| 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 |