| Index: chrome/browser/thumbnail_store.cc
|
| ===================================================================
|
| --- chrome/browser/thumbnail_store.cc (revision 19766)
|
| +++ chrome/browser/thumbnail_store.cc (working copy)
|
| @@ -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,90 +44,10 @@
|
| file_path_, MessageLoop::current()));
|
|
|
| timer_.Start(base::TimeDelta::FromMinutes(30), this,
|
| - &ThumbnailStore::UpdateMostVisited);
|
| - UpdateMostVisited();
|
| + &ThumbnailStore::UpdateURLData);
|
| + UpdateURLData();
|
| }
|
|
|
| -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;
|
| - }
|
| -}
|
| -
|
| bool ThumbnailStore::SetPageThumbnail(const GURL& url,
|
| const SkBitmap& thumbnail,
|
| const ThumbnailScore& score,
|
| @@ -171,41 +90,17 @@
|
| 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;
|
| + return false;
|
|
|
| - // 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;
|
| + // 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 @@
|
| 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;
|
| + return true;
|
| }
|
|
|
| -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::UpdateURLData() {
|
| + int result_count = ThumbnailStore::kMaxCacheSize + url_blacklist_->GetSize();
|
| + hs_->QueryTopURLsAndRedirects(result_count, &consumer_,
|
| + NewCallback(this, &ThumbnailStore::OnURLDataAvailable));
|
| }
|
|
|
| -void ThumbnailStore::OnRedirectQueryComplete(
|
| - HistoryService::Handle request_handle,
|
| - GURL url,
|
| - bool success,
|
| - history::RedirectList* redirects) {
|
| - if (!success)
|
| - return;
|
| +void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls,
|
| + history::RedirectMap* redirects) {
|
| + DCHECK(urls);
|
| + DCHECK(redirects);
|
|
|
| - // 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);
|
| - }
|
| -}
|
| -
|
| -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::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;
|
| -
|
| - 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 @@
|
| // 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,40 +161,126 @@
|
| }
|
| }
|
|
|
| - // 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,
|
| Pickle* packed) const {
|
| // Pack the contents of the given ThumbnailScore into the given Pickle.
|
| @@ -417,11 +312,12 @@
|
| 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 @@
|
| }
|
|
|
| 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);
|
| }
|
|
|