summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.cc31
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.h9
-rw-r--r--chrome/browser/thumbnail_store.cc384
-rw-r--r--chrome/browser/thumbnail_store.h101
-rw-r--r--chrome/browser/thumbnail_store_unittest.cc92
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();
}