diff options
-rw-r--r-- | chrome/browser/history/history_types.h | 2 | ||||
-rw-r--r-- | chrome/browser/history/top_sites.cc | 70 | ||||
-rw-r--r-- | chrome/browser/history/top_sites.h | 55 | ||||
-rw-r--r-- | chrome/browser/history/top_sites_unittest.cc | 57 |
4 files changed, 173 insertions, 11 deletions
diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h index b35f432..a2be051 100644 --- a/chrome/browser/history/history_types.h +++ b/chrome/browser/history/history_types.h @@ -504,7 +504,7 @@ struct KeywordSearchTermVisit { struct MostVisitedURL { GURL url; GURL favicon_url; - std::wstring title; + string16 title; RedirectList redirects; }; diff --git a/chrome/browser/history/top_sites.cc b/chrome/browser/history/top_sites.cc index 693fbfc7..b574a6c 100644 --- a/chrome/browser/history/top_sites.cc +++ b/chrome/browser/history/top_sites.cc @@ -5,12 +5,19 @@ #include "chrome/browser/history/top_sites.h" #include "base/logging.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/history/page_usage_data.h" #include "gfx/codec/jpeg_codec.h" #include "third_party/skia/include/core/SkBitmap.h" namespace history { -TopSites::TopSites() { +// How many top sites to store in the cache. +static const int kTopSitesNumber = 20; +static const int kDaysOfHistory = 90; + +TopSites::TopSites(Profile* profile) : profile_(profile), + mock_history_service_(NULL) { } TopSites::~TopSites() { @@ -58,6 +65,10 @@ bool TopSites::SetPageThumbnail(const GURL& url, return true; } +MostVisitedURLList TopSites::GetMostVisitedURLs() { + return top_sites_; +} + void TopSites::StoreMostVisited(std::vector<MostVisitedURL>* most_visited) { lock_.AssertAcquired(); // TODO(brettw) filter for blacklist! @@ -167,4 +178,61 @@ void TopSites::DiffMostVisited(const std::vector<MostVisitedURL>& old_list, } } +void TopSites::StartQueryForMostVisited() { + if (mock_history_service_) { + // Testing with a mockup. + // QuerySegmentUsageSince is not virtual, so we have to duplicate the code. + mock_history_service_->QuerySegmentUsageSince( + &cancelable_consumer_, + base::Time::Now() - base::TimeDelta::FromDays(kDaysOfHistory), + kTopSitesNumber, + NewCallback(this, &TopSites::OnTopSitesAvailable)); + } else { + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + // |hs| may be null during unit tests. + if (hs) { + hs->QuerySegmentUsageSince( + &cancelable_consumer_, + base::Time::Now() - base::TimeDelta::FromDays(kDaysOfHistory), + kTopSitesNumber, + NewCallback(this, &TopSites::OnTopSitesAvailable)); + } else { + LOG(INFO) << "History Service not available."; + } + } +} + +MostVisitedURL TopSites::MakeMostVisitedURL(const PageUsageData& page_data, + const RedirectList& redirects) { + MostVisitedURL mv; + mv.url = page_data.GetURL(); + mv.title = page_data.GetTitle(); + if (redirects.empty()) { + // Redirects must contain at least the target url. + mv.redirects.push_back(mv.url); + } else { + mv.redirects = redirects; + } + return mv; +} + +void TopSites::OnTopSitesAvailable( + CancelableRequestProvider::Handle handle, + std::vector<PageUsageData*>* pages) { + AutoLock lock(lock_); + std::vector<MostVisitedURL> most_visited; + + for (size_t i = 0; i < pages->size(); i++) { + PageUsageData* pd = (*pages)[i]; + MostVisitedURL mv = MakeMostVisitedURL(*pd, RedirectList()); + most_visited.push_back(mv); + } + + StoreMostVisited(&most_visited); +} + +void TopSites::SetMockHistoryService(MockHistoryService* mhs) { + mock_history_service_ = mhs; +} + } // namespace history diff --git a/chrome/browser/history/top_sites.h b/chrome/browser/history/top_sites.h index cce4606..f09fcf8 100644 --- a/chrome/browser/history/top_sites.h +++ b/chrome/browser/history/top_sites.h @@ -14,18 +14,23 @@ #include "base/lock.h" #include "base/ref_counted.h" #include "base/ref_counted_memory.h" +#include "chrome/browser/cancelable_request.h" #include "chrome/browser/history/history_types.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/history/page_usage_data.h" #include "chrome/common/thumbnail_score.h" #include "googleurl/src/gurl.h" class SkBitmap; -struct ThumbnailScore; +class Profile; namespace history { class TopSitesBackend; class TopSitesTest; +typedef std::vector<MostVisitedURL> MostVisitedURLList; + // Stores the data for the top "most visited" sites. This includes a cache of // the most visited data from history, as well as the corresponding thumbnails // of those sites. @@ -38,8 +43,18 @@ class TopSitesTest; // the UI thread is busy. class TopSites : public base::RefCountedThreadSafe<TopSites> { public: - TopSites(); - ~TopSites(); + explicit TopSites(Profile* profile); + + class MockHistoryService { + // A mockup of a HistoryService used for testing TopSites. + public: + virtual HistoryService::Handle QuerySegmentUsageSince( + CancelableRequestConsumerBase* consumer, + base::Time from_time, + int max_result_count, + HistoryService::SegmentQueryCallback* callback) = 0; + virtual ~MockHistoryService() {} + }; // Initializes this component, returning true on success. bool Init(); @@ -51,11 +66,17 @@ class TopSites : public base::RefCountedThreadSafe<TopSites> { const SkBitmap& thumbnail, const ThumbnailScore& score); + MostVisitedURLList GetMostVisitedURLs(); + // TODO(brettw): write this. // bool GetPageThumbnail(const GURL& url, RefCountedBytes** data) const; private: + friend class base::RefCountedThreadSafe<TopSites>; friend class TopSitesTest; + friend class TopSitesTest_GetMostVisited_Test; + + ~TopSites(); struct Images { scoped_refptr<RefCountedBytes> thumbnail; @@ -65,11 +86,22 @@ class TopSites : public base::RefCountedThreadSafe<TopSites> { // scoped_refptr<RefCountedBytes> favicon; }; + void StartQueryForMostVisited(); + + // Handler for the query response. + void OnTopSitesAvailable(CancelableRequestProvider::Handle handle, + std::vector<PageUsageData*>* data); + + // Converts from PageUsageData to MostVisitedURL. redirects is a + // list of redirects for this URL. Empty list means no redirects. + static MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, + const RedirectList& redirects); + // Saves the set of the top URLs visited by this user. The 0th item is the // most popular. // // DANGER! This will clear all data from the input argument. - void StoreMostVisited(std::vector<MostVisitedURL>* most_visited); + void StoreMostVisited(MostVisitedURLList* most_visited); // Saves the given set of redirects. The redirects are in order of the // given vector, so [0] -> [1] -> [2]. @@ -97,17 +129,25 @@ class TopSites : public base::RefCountedThreadSafe<TopSites> { // // 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 std::vector<MostVisitedURL>& old_list, - const std::vector<MostVisitedURL>& new_list, + static void DiffMostVisited(const MostVisitedURLList& old_list, + const MostVisitedURLList& new_list, std::vector<size_t>* added_urls, std::vector<size_t>* deleted_urls, std::vector<size_t>* moved_urls); + // For testing with a HistoryService mock. + void SetMockHistoryService(MockHistoryService* mhs); + + Profile* profile_; + // A mockup to use for testing. If NULL, use the real HistoryService + // from the profile_. See SetMockHistoryService. + MockHistoryService* mock_history_service_; + CancelableRequestConsumerTSimple<PageUsageData*> cancelable_consumer_; mutable Lock lock_; // The cached version of the top sites. The 0th item in this vector is the // #1 site. - std::vector<MostVisitedURL> top_sites_; + MostVisitedURLList top_sites_; // The images corresponding to the top_sites. This is indexed by the URL of // the top site, so this doesn't have to be shuffled around when the ordering @@ -127,4 +167,3 @@ class TopSites : public base::RefCountedThreadSafe<TopSites> { } // namespace history #endif // CHROME_BROWSER_HISTORY_TOP_SITES_H_ - diff --git a/chrome/browser/history/top_sites_unittest.cc b/chrome/browser/history/top_sites_unittest.cc index 55ff778..fe5ba7e 100644 --- a/chrome/browser/history/top_sites_unittest.cc +++ b/chrome/browser/history/top_sites_unittest.cc @@ -2,15 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/string_util.h" #include "chrome/browser/history/top_sites.h" +#include "chrome/test/testing_profile.h" +#include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" + namespace history { class TopSitesTest : public testing::Test { public: - TopSitesTest() : top_sites_(new TopSites) { + TopSitesTest() { } ~TopSitesTest() { } @@ -18,9 +22,13 @@ class TopSitesTest : public testing::Test { TopSites& top_sites() { return *top_sites_; } virtual void SetUp() { + profile_.reset(new TestingProfile); + top_sites_ = new TopSites(profile_.get()); } virtual void TearDown() { + profile_.reset(); + top_sites_ = NULL; } // Wrappers that allow private TopSites functions to be called from the @@ -46,10 +54,40 @@ class TopSitesTest : public testing::Test { private: scoped_refptr<TopSites> top_sites_; + scoped_ptr<TestingProfile> profile_; DISALLOW_COPY_AND_ASSIGN(TopSitesTest); }; +class MockHistoryServiceImpl: public TopSites::MockHistoryService { + // A mockup of a HistoryService used for testing TopSites. + public: + // Calls the callback directly with the results. + HistoryService::Handle QuerySegmentUsageSince( + CancelableRequestConsumerBase* consumer, + base::Time from_time, + int max_result_count, + HistoryService::SegmentQueryCallback* callback) { + callback->Run(CancelableRequestProvider::Handle(0), // Handle is unused. + &page_usage_data_); + return 0; + } + + // Add a page to the end of the pages list. + void AppendMockPage(const GURL& url, + const string16& title) { + PageUsageData* pd = new PageUsageData(URLID(0)); + pd->SetURL(url); + pd->SetTitle(title); + page_usage_data_.push_back(pd); + } + + private: + std::vector<PageUsageData*> page_usage_data_; +}; + + + // Helper function for appending a URL to a vector of "most visited" URLs, // using the default values for everything but the URL. static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list, @@ -185,4 +223,21 @@ TEST_F(TopSitesTest, SetPageThumbnail) { EXPECT_FALSE(top_sites().SetPageThumbnail(url1a, thumbnail, medium_score)); } +TEST_F(TopSitesTest, GetMostVisited) { + GURL news("http://news.google.com/"); + GURL google("http://google.com/"); + + MockHistoryServiceImpl hs; + hs.AppendMockPage(news, ASCIIToUTF16("Google News")); + hs.AppendMockPage(google, ASCIIToUTF16("Google")); + top_sites().SetMockHistoryService(&hs); + + top_sites().StartQueryForMostVisited(); + + MostVisitedURLList results = top_sites().GetMostVisitedURLs(); + EXPECT_EQ(2u, results.size()); + EXPECT_EQ(news, results[0].url); + EXPECT_EQ(google, results[1].url); +} + } // namespace history |