summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormeelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-08 00:08:31 +0000
committermeelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-08 00:08:31 +0000
commit3254563421b09469b9668ff69562d098a8661d23 (patch)
treeb9222dcaebe54cc87dcf47f952f58d124ae9b4ab /chrome/browser
parentcb1da54001174e027d1bd5de4dbc5a91dca140e2 (diff)
downloadchromium_src-3254563421b09469b9668ff69562d098a8661d23.zip
chromium_src-3254563421b09469b9668ff69562d098a8661d23.tar.gz
chromium_src-3254563421b09469b9668ff69562d098a8661d23.tar.bz2
Reverting 20097.
Review URL: http://codereview.chromium.org/155186 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20101 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/profile.cc2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc4
-rw-r--r--chrome/browser/thumbnail_store.cc288
-rw-r--r--chrome/browser/thumbnail_store.h78
-rw-r--r--chrome/browser/thumbnail_store_unittest.cc124
5 files changed, 273 insertions, 223 deletions
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 085f814..6e0a5a4 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -1016,7 +1016,7 @@ TabRestoreService* ProfileImpl::GetTabRestoreService() {
ThumbnailStore* ProfileImpl::GetThumbnailStore() {
if (!thumbnail_store_.get()) {
thumbnail_store_ = new ThumbnailStore;
- thumbnail_store_->Init(GetPath().AppendASCII("Top Thumbnails"), this);
+ thumbnail_store_->Init(GetPath().AppendASCII("thumbnailstore"), this);
}
return thumbnail_store_.get();
}
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 04e4a26e..d239955 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -1650,8 +1650,8 @@ void TabContents::UpdateThumbnail(const GURL& url,
const ThumbnailScore& score) {
// Tell History about this thumbnail
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kThumbnailStore)) {
- if (!profile()->IsOffTheRecord())
- profile()->GetThumbnailStore()->SetPageThumbnail(url, bitmap, score);
+ profile()->GetThumbnailStore()->
+ SetPageThumbnail(url, bitmap, score, !profile()->IsOffTheRecord());
} else {
HistoryService* hs;
if (!profile()->IsOffTheRecord() &&
diff --git a/chrome/browser/thumbnail_store.cc b/chrome/browser/thumbnail_store.cc
index 4579665..d5679c9 100644
--- a/chrome/browser/thumbnail_store.cc
+++ b/chrome/browser/thumbnail_store.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include "base/basictypes.h"
+#include "base/pickle.h"
#include "base/file_util.h"
#include "base/gfx/jpeg_codec.h"
#include "base/md5.h"
@@ -17,57 +18,51 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_service.h"
-#include "chrome/common/sqlite_utils.h"
+#include "chrome/common/thumbnail_score.h"
#include "googleurl/src/gurl.h"
#include "third_party/skia/include/core/SkBitmap.h"
ThumbnailStore::ThumbnailStore()
: cache_(NULL),
- db_(NULL),
+ cache_initialized_(false),
hs_(NULL),
url_blacklist_(NULL) {
}
ThumbnailStore::~ThumbnailStore() {
- CommitCacheToDB(NULL);
}
-void ThumbnailStore::Init(const FilePath& db_name,
- Profile* profile) {
- // Load thumbnails already in the database.
- g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &ThumbnailStore::InitializeFromDB,
- db_name, MessageLoop::current()));
-
- // Take ownership of a reference to the HistoryService.
+void ThumbnailStore::Init(const FilePath& file_path, Profile* profile) {
+ file_path_ = file_path;
hs_ = profile->GetHistoryService(Profile::EXPLICIT_ACCESS);
-
- // Store a pointer to a persistent table of blacklisted URLs.
url_blacklist_ = profile->GetPrefs()->
GetMutableDictionary(prefs::kNTPMostVisitedURLsBlacklist);
- // Get the list of most visited URLs and redirect information from the
- // HistoryService.
+ g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ThumbnailStore::GetAllThumbnailsFromDisk,
+ file_path_, MessageLoop::current()));
+
timer_.Start(base::TimeDelta::FromMinutes(30), this,
- &ThumbnailStore::UpdateURLData);
+ &ThumbnailStore::UpdateURLData);
UpdateURLData();
}
bool ThumbnailStore::SetPageThumbnail(const GURL& url,
const SkBitmap& thumbnail,
- const ThumbnailScore& score) {
- if (!cache_.get())
+ const ThumbnailScore& score,
+ bool write_to_disk) {
+ if (!cache_initialized_)
return false;
if (!ShouldStoreThumbnailForURL(url) ||
(cache_->find(url) != cache_->end() &&
- !ShouldReplaceThumbnailWith((*cache_)[url].score_, score)))
+ !ShouldReplaceThumbnailWith((*cache_)[url].second, score)))
return true;
base::TimeTicks encode_start = base::TimeTicks::Now();
- // Encode the SkBitmap to jpeg.
+ // Encode the SkBitmap to jpeg and add to cache.
scoped_refptr<RefCountedBytes> jpeg_data = new RefCountedBytes;
SkAutoLockPixels thumbnail_lock(thumbnail);
bool encoded = JPEGCodec::Encode(
@@ -84,31 +79,38 @@ bool ThumbnailStore::SetPageThumbnail(const GURL& url,
return false;
// Update the cache_ with the new thumbnail.
- (*cache_)[url] = CacheEntry(jpeg_data, score, true);
+ (*cache_)[url] = std::make_pair(jpeg_data, score);
+ // Write the new thumbnail data to disk in the background on file_thread.
+ if (write_to_disk) {
+ g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ThumbnailStore::WriteThumbnailToDisk, url,
+ jpeg_data, score));
+ }
return true;
}
bool ThumbnailStore::GetPageThumbnail(
const GURL& url,
RefCountedBytes** data) {
- if (!cache_.get() || IsURLBlacklisted(url))
+ if (!cache_initialized_ || IsURLBlacklisted(url))
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 the first available thumbnail starting at the end of the
- // redirect list.
- history::RedirectList::reverse_iterator rit;
- for (rit = it->second->data.rbegin();
- rit != it->second->data.rend(); ++rit) {
- if (cache_->find(*rit) != cache_->end()) {
- *data = (*cache_)[*rit].data_.get();
- (*data)->AddRef();
- return true;
- }
+ if (it == redirect_urls_->end())
+ return false;
+
+ // Return the first available thumbnail starting at the end of the
+ // redirect list.
+ history::RedirectList::reverse_iterator rit;
+ for (rit = it->second->data.rbegin();
+ rit != it->second->data.rend(); ++rit) {
+ if (cache_->find(*rit) != cache_->end()) {
+ *data = (*cache_)[*rit].first;
+ (*data)->AddRef();
+ return true;
}
}
@@ -117,7 +119,7 @@ bool ThumbnailStore::GetPageThumbnail(
if (cache_->find(url) == cache_->end())
return false;
- *data = (*cache_)[url].data_.get();
+ *data = (*cache_)[url].first;
(*data)->AddRef();
return true;
}
@@ -139,14 +141,14 @@ void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls,
}
void ThumbnailStore::CleanCacheData() {
- if (!cache_.get())
+ if (!cache_initialized_)
return;
// 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> > old_urls = new RefCountedVector<GURL>;
- for (Cache::iterator cache_it = cache_->begin();
+ for (ThumbnailStore::Cache::iterator cache_it = cache_->begin();
cache_it != cache_->end();) {
const GURL* url = NULL;
for (history::RedirectMap::iterator it = redirect_urls_->begin();
@@ -169,115 +171,145 @@ void ThumbnailStore::CleanCacheData() {
if (old_urls->data.size()) {
g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &ThumbnailStore::CommitCacheToDB, old_urls));
+ NewRunnableMethod(this, &ThumbnailStore::DeleteThumbnails, old_urls));
}
}
-void ThumbnailStore::CommitCacheToDB(
- scoped_refptr<RefCountedVector<GURL> > stale_urls) const {
- if (!db_)
- return;
+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);
+}
- // Delete old thumbnails.
- if (stale_urls.get()) {
- for (std::vector<GURL>::iterator it = stale_urls->data.begin();
- it != stale_urls->data.end(); ++it) {
- SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
- "DELETE FROM thumbnails WHERE url=?");
- statement->bind_string(0, it->spec());
- if (statement->step() != SQLITE_DONE)
- NOTREACHED();
- }
- }
+void ThumbnailStore::GetAllThumbnailsFromDisk(FilePath filepath,
+ MessageLoop* cb_loop) {
+ ThumbnailStore::Cache* cache = new ThumbnailStore::Cache;
- // Update cached thumbnails.
- for (Cache::iterator it = cache_->begin(); it != cache_->end(); ++it) {
- if (!it->second.dirty_)
- continue;
-
- SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
- "INSERT OR REPLACE INTO thumbnails "
- "(url, boring_score, good_clipping, at_top, time_taken, data) "
- "VALUES (?,?,?,?,?,?)");
- statement->bind_string(0, it->first.spec());
- statement->bind_double(1, it->second.score_.boring_score);
- statement->bind_bool(2, it->second.score_.good_clipping);
- statement->bind_bool(3, it->second.score_.at_top);
- statement->bind_int64(4, it->second.score_.time_at_snapshot.
- ToInternalValue());
- statement->bind_blob(5, &it->second.data_->data[0],
- static_cast<int>(it->second.data_->data.size()));
- if (statement->step() != SQLITE_DONE)
- DLOG(WARNING) << "Unable to insert thumbnail for URL";
- else
- it->second.dirty_ = false;
+ // 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));
}
-void ThumbnailStore::InitializeFromDB(const FilePath& db_name,
- MessageLoop* cb_loop) {
- if (OpenSqliteDb(db_name, &db_) != SQLITE_OK)
- return;
+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;
- // Use a large page size since the thumbnails we are storing are typically
- // large, a small cache size since we cache in memory and don't go to disk
- // often, and take exclusive access since nobody else uses this db.
- sqlite3_exec(db_, "PRAGMA page_size=4096 "
- "PRAGMA cache_size=64 "
- "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, NULL);
-
- statement_cache_ = new SqliteStatementCache;
-
- // Use local DBCloseScoper so that if we cannot create the table and
- // need to return, the |db_| and |statement_cache_| are closed properly.
- history::DBCloseScoper scoper(&db_, &statement_cache_);
-
- if (!DoesSqliteTableExist(db_, "thumbnails")) {
- if (sqlite3_exec(db_, "CREATE TABLE thumbnails ("
- "url LONGVARCHAR PRIMARY KEY,"
- "boring_score DOUBLE DEFAULT 1.0,"
- "good_clipping INTEGER DEFAULT 0,"
- "at_top INTEGER DEFAULT 0,"
- "time_taken INTEGER DEFAULT 0,"
- "data BLOB)", NULL, NULL, NULL) != SQLITE_OK)
- return;
- }
+ // 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;
- statement_cache_->set_db(db_);
+ // 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));
- // Now we can use a DBCloseScoper at the object scope.
- scoper.Detach();
- close_scoper_.Attach(&db_, &statement_cache_);
+ if (!packed.ReadString(&iter, &url_string) ||
+ !UnpackScore(score, packed, iter) ||
+ !packed.ReadUInt32(&iter, &jpeg_len))
+ return false;
- if (cb_loop)
- GetAllThumbnailsFromDisk(cb_loop);
-}
+ // Store the url to the out parameter.
+ GURL temp_url(url_string);
+ url->Swap(&temp_url);
-void ThumbnailStore::GetAllThumbnailsFromDisk(MessageLoop* cb_loop) {
- ThumbnailStore::Cache* cache = new ThumbnailStore::Cache;
+ // Unpack the JPEG data from the buffer.
+ const char* jpeg_data = NULL;
+ int out_len;
- SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
- "SELECT * FROM thumbnails");
-
- while (statement->step() == SQLITE_ROW) {
- GURL url(statement->column_string(0));
- ThumbnailScore score(statement->column_double(1), // Boring score
- statement->column_bool(2), // Good clipping
- statement->column_bool(3), // At top
- base::Time::FromInternalValue(
- statement->column_int64(4))); // Time taken
- scoped_refptr<RefCountedBytes> data = new RefCountedBytes;
- if (statement->column_blob_as_vector(5, &data->data))
- (*cache)[url] = CacheEntry(data, score, false);
- }
+ if (!packed.ReadData(&iter, &jpeg_data, &out_len) ||
+ out_len != static_cast<int>(jpeg_len))
+ return false;
- cb_loop->PostTask(FROM_HERE,
- NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache));
+ // 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)
+ 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.
+ packed->WriteData(reinterpret_cast<const char*>(&score.boring_score),
+ sizeof(score.boring_score));
+ packed->WriteBool(score.at_top);
+ packed->WriteBool(score.good_clipping);
+ packed->WriteInt64(score.time_at_snapshot.ToInternalValue());
+}
+
+bool ThumbnailStore::UnpackScore(ThumbnailScore* score, const Pickle& packed,
+ void*& iter) const {
+ // Unpack a ThumbnailScore from the given Pickle and iterator.
+ const char* boring = NULL;
+ int out_len;
+ int64 us;
+
+ if (!packed.ReadData(&iter, &boring, &out_len) ||
+ !packed.ReadBool(&iter, &score->at_top) ||
+ !packed.ReadBool(&iter, &score->good_clipping) ||
+ !packed.ReadInt64(&iter, &us))
+ return false;
+
+ if (out_len != sizeof(score->boring_score))
+ return false;
+
+ memcpy(&score->boring_score, boring, sizeof(score->boring_score));
+ score->time_at_snapshot = base::Time::FromInternalValue(us);
+ return true;
}
bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const {
@@ -301,6 +333,6 @@ 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(),
- url);
+ most_visited_urls_->end(),
+ url);
}
diff --git a/chrome/browser/thumbnail_store.h b/chrome/browser/thumbnail_store.h
index 0ec81f4..cf29e43 100644
--- a/chrome/browser/thumbnail_store.h
+++ b/chrome/browser/thumbnail_store.h
@@ -15,19 +15,17 @@
#include "base/timer.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/history/history.h"
-#include "chrome/browser/history/url_database.h" // For DBCloseScoper
#include "chrome/common/pref_names.h"
#include "chrome/common/ref_counted_util.h"
-#include "chrome/common/sqlite_compiled_statement.h"
-#include "chrome/common/thumbnail_score.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
class DictionaryValue;
class GURL;
class HistoryService;
+class Pickle;
class Profile;
class SkBitmap;
-struct sqlite3;
+struct ThumbnailScore;
namespace base {
class Time;
}
@@ -40,13 +38,17 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> {
~ThumbnailStore();
// Must be called after creation but before other methods are called.
- void Init(const FilePath& db_name, // The location of the database.
- Profile* profile); // To get to the HistoryService.
+ // file_path is a directory where a new database should be created
+ // or the location of an existing databse.
+ void Init(const FilePath& file_path, Profile* profile);
// Stores the given thumbnail and score with the associated url in the cache.
+ // If write_to_disk is true, the thumbnail data is written to disk on the
+ // file_thread.
bool SetPageThumbnail(const GURL& url,
const SkBitmap& thumbnail,
- const ThumbnailScore& score);
+ const ThumbnailScore& score,
+ bool write_to_disk);
// Sets *data to point to the thumbnail for the given url.
// Returns false if no thumbnail available.
@@ -59,22 +61,9 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> {
FRIEND_TEST(ThumbnailStoreTest, FollowRedirects);
friend class ThumbnailStoreTest;
- struct CacheEntry {
- scoped_refptr<RefCountedBytes> data_;
- ThumbnailScore score_;
- bool dirty_;
-
- CacheEntry() : data_(NULL), score_(ThumbnailScore()), dirty_(false) {}
- CacheEntry(RefCountedBytes* data,
- const ThumbnailScore& score,
- bool dirty)
- : data_(data),
- score_(score),
- dirty_(dirty) {}
- };
-
// Data structure used to store thumbnail data in memory.
- typedef std::map<GURL, CacheEntry> Cache;
+ typedef std::map<GURL, std::pair<scoped_refptr<RefCountedBytes>,
+ ThumbnailScore> > Cache;
// Most visited URLs and their redirect lists -------------------------------
@@ -83,7 +72,8 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> {
// callback is OnURLDataAvailable.
void UpdateURLData();
- // The callback for 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);
@@ -94,26 +84,43 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> {
// visited sites.
void CleanCacheData();
- // Disk operations ----------------------------------------------------------
+ // Deletes thumbnail data from disk for the given list of urls.
+ void DeleteThumbnails(
+ scoped_refptr<RefCountedVector<GURL> > thumbnail_urls) const;
- // Initialize |db_| to the database specified in |db_name|. If |cb_loop|
- // is non-null, calls GetAllThumbnailsFromDisk. Done on the file_thread.
- void InitializeFromDB(const FilePath& db_name, MessageLoop* cb_loop);
+ // 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.
- void GetAllThumbnailsFromDisk(MessageLoop* cb_loop);
+ void GetAllThumbnailsFromDisk(FilePath filepath, MessageLoop* cb_loop);
+
+ // Read the thumbnail data from the given file and stores it in the
+ // out parameters GURL, SkBitmap, and ThumbnailScore.
+ bool GetPageThumbnailFromDisk(const FilePath& file,
+ GURL* url,
+ RefCountedBytes* data,
+ ThumbnailScore* score) const;
// 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(Cache* cache);
- // Delete each URL in the given vector from the DB and write all dirty
- // cache entries to the DB.
- void CommitCacheToDB(
- scoped_refptr<RefCountedVector<GURL> > stale_urls) const;
+ // 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;
+
+ // Unpack a ThumbnailScore from a given Pickle and associated iterator.
+ // Returns false is a ThumbnailScore could not be unpacked.
+ bool UnpackScore(ThumbnailScore* score,
+ const Pickle& packed,
+ void*& iter) const;
// Decide whether to store data ---------------------------------------------
@@ -132,11 +139,10 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore> {
// The Cache maintained by the object.
scoped_ptr<Cache> cache_;
+ bool cache_initialized_;
- // The database holding the thumbnails on disk.
- sqlite3* db_;
- SqliteStatementCache* statement_cache_;
- history::DBCloseScoper close_scoper_;
+ // 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.
diff --git a/chrome/browser/thumbnail_store_unittest.cc b/chrome/browser/thumbnail_store_unittest.cc
index 8d3cb8a..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>
@@ -13,13 +12,12 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/gfx/jpeg_codec.h"
+#include "base/md5.h"
#include "base/path_service.h"
#include "base/ref_counted.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/ref_counted_util.h"
#include "chrome/common/thumbnail_score.h"
-#include "chrome/common/sqlite_compiled_statement.h"
-#include "chrome/common/sqlite_utils.h"
#include "chrome/tools/profiles/thumbnail-inl.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,10 +30,9 @@ inline unsigned int diff(unsigned int a, unsigned int b) {
class ThumbnailStoreTest : public testing::Test {
public:
- ThumbnailStoreTest() : score_(.5, true, false),
- url_("http://www.google.com/") {
+ ThumbnailStoreTest() : score1_(.5, true, false),
+ url1_("http://www.google.com/"), url2_("http://www.elgoog.com") {
}
-
~ThumbnailStoreTest() {
}
@@ -43,32 +40,33 @@ class ThumbnailStoreTest : public testing::Test {
void SetUp();
void TearDown() {
- file_util::Delete(db_name_, false);
+ file_util::Delete(file_path_.AppendASCII(url1_.host()), false);
+ file_util::Delete(file_path_.AppendASCII(url2_.host()), false);
}
// Compute the max difference over all pixels for each RGBA component.
void PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b);
// The directory where ThumbnailStore will store data.
- FilePath db_name_;
+ FilePath file_path_;
scoped_refptr<ThumbnailStore> store_;
scoped_ptr<SkBitmap> google_;
scoped_ptr<SkBitmap> weewar_;
scoped_refptr<RefCountedBytes> jpeg_google_;
scoped_refptr<RefCountedBytes> jpeg_weewar_;
- ThumbnailScore score_;
- GURL url_;
+ ThumbnailScore score1_;
+ GURL url1_, url2_;
base::Time time_;
};
void ThumbnailStoreTest::SetUp() {
- if (!file_util::GetTempDir(&db_name_))
+ if (!file_util::GetTempDir(&file_path_))
FAIL();
// Delete any old thumbnail files if they exist.
- db_name_ = db_name_.AppendASCII("ThumbnailDB");
- file_util::Delete(db_name_, false);
+ file_util::Delete(file_path_.AppendASCII(url1_.host()), false);
+ file_util::Delete(file_path_.AppendASCII(url2_.host()), false);
google_.reset(JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail)));
weewar_.reset(JPEGCodec::Decode(kWeewarThumbnail, sizeof(kWeewarThumbnail)));
@@ -92,12 +90,12 @@ void ThumbnailStoreTest::SetUp() {
&(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);
-
- store_->most_visited_urls_.reset(new std::vector<GURL>);
- store_->most_visited_urls_->push_back(url_);
}
void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) {
@@ -141,14 +139,21 @@ void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) {
TEST_F(ThumbnailStoreTest, UpdateThumbnail) {
RefCountedBytes* read_image = NULL;
ThumbnailScore score2(0.1, true, true);
+ store_->cache_->clear();
+ store_->redirect_urls_->clear();
// store_ google_ with a low score, then weewar_ with a higher score
// and check that weewar_ overwrote google_.
- EXPECT_TRUE(store_->SetPageThumbnail(url_, *google_, score_));
- EXPECT_TRUE(store_->SetPageThumbnail(url_, *weewar_, score2));
+ 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);
- EXPECT_TRUE(store_->GetPageThumbnail(url_, &read_image));
+ 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()));
@@ -158,16 +163,24 @@ TEST_F(ThumbnailStoreTest, UpdateThumbnail) {
TEST_F(ThumbnailStoreTest, RetrieveFromCache) {
RefCountedBytes* read_image = NULL;
+ store_->cache_->clear();
+ store_->redirect_urls_->clear();
// Retrieve a thumbnail/score for a page not in the cache.
- EXPECT_FALSE(store_->GetPageThumbnail(GURL("nonexistent"), &read_image));
+ 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(url_, *google_, score_));
- EXPECT_TRUE(store_->GetPageThumbnail(url_, &read_image));
- EXPECT_TRUE(score_.Equals((*store_->cache_)[url_].score_));
+ // 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);
+
+ 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()));
@@ -176,47 +189,46 @@ TEST_F(ThumbnailStoreTest, RetrieveFromCache) {
}
TEST_F(ThumbnailStoreTest, RetrieveFromDisk) {
- EXPECT_TRUE(store_->SetPageThumbnail(url_, *google_, score_));
-
- // Write the thumbnail to disk and retrieve it.
-
- store_->InitializeFromDB(db_name_, NULL);
- store_->CommitCacheToDB(NULL); // Write to the DB (dirty bit sould be set)
- store_->cache_->clear(); // Clear it from the cache.
-
- // Read from the DB.
- SQLITE_UNIQUE_STATEMENT(statement, *store_->statement_cache_,
- "SELECT * FROM thumbnails");
- EXPECT_TRUE(statement->step() == SQLITE_ROW);
- GURL url(statement->column_string(0));
- ThumbnailScore score(statement->column_double(1),
- statement->column_bool(2),
- statement->column_bool(3),
- base::Time::FromInternalValue(
- statement->column_int64(4)));
- scoped_refptr<RefCountedBytes> data = new RefCountedBytes;
- EXPECT_TRUE(statement->column_blob_as_vector(5, &data->data));
-
- EXPECT_TRUE(url == url_);
- EXPECT_TRUE(score.Equals(score_));
- EXPECT_TRUE(data->data.size() == jpeg_google_->data.size());
- EXPECT_EQ(0, memcmp(&data->data[0], &jpeg_google_->data[0],
+ scoped_refptr<RefCountedBytes> read_image = new RefCountedBytes;
+ ThumbnailScore score2;
+ store_->cache_->clear();
+ store_->redirect_urls_->clear();
+
+ // store_ a thumbnail onto the disk and retrieve it.
+
+ 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));
+ 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()));
}
TEST_F(ThumbnailStoreTest, FollowRedirects) {
RefCountedBytes* read_image = NULL;
- std::vector<GURL> redirects;
+ scoped_ptr<std::vector<GURL> > redirects(new std::vector<GURL>);
+ 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(url_); // url_ = http://www.google.com/
- (*store_->redirect_urls_)[my_url] = new RefCountedVector<GURL>(redirects);
+ redirects->push_back(GURL("google.com"));
+ redirects->push_back(GURL("www.google.com"));
+ redirects->push_back(url1_); // url1_ = http://www.google.com/
store_->most_visited_urls_->push_back(my_url);
- EXPECT_TRUE(store_->SetPageThumbnail(GURL("google.com"), *google_, score_));
+ (*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_));
+
+ EXPECT_TRUE(store_->SetPageThumbnail(GURL("google.com"), *google_, score1_,
+ false));
EXPECT_TRUE(store_->GetPageThumbnail(my_url, &read_image));
read_image->Release();