diff options
author | meelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-08 00:08:31 +0000 |
---|---|---|
committer | meelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-08 00:08:31 +0000 |
commit | 3254563421b09469b9668ff69562d098a8661d23 (patch) | |
tree | b9222dcaebe54cc87dcf47f952f58d124ae9b4ab /chrome/browser | |
parent | cb1da54001174e027d1bd5de4dbc5a91dca140e2 (diff) | |
download | chromium_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.cc | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 4 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.cc | 288 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.h | 78 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store_unittest.cc | 124 |
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(); |