diff options
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_thumbnail_source.cc | 31 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_thumbnail_source.h | 9 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.cc | 384 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.h | 101 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store_unittest.cc | 92 |
5 files changed, 217 insertions, 400 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc index c3d51a1..fd40e867 100644 --- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc +++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc @@ -21,20 +21,15 @@ DOMUIThumbnailSource::DOMUIThumbnailSource(Profile* profile) store_(profile->GetThumbnailStore()) { } -DOMUIThumbnailSource::~DOMUIThumbnailSource() { - store_->CancelPendingRequests(pending_requests_); -} - void DOMUIThumbnailSource::StartDataRequest(const std::string& path, int request_id) { if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kThumbnailStore)) { RefCountedBytes* data = NULL; - ThumbnailStore::GetStatus res = store_->GetPageThumbnail(GURL(path), &data); - if (res == ThumbnailStore::SUCCESS) { + if (store_->GetPageThumbnail(GURL(path), &data)) { // Got the thumbnail. SendResponse(request_id, data); - } else if (res == ThumbnailStore::FAIL) { + } else { // Don't have the thumbnail so return the default thumbnail. if (!default_thumbnail_.get()) { default_thumbnail_ = new RefCountedBytes; @@ -42,12 +37,6 @@ void DOMUIThumbnailSource::StartDataRequest(const std::string& path, IDR_DEFAULT_THUMBNAIL, &default_thumbnail_->data); } SendResponse(request_id, default_thumbnail_); - } else if (res == ThumbnailStore::ASYNC) { - // Getting the redirect list for the url. Will return thumbnail later. - ThumbnailStore::ThumbnailDataCallback* cb = - NewCallback(this, &DOMUIThumbnailSource::ReturnData); - pending_requests_.insert(request_id); - store_->GetPageThumbnailAsync(GURL(path), request_id, cb); } return; } // end --thumbnail-store switch @@ -66,22 +55,6 @@ void DOMUIThumbnailSource::StartDataRequest(const std::string& path, } } -void DOMUIThumbnailSource::ReturnData(int request_id, - scoped_refptr<RefCountedBytes> data) { - pending_requests_.erase(request_id); - if (data.get() && !data->data.empty()) { - SendResponse(request_id, data); - } else { - if (!default_thumbnail_.get()) { - default_thumbnail_ = new RefCountedBytes; - ResourceBundle::GetSharedInstance().LoadImageResourceBytes( - IDR_DEFAULT_THUMBNAIL, &default_thumbnail_->data); - } - - SendResponse(request_id, default_thumbnail_); - } -} - void DOMUIThumbnailSource::OnThumbnailDataAvailable( HistoryService::Handle request_handle, scoped_refptr<RefCountedBytes> data) { diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h index b694466..2d475af 100644 --- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h +++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h @@ -21,17 +21,11 @@ class ThumbnailStore; class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource { public: explicit DOMUIThumbnailSource(Profile* profile); - virtual ~DOMUIThumbnailSource(); // Called when the network layer has requested a resource underneath // the path we registered. virtual void StartDataRequest(const std::string& path, int request_id); - // Used only when chromium is invoked with the --thumbnail-store switch. - // If StartDataRequest does not return thumbnail data synchronously, this - // method will be invoked when the thumbnail data becomes available. - virtual void ReturnData(int request_id, scoped_refptr<RefCountedBytes> data); - virtual std::string GetMimeType(const std::string&) const { // We need to explicitly return a mime type, otherwise if the user tries to // drag the image they get no extension. @@ -46,9 +40,6 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource { Profile* profile_; CancelableRequestConsumerT<int, 0> cancelable_consumer_; - // A set of outstanding request_id's. These are canceled on destruction. - std::set<int> pending_requests_; - // The ThumbnailStore from which thumbnails are requested. scoped_refptr<ThumbnailStore> store_; diff --git a/chrome/browser/thumbnail_store.cc b/chrome/browser/thumbnail_store.cc index 186fc81..d5679c9 100644 --- a/chrome/browser/thumbnail_store.cc +++ b/chrome/browser/thumbnail_store.cc @@ -16,7 +16,6 @@ #include "base/thread.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/history/page_usage_data.h" #include "chrome/browser/profile.h" #include "chrome/common/pref_service.h" #include "chrome/common/thumbnail_score.h" @@ -45,88 +44,8 @@ void ThumbnailStore::Init(const FilePath& file_path, Profile* profile) { file_path_, MessageLoop::current())); timer_.Start(base::TimeDelta::FromMinutes(30), this, - &ThumbnailStore::UpdateMostVisited); - UpdateMostVisited(); -} - -void ThumbnailStore::GetAllThumbnailsFromDisk(FilePath filepath, - MessageLoop* cb_loop) { - ThumbnailStore::Cache* cache = new ThumbnailStore::Cache; - - // Create the specified directory if it does not exist. - if (!file_util::DirectoryExists(filepath)) { - file_util::CreateDirectory(filepath); - } else { - // Walk the directory and read the thumbnail data from disk. - FilePath path; - GURL url; - RefCountedBytes* data; - ThumbnailScore score; - file_util::FileEnumerator fenum(filepath, false, - file_util::FileEnumerator::FILES); - - while (!(path = fenum.Next()).empty()) { - data = new RefCountedBytes; - if (GetPageThumbnailFromDisk(path, &url, data, &score)) - (*cache)[url] = std::make_pair(data, score); - else - delete data; - } - } - cb_loop->PostTask(FROM_HERE, - NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache)); -} - -bool ThumbnailStore::GetPageThumbnailFromDisk(const FilePath& file, - GURL* url, - RefCountedBytes* data, - ThumbnailScore* score) const { - int64 file_size; - if (!file_util::GetFileSize(file, &file_size)) - return false; - - // Read the file into a buffer. - std::vector<char> file_data; - file_data.resize(static_cast<unsigned int>(file_size)); - if (file_util::ReadFile(file, &file_data[0], - static_cast<int>(file_size)) == -1) - return false; - - // Unpack the url, ThumbnailScore and JPEG size from the buffer. - std::string url_string; - unsigned int jpeg_len; - void* iter = NULL; - Pickle packed(&file_data[0], static_cast<int>(file_size)); - - if (!packed.ReadString(&iter, &url_string) || - !UnpackScore(score, packed, iter) || - !packed.ReadUInt32(&iter, &jpeg_len)) - return false; - - // Store the url to the out parameter. - GURL temp_url(url_string); - url->Swap(&temp_url); - - // Unpack the JPEG data from the buffer. - const char* jpeg_data = NULL; - int out_len; - - if (!packed.ReadData(&iter, &jpeg_data, &out_len) || - out_len != static_cast<int>(jpeg_len)) - return false; - - // Copy jpeg data to the out parameter. - data->data.resize(jpeg_len); - memcpy(&data->data[0], jpeg_data, jpeg_len); - - return true; -} - -void ThumbnailStore::OnDiskDataAvailable(ThumbnailStore::Cache* cache) { - if (cache) { - cache_.reset(cache); - cache_initialized_ = true; - } + &ThumbnailStore::UpdateURLData); + UpdateURLData(); } bool ThumbnailStore::SetPageThumbnail(const GURL& url, @@ -171,41 +90,17 @@ bool ThumbnailStore::SetPageThumbnail(const GURL& url, return true; } -bool ThumbnailStore::WriteThumbnailToDisk(const GURL& url, - scoped_refptr<RefCountedBytes> data, - const ThumbnailScore& score) const { - Pickle packed; - FilePath file = file_path_.AppendASCII(MD5String(url.spec())); - - // Pack the url, ThumbnailScore, and the JPEG data. - packed.WriteString(url.spec()); - PackScore(score, &packed); - packed.WriteUInt32(data->data.size()); - packed.WriteData(reinterpret_cast<char*>(&data->data[0]), data->data.size()); - - // Write the packed data to a file. - file_util::Delete(file, false); - return file_util::WriteFile(file, - reinterpret_cast<const char*>(packed.data()), - packed.size()) != -1; -} - -ThumbnailStore::GetStatus ThumbnailStore::GetPageThumbnail( +bool ThumbnailStore::GetPageThumbnail( const GURL& url, RefCountedBytes** data) { if (!cache_initialized_ || IsURLBlacklisted(url)) - return ThumbnailStore::FAIL; - - // We need to check if the URL was redirected so that we can return the - // thumbnail for the final destination. Redirect information needs to be - // fetched asynchronously from the HistoryService and is stored in a map - // of the form "url => {redirect1 -> redirect2 -> .... -> final url}". - // If the redirect info has not been cached, tell the caller to call - // GetPageThumbnailAsync instead which will wait for the redirect info - // and return the thumbnail data when it becomes available. - ThumbnailStore::RedirectMap::iterator it = redirect_urls_.find(url); - if (it == redirect_urls_.end()) - return ThumbnailStore::ASYNC; + return false; + + // Look up the |url| in the redirect list to find the final destination + // which is the key into the |cache_|. + history::RedirectMap::iterator it = redirect_urls_->find(url); + if (it == redirect_urls_->end()) + return false; // Return the first available thumbnail starting at the end of the // redirect list. @@ -215,119 +110,33 @@ ThumbnailStore::GetStatus ThumbnailStore::GetPageThumbnail( if (cache_->find(*rit) != cache_->end()) { *data = (*cache_)[*rit].first; (*data)->AddRef(); - return ThumbnailStore::SUCCESS; + return true; } } // TODO(meelapshah) bug 14643: check past redirect lists if (cache_->find(url) == cache_->end()) - return ThumbnailStore::FAIL; + return false; *data = (*cache_)[url].first; (*data)->AddRef(); - return ThumbnailStore::SUCCESS; -} - -void ThumbnailStore::GetPageThumbnailAsync(const GURL& url, - int request_id, - ThumbnailStore::ThumbnailDataCallback* cb) { - DCHECK(redirect_requests_.find(request_id) == redirect_requests_.end()); - - HistoryService::Handle handle = hs_->QueryRedirectsFrom( - url, &hs_consumer_, - NewCallback(this, &ThumbnailStore::OnRedirectQueryComplete)); - hs_consumer_.SetClientData(hs_, handle, request_id); - redirect_requests_[request_id] = std::make_pair(cb, handle); -} - -void ThumbnailStore::OnRedirectQueryComplete( - HistoryService::Handle request_handle, - GURL url, - bool success, - history::RedirectList* redirects) { - if (!success) - return; - - // Copy the redirects list returned by the HistoryService into our cache. - redirect_urls_[url] = new RefCountedVector<GURL>(*redirects); - - // Get the request_id associated with this request. - int request_id = hs_consumer_.GetClientData(hs_, request_handle); - - // Return if no callback was associated with this redirect query. - // (The request for redirect info was made from UpdateMostVisited().) - if (request_id == -1) - return; - - // Run the callback if a thumbnail was requested for the URL. - ThumbnailStore::RequestMap::iterator it = - redirect_requests_.find(request_id); - if (it != redirect_requests_.end()) { - ThumbnailStore::ThumbnailDataCallback* cb = it->second.first; - RefCountedBytes* data = NULL; - - redirect_requests_.erase(it); - GetPageThumbnail(url, &data); - cb->Run(request_id, data); - } + return true; } -void ThumbnailStore::CancelPendingRequests( - const std::set<int>& pending_requests) { - ThumbnailStore::RequestMap::iterator req_it; - for (std::set<int>::const_iterator it = pending_requests.begin(); - it != pending_requests.end(); ++it) { - req_it = redirect_requests_.find(*it); - - // Cancel the request and delete the callback. - DCHECK(req_it != redirect_requests_.end()); - hs_->CancelRequest(req_it->second.second); - delete req_it->second.first; - redirect_requests_.erase(req_it); - } +void ThumbnailStore::UpdateURLData() { + int result_count = ThumbnailStore::kMaxCacheSize + url_blacklist_->GetSize(); + hs_->QueryTopURLsAndRedirects(result_count, &consumer_, + NewCallback(this, &ThumbnailStore::OnURLDataAvailable)); } -void ThumbnailStore::UpdateMostVisited() { - int result_count = ThumbnailStore::kMaxCacheSize; - if (url_blacklist_) - result_count += url_blacklist_->GetSize(); - - hs_->QuerySegmentUsageSince( - &cancelable_consumer_, - base::Time::Now() - - base::TimeDelta::FromDays(ThumbnailStore::kMostVisitedScope), - result_count, - NewCallback(this, &ThumbnailStore::OnMostVisitedURLsAvailable)); -} - -void ThumbnailStore::OnMostVisitedURLsAvailable( - CancelableRequestProvider::Handle handle, - std::vector<PageUsageData*>* data) { - most_visited_urls_.clear(); - - // Extract the top kMaxCacheSize + |url_blacklist_| most visited URLs. - GURL url; - size_t data_index = 0; - size_t output_index = 0; - - while (output_index < ThumbnailStore::kMaxCacheSize && - data_index < data->size()) { - url = (*data)[data_index]->GetURL(); - ++data_index; +void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls, + history::RedirectMap* redirects) { + DCHECK(urls); + DCHECK(redirects); - if (!IsURLBlacklisted(url)) { - most_visited_urls_.push_back(url); - ++output_index; - } - - // Preemptively fetch the redirect lists for the current URL if we don't - // already have it cached. - if (redirect_urls_.find(url) == redirect_urls_.end()) { - hs_->QueryRedirectsFrom(url, &hs_consumer_, - NewCallback(this, &ThumbnailStore::OnRedirectQueryComplete)); - } - } + most_visited_urls_.reset(new std::vector<GURL>(*urls)); + redirect_urls_.reset(new history::RedirectMap(*redirects)); CleanCacheData(); } @@ -338,12 +147,12 @@ void ThumbnailStore::CleanCacheData() { // For each URL in the cache, search the RedirectMap for the originating URL. // If this URL is blacklisted or not in the most visited list, delete the // thumbnail data for it from the cache and from disk in the background. - scoped_refptr<RefCountedVector<GURL> > delete_me = new RefCountedVector<GURL>; + scoped_refptr<RefCountedVector<GURL> > old_urls = new RefCountedVector<GURL>; for (ThumbnailStore::Cache::iterator cache_it = cache_->begin(); cache_it != cache_->end();) { const GURL* url = NULL; - for (ThumbnailStore::RedirectMap::iterator it = redirect_urls_.begin(); - it != redirect_urls_.end(); ++it) { + for (history::RedirectMap::iterator it = redirect_urls_->begin(); + it != redirect_urls_->end(); ++it) { if (cache_it->first == it->first || (it->second->data.size() && cache_it->first == it->second->data.back())) { @@ -352,38 +161,124 @@ void ThumbnailStore::CleanCacheData() { } } - // If there was no entry in the RedirectMap for the URL cache_it->first, - // that means SetPageThumbnail was called but GetPageThumbnail was not - // called. Since we do not have a reverse redirect lookup (i.e. we have - // a final destination such as http://www.google.com/ but we cannot get - // what the user typed such as google.com from it), we cannot - // check if this cache entry is blacklisted or if it is popular. - // TODO(meelapshah) bug 14644: Fix this. - if (url == NULL) { - cache_it++; - continue; - } - - if (IsURLBlacklisted(*url) || !IsPopular(*url)) { - delete_me->data.push_back(cache_it->first); + if (url == NULL || IsURLBlacklisted(*url) || !IsPopular(*url)) { + old_urls->data.push_back(cache_it->first); cache_->erase(cache_it++); } else { cache_it++; } } - if (delete_me->data.size()) { + if (old_urls->data.size()) { g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &ThumbnailStore::DeleteThumbnails, delete_me)); + NewRunnableMethod(this, &ThumbnailStore::DeleteThumbnails, old_urls)); } } -bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const { - if (IsURLBlacklisted(url) || cache_->size() >= ThumbnailStore::kMaxCacheSize) +void ThumbnailStore::DeleteThumbnails( + scoped_refptr<RefCountedVector<GURL> > thumbnail_urls) const { + for (std::vector<GURL>::iterator it = thumbnail_urls->data.begin(); + it != thumbnail_urls->data.end(); ++it) + file_util::Delete(file_path_.AppendASCII(MD5String(it->spec())), false); +} + +void ThumbnailStore::GetAllThumbnailsFromDisk(FilePath filepath, + MessageLoop* cb_loop) { + ThumbnailStore::Cache* cache = new ThumbnailStore::Cache; + + // Create the specified directory if it does not exist. + if (!file_util::DirectoryExists(filepath)) { + file_util::CreateDirectory(filepath); + } else { + // Walk the directory and read the thumbnail data from disk. + FilePath path; + GURL url; + RefCountedBytes* data; + ThumbnailScore score; + file_util::FileEnumerator fenum(filepath, false, + file_util::FileEnumerator::FILES); + + while (!(path = fenum.Next()).empty()) { + data = new RefCountedBytes; + if (GetPageThumbnailFromDisk(path, &url, data, &score)) + (*cache)[url] = std::make_pair(data, score); + else + delete data; + } + } + cb_loop->PostTask(FROM_HERE, + NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache)); +} + +bool ThumbnailStore::GetPageThumbnailFromDisk(const FilePath& file, + GURL* url, + RefCountedBytes* data, + ThumbnailScore* score) const { + int64 file_size; + if (!file_util::GetFileSize(file, &file_size)) return false; - return most_visited_urls_.size() < ThumbnailStore::kMaxCacheSize || - IsPopular(url); + // Read the file into a buffer. + std::vector<char> file_data; + file_data.resize(static_cast<unsigned int>(file_size)); + if (file_util::ReadFile(file, &file_data[0], + static_cast<int>(file_size)) == -1) + return false; + + // Unpack the url, ThumbnailScore and JPEG size from the buffer. + std::string url_string; + unsigned int jpeg_len; + void* iter = NULL; + Pickle packed(&file_data[0], static_cast<int>(file_size)); + + if (!packed.ReadString(&iter, &url_string) || + !UnpackScore(score, packed, iter) || + !packed.ReadUInt32(&iter, &jpeg_len)) + return false; + + // Store the url to the out parameter. + GURL temp_url(url_string); + url->Swap(&temp_url); + + // Unpack the JPEG data from the buffer. + const char* jpeg_data = NULL; + int out_len; + + if (!packed.ReadData(&iter, &jpeg_data, &out_len) || + out_len != static_cast<int>(jpeg_len)) + return false; + + // Copy jpeg data to the out parameter. + data->data.resize(jpeg_len); + memcpy(&data->data[0], jpeg_data, jpeg_len); + + return true; +} + +void ThumbnailStore::OnDiskDataAvailable(ThumbnailStore::Cache* cache) { + if (cache) { + cache_.reset(cache); + cache_initialized_ = true; + } +} + +bool ThumbnailStore::WriteThumbnailToDisk(const GURL& url, + scoped_refptr<RefCountedBytes> data, + const ThumbnailScore& score) const { + Pickle packed; + FilePath file = file_path_.AppendASCII(MD5String(url.spec())); + + // Pack the url, ThumbnailScore, and the JPEG data. + packed.WriteString(url.spec()); + PackScore(score, &packed); + packed.WriteUInt32(data->data.size()); + packed.WriteData(reinterpret_cast<char*>(&data->data[0]), data->data.size()); + + // Write the packed data to a file. + file_util::Delete(file, false); + return file_util::WriteFile(file, + reinterpret_cast<const char*>(packed.data()), + packed.size()) != -1; } void ThumbnailStore::PackScore(const ThumbnailScore& score, @@ -417,11 +312,12 @@ bool ThumbnailStore::UnpackScore(ThumbnailScore* score, const Pickle& packed, return true; } -void ThumbnailStore::DeleteThumbnails( - scoped_refptr<RefCountedVector<GURL> > thumbnail_urls) const { - for (std::vector<GURL>::iterator it = thumbnail_urls->data.begin(); - it != thumbnail_urls->data.end(); ++it) - file_util::Delete(file_path_.AppendASCII(MD5String(it->spec())), false); +bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const { + if (IsURLBlacklisted(url) || cache_->size() >= ThumbnailStore::kMaxCacheSize) + return false; + + return most_visited_urls_->size() < ThumbnailStore::kMaxCacheSize || + IsPopular(url); } bool ThumbnailStore::IsURLBlacklisted(const GURL& url) const { @@ -436,7 +332,7 @@ std::wstring ThumbnailStore::GetDictionaryKeyForURL( } bool ThumbnailStore::IsPopular(const GURL& url) const { - return most_visited_urls_.end() != find(most_visited_urls_.begin(), - most_visited_urls_.end(), + return most_visited_urls_->end() != find(most_visited_urls_->begin(), + most_visited_urls_->end(), url); } diff --git a/chrome/browser/thumbnail_store.h b/chrome/browser/thumbnail_store.h index 6369224..cf29e43 100644 --- a/chrome/browser/thumbnail_store.h +++ b/chrome/browser/thumbnail_store.h @@ -6,7 +6,6 @@ #define CHROME_BROWSER_THUMBNAIL_STORE_H_ #include <map> -#include <set> #include <string> #include <vector> @@ -23,7 +22,6 @@ class DictionaryValue; class GURL; class HistoryService; -class PageUsageData; class Pickle; class Profile; class SkBitmap; @@ -36,9 +34,6 @@ class Time; // by the new_tab_ui. class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { public: - typedef Callback2<int, scoped_refptr<RefCountedBytes> >::Type - ThumbnailDataCallback; - ThumbnailStore(); ~ThumbnailStore(); @@ -56,49 +51,45 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { bool write_to_disk); // Sets *data to point to the thumbnail for the given url. - // A return value of ASYNC means you should call GetPageThumbnailAsync. - // On a return value of SUCCESS, the refcount of the out parameter data - // is incremented for the caller who takes ownership of that reference. - enum GetStatus { SUCCESS, FAIL, ASYNC }; - ThumbnailStore::GetStatus GetPageThumbnail(const GURL& url, - RefCountedBytes** data); - - // Retrieves the redirects list for the given url asynchronously. - // Calls the callback with the request_id and thumbnail data if found. - void GetPageThumbnailAsync(const GURL& url, - int request_id, - ThumbnailStore::ThumbnailDataCallback* cb); - - // Cancels the given set of request_id's which were issued from - // GetPageThumbnailAsync. - // This method is called from ~DOMUIThumbnailSource. If a - // DOMUIThumbnailSource requests a thumbnail but is destroyed before the - // data is sent back, this method will cancel the request and delete the - // callback. - void CancelPendingRequests(const std::set<int>& pending_requests); + // Returns false if no thumbnail available. + bool GetPageThumbnail(const GURL& url, RefCountedBytes** data); private: FRIEND_TEST(ThumbnailStoreTest, RetrieveFromCache); FRIEND_TEST(ThumbnailStoreTest, RetrieveFromDisk); FRIEND_TEST(ThumbnailStoreTest, UpdateThumbnail); FRIEND_TEST(ThumbnailStoreTest, FollowRedirects); + friend class ThumbnailStoreTest; // Data structure used to store thumbnail data in memory. typedef std::map<GURL, std::pair<scoped_refptr<RefCountedBytes>, ThumbnailScore> > Cache; - // Data structure used to cache the redirect lists for urls. - typedef std::map<GURL, scoped_refptr<RefCountedVector<GURL> > > RedirectMap; + // Most visited URLs and their redirect lists ------------------------------- + + // Query the HistoryService for the most visited URLs and the most recent + // redirect lists for those URLs. This happens in the background and the + // callback is OnURLDataAvailable. + void UpdateURLData(); + + // The callback for UpdateURLData. The ThumbnailStore takes ownership of + // the most visited urls list and redirect lists passed in. + void OnURLDataAvailable(std::vector<GURL>* urls, + history::RedirectMap* redirects); - // Data structure used to store request_id's and callbacks for - // GetPageThumbnailAsync. - typedef std::map<int, std::pair<ThumbnailStore::ThumbnailDataCallback*, - HistoryService::Handle> > RequestMap; + // Remove stale data -------------------------------------------------------- + + // Remove entries from the in memory thumbnail cache and redirect lists + // cache that have been blacklisted or are not in the top kMaxCacheSize + // visited sites. + void CleanCacheData(); // Deletes thumbnail data from disk for the given list of urls. void DeleteThumbnails( scoped_refptr<RefCountedVector<GURL> > thumbnail_urls) const; + // Disk operations ---------------------------------------------------------- + // Read all thumbnail data from the specified FilePath into a Cache object. // Done on the file_thread and returns to OnDiskDataAvailable on the thread // owning the specified MessageLoop. @@ -114,13 +105,14 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { // Once thumbnail data from the disk is available from the file_thread, // this function is invoked on the main thread. It takes ownership of the // Cache* passed in and retains this Cache* for the lifetime of the object. - void OnDiskDataAvailable(ThumbnailStore::Cache* cache); + void OnDiskDataAvailable(Cache* cache); // Write thumbnail data to disk for a given url. bool WriteThumbnailToDisk(const GURL& url, scoped_refptr<RefCountedBytes> data, const ThumbnailScore& score) const; + // Pack the given ThumbnailScore into the given Pickle. void PackScore(const ThumbnailScore& score, Pickle* packed) const; @@ -130,6 +122,8 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { const Pickle& packed, void*& iter) const; + // Decide whether to store data --------------------------------------------- + bool ShouldStoreThumbnailForURL(const GURL& url) const; bool IsURLBlacklisted(const GURL& url) const; @@ -139,39 +133,24 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { // Returns true if url is in most_visited_urls_. bool IsPopular(const GURL& url) const; - // The callback for GetPageThumbnailAsync. Caches the redirect list - // and calls the callback for the request asssociated with the url. - void OnRedirectQueryComplete(HistoryService::Handle request_handle, - GURL url, - bool success, - history::RedirectList* redirects); - // Called on a timer initiated in Init(). Calls the HistoryService to - // update the list of most visited URLs. The callback is - // OnMostVisitedURLsAvailable. - void UpdateMostVisited(); - // Updates the list of most visited URLs. Then calls CleanCacheData. - void OnMostVisitedURLsAvailable(CancelableRequestProvider::Handle handle, - std::vector<PageUsageData*>* data); - - // Remove entries from the in memory thumbnail cache and redirect lists - // cache that have been blacklisted or are not in the top kMaxCacheSize - // visited sites. - void CleanCacheData(); + // Member variables --------------------------------------------------------- // The Cache maintained by the object. - scoped_ptr<ThumbnailStore::Cache> cache_; + scoped_ptr<Cache> cache_; bool cache_initialized_; // The location of the thumbnail store. FilePath file_path_; + // We hold a reference to the history service to query for most visited URLs + // and redirect information. scoped_refptr<HistoryService> hs_; // A list of the most_visited_urls_ refreshed every 30mins from the // HistoryService. - std::vector<GURL> most_visited_urls_; + scoped_ptr<std::vector<GURL> > most_visited_urls_; // A pointer to the persistent URL blacklist for this profile. const DictionaryValue* url_blacklist_; @@ -179,24 +158,14 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> { // A map pairing the URL that a user typed to a list of URLs it was // redirected to. Ex: // google.com => { http://www.google.com/ } - ThumbnailStore::RedirectMap redirect_urls_; + scoped_ptr<history::RedirectMap> redirect_urls_; - // When GetPageThumbnailAsync is called, this map records the request_id - // and callback associated with the request. When the thumbnail becomes - // available, the callback is taken from this map and the thumbnail data - // is returned to it. - ThumbnailStore::RequestMap redirect_requests_; - - // Timer on which UpdateMostVisited runs. + // Timer on which UpdateURLData runs. base::RepeatingTimer<ThumbnailStore> timer_; - // Consumer for getting redirect lists from the history service. - CancelableRequestConsumerT<int, -1> hs_consumer_; - - // Consumer for getting the list of most visited urls. - CancelableRequestConsumerTSimple<PageUsageData*> cancelable_consumer_; + // Consumer for queries to the HistoryService. + CancelableRequestConsumer consumer_; - static const int kMostVisitedScope = 90; static const unsigned int kMaxCacheSize = 45; DISALLOW_COPY_AND_ASSIGN(ThumbnailStore); diff --git a/chrome/browser/thumbnail_store_unittest.cc b/chrome/browser/thumbnail_store_unittest.cc index d9ce619..72a5013 100644 --- a/chrome/browser/thumbnail_store_unittest.cc +++ b/chrome/browser/thumbnail_store_unittest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include <string.h> -#include <algorithm> #include <iostream> #include <vector> @@ -51,6 +50,7 @@ class ThumbnailStoreTest : public testing::Test { // The directory where ThumbnailStore will store data. FilePath file_path_; + scoped_refptr<ThumbnailStore> store_; scoped_ptr<SkBitmap> google_; scoped_ptr<SkBitmap> weewar_; scoped_refptr<RefCountedBytes> jpeg_google_; @@ -88,6 +88,14 @@ void ThumbnailStoreTest::SetUp() { weewar_->height(), static_cast<int>(weewar_->rowBytes()), 90, &(jpeg_weewar_->data)); + + store_ = new ThumbnailStore; + store_->cache_initialized_ = true; + store_->file_path_ = file_path_; + store_->most_visited_urls_.reset(new std::vector<GURL>); + store_->most_visited_urls_->push_back(url1_); + store_->cache_.reset(new ThumbnailStore::Cache); + store_->redirect_urls_.reset(new history::RedirectMap); } void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) { @@ -129,27 +137,23 @@ void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) { } TEST_F(ThumbnailStoreTest, UpdateThumbnail) { - scoped_refptr<ThumbnailStore> store = new ThumbnailStore; RefCountedBytes* read_image = NULL; ThumbnailScore score2(0.1, true, true); + store_->cache_->clear(); + store_->redirect_urls_->clear(); - store->file_path_ = file_path_; - store->cache_.reset(new ThumbnailStore::Cache); - store->cache_initialized_ = true; - - // Store google_ with a low score, then weewar_ with a higher score + // store_ google_ with a low score, then weewar_ with a higher score // and check that weewar_ overwrote google_. - EXPECT_TRUE(store->SetPageThumbnail(url1_, *google_, score1_, false)); - EXPECT_TRUE(store->SetPageThumbnail(url1_, *weewar_, score2, false)); + EXPECT_TRUE(store_->SetPageThumbnail(url1_, *google_, score1_, false)); + EXPECT_TRUE(store_->SetPageThumbnail(url1_, *weewar_, score2, false)); // Set fake redirects list. scoped_ptr<std::vector<GURL> > redirects(new std::vector<GURL>); redirects->push_back(url1_); - store->redirect_urls_[url1_] = new RefCountedVector<GURL>(*redirects); + (*store_->redirect_urls_)[url1_] = new RefCountedVector<GURL>(*redirects); - EXPECT_EQ(store->GetPageThumbnail(url1_, &read_image), - ThumbnailStore::SUCCESS); + EXPECT_TRUE(store_->GetPageThumbnail(url1_, &read_image)); EXPECT_EQ(read_image->data.size(), jpeg_weewar_->data.size()); EXPECT_EQ(0, memcmp(&read_image->data[0], &jpeg_weewar_->data[0], jpeg_weewar_->data.size())); @@ -159,29 +163,24 @@ TEST_F(ThumbnailStoreTest, UpdateThumbnail) { TEST_F(ThumbnailStoreTest, RetrieveFromCache) { RefCountedBytes* read_image = NULL; - scoped_refptr<ThumbnailStore> store = new ThumbnailStore; - - store->file_path_ = file_path_; - store->cache_.reset(new ThumbnailStore::Cache); - store->cache_initialized_ = true; + store_->cache_->clear(); + store_->redirect_urls_->clear(); // Retrieve a thumbnail/score for a page not in the cache. - EXPECT_EQ(store->GetPageThumbnail(url2_, &read_image), - ThumbnailStore::ASYNC); + EXPECT_FALSE(store_->GetPageThumbnail(url2_, &read_image)); - // Store a thumbnail into the cache and retrieve it. + // store_ a thumbnail into the cache and retrieve it. - EXPECT_TRUE(store->SetPageThumbnail(url1_, *google_, score1_, false)); + EXPECT_TRUE(store_->SetPageThumbnail(url1_, *google_, score1_, false)); // Set fake redirects list. scoped_ptr<std::vector<GURL> > redirects(new std::vector<GURL>); redirects->push_back(url1_); - store->redirect_urls_[url1_] = new RefCountedVector<GURL>(*redirects); + (*store_->redirect_urls_)[url1_] = new RefCountedVector<GURL>(*redirects); - EXPECT_EQ(store->GetPageThumbnail(url1_, &read_image), - ThumbnailStore::SUCCESS); - EXPECT_TRUE(score1_.Equals((*store->cache_)[url1_].second)); + EXPECT_TRUE(store_->GetPageThumbnail(url1_, &read_image)); + EXPECT_TRUE(score1_.Equals((*store_->cache_)[url1_].second)); EXPECT_TRUE(read_image->data.size() == jpeg_google_->data.size()); EXPECT_EQ(0, memcmp(&read_image->data[0], &jpeg_google_->data[0], jpeg_google_->data.size())); @@ -191,23 +190,15 @@ TEST_F(ThumbnailStoreTest, RetrieveFromCache) { TEST_F(ThumbnailStoreTest, RetrieveFromDisk) { scoped_refptr<RefCountedBytes> read_image = new RefCountedBytes; - scoped_refptr<ThumbnailStore> store = new ThumbnailStore; ThumbnailScore score2; + store_->cache_->clear(); + store_->redirect_urls_->clear(); - store->file_path_ = file_path_; - store->cache_.reset(new ThumbnailStore::Cache); - store->cache_initialized_ = true; - - // Store a thumbnail onto the disk and retrieve it. + // store_ a thumbnail onto the disk and retrieve it. - EXPECT_TRUE(store->SetPageThumbnail(url1_, *google_, score1_, false)); - - ThumbnailStore::Cache::iterator it = store->cache_->find(url1_); - DCHECK(it != store->cache_->end()); - - EXPECT_TRUE(store->WriteThumbnailToDisk(url1_, it->second.first, - it->second.second)); - EXPECT_TRUE(store->GetPageThumbnailFromDisk(file_path_.AppendASCII( + EXPECT_TRUE(store_->SetPageThumbnail(url1_, *google_, score1_, false)); + EXPECT_TRUE(store_->WriteThumbnailToDisk(url1_, jpeg_google_, score1_)); + EXPECT_TRUE(store_->GetPageThumbnailFromDisk(file_path_.AppendASCII( MD5String(url1_.spec())), &url2_, read_image, &score2)); EXPECT_TRUE(url1_ == url2_); EXPECT_TRUE(score1_.Equals(score2)); @@ -219,29 +210,26 @@ TEST_F(ThumbnailStoreTest, RetrieveFromDisk) { TEST_F(ThumbnailStoreTest, FollowRedirects) { RefCountedBytes* read_image = NULL; scoped_ptr<std::vector<GURL> > redirects(new std::vector<GURL>); - scoped_refptr<ThumbnailStore> store = new ThumbnailStore; - - store->file_path_ = file_path_; - store->cache_.reset(new ThumbnailStore::Cache); - store->cache_initialized_ = true; + store_->cache_->clear(); + store_->redirect_urls_->clear(); GURL my_url("google"); redirects->push_back(GURL("google.com")); redirects->push_back(GURL("www.google.com")); redirects->push_back(url1_); // url1_ = http://www.google.com/ - store->redirect_urls_[my_url] = new RefCountedVector<GURL>(*redirects); - EXPECT_TRUE(store->SetPageThumbnail(url1_, *google_, score1_, false)); - EXPECT_EQ(store->GetPageThumbnail(my_url, &read_image), - ThumbnailStore::SUCCESS); + store_->most_visited_urls_->push_back(my_url); + + (*store_->redirect_urls_)[my_url] = new RefCountedVector<GURL>(*redirects); + EXPECT_TRUE(store_->SetPageThumbnail(url1_, *google_, score1_, false)); + EXPECT_TRUE(store_->GetPageThumbnail(my_url, &read_image)); read_image->Release(); - store->cache_->erase(store->cache_->find(url1_)); + store_->cache_->erase(store_->cache_->find(url1_)); - EXPECT_TRUE(store->SetPageThumbnail(GURL("google.com"), *google_, score1_, + EXPECT_TRUE(store_->SetPageThumbnail(GURL("google.com"), *google_, score1_, false)); - EXPECT_EQ(store->GetPageThumbnail(my_url, &read_image), - ThumbnailStore::SUCCESS); + EXPECT_TRUE(store_->GetPageThumbnail(my_url, &read_image)); read_image->Release(); } |