diff options
author | nshkrob@chromium.org <nshkrob@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 17:19:02 +0000 |
---|---|---|
committer | nshkrob@chromium.org <nshkrob@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 17:19:02 +0000 |
commit | 0e7d57fa87b02031db31444a22cba54b32405896 (patch) | |
tree | 375a9a54ee14ef2eb66317ec074c280450f652e1 /chrome/browser | |
parent | f93d639888a72686e72f49e57fb4d42eab32cb04 (diff) | |
download | chromium_src-0e7d57fa87b02031db31444a22cba54b32405896.zip chromium_src-0e7d57fa87b02031db31444a22cba54b32405896.tar.gz chromium_src-0e7d57fa87b02031db31444a22cba54b32405896.tar.bz2 |
Remove ThumbnailStore - replaced by TopSites.
BUG=none
TEST=open New Tab page, see thumbnails. Same with chrome --top-sites.
Review URL: http://codereview.chromium.org/2815045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51728 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_thumbnail_source.cc | 31 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_thumbnail_source.h | 11 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 20 | ||||
-rw-r--r-- | chrome/browser/profile.h | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 1 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.cc | 436 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store.h | 216 | ||||
-rw-r--r-- | chrome/browser/thumbnail_store_unittest.cc | 227 |
8 files changed, 1 insertions, 946 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc index 5664cd5..a89c92f 100644 --- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc +++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc @@ -9,7 +9,6 @@ #include "base/command_line.h" #include "chrome/browser/profile.h" #include "chrome/browser/history/top_sites.h" -#include "chrome/browser/thumbnail_store.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" @@ -62,19 +61,6 @@ void DOMUIThumbnailSource::SendDefaultThumbnail(int request_id) { SendResponse(request_id, default_thumbnail_); } -// TODO(Nik): remove. ThumbnailStore is to be replaced with TopSites. -void DOMUIThumbnailSource::DoDataRequest(const std::string& path, - int request_id) { - RefCountedBytes* data = NULL; - scoped_refptr<ThumbnailStore> store_ = profile_->GetThumbnailStore(); - if (store_->GetPageThumbnail(GURL(path), &data)) { - // Got the thumbnail. - SendResponse(request_id, data); - } else { - SendDefaultThumbnail(request_id); - } -} - void DOMUIThumbnailSource::OnThumbnailDataAvailable( HistoryService::Handle request_handle, scoped_refptr<RefCountedBytes> data) { @@ -88,20 +74,3 @@ void DOMUIThumbnailSource::OnThumbnailDataAvailable( SendDefaultThumbnail(request_id); } } - -void DOMUIThumbnailSource::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type.value != NotificationType::THUMBNAIL_STORE_READY) { - NOTREACHED(); - return; - } - - // This notification is sent only once. - registrar_.RemoveAll(); - - for (size_t i = 0; i < pending_requests_.size(); ++i) - DoDataRequest(pending_requests_[i].first, pending_requests_[i].second); - - pending_requests_.clear(); -} diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h index d916aa4..cadf542 100644 --- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h +++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h @@ -20,8 +20,7 @@ class ThumbnailStore; // ThumbnailSource is the gateway between network-level chrome: // requests for thumbnails and the history backend that serves these. -class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource, - public NotificationObserver { +class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource { public: explicit DOMUIThumbnailSource(Profile* profile); @@ -44,14 +43,6 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource, private: ~DOMUIThumbnailSource() {} - // NotificationObserver implementation - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Fetch the specified resource. - void DoDataRequest(const std::string& path, int request_id); - // Send the default thumbnail when we are missing a real one. void SendDefaultThumbnail(int request_id); diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 6bd2104..3189694 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -58,7 +58,6 @@ #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_factory_impl.h" #include "chrome/browser/tabs/pinned_tab_service.h" -#include "chrome/browser/thumbnail_store.h" #include "chrome/browser/user_style_sheet_watcher.h" #include "chrome/browser/visitedlink_master.h" #include "chrome/browser/visitedlink_event_listener.h" @@ -623,10 +622,6 @@ class OffTheRecordProfileImpl : public Profile, return webkit_context_.get(); } - virtual ThumbnailStore* GetThumbnailStore() { - return NULL; - } - virtual history::TopSites* GetTopSites() { return NULL; } @@ -938,12 +933,6 @@ ProfileImpl::~ProfileImpl() { // The theme provider provides bitmaps to whoever wants them. theme_provider_.reset(); - // The ThumbnailStore saves thumbnails used by the NTP. Call Shutdown to - // save any new thumbnails to disk and release its reference to the - // HistoryService. - if (thumbnail_store_.get()) - thumbnail_store_->Shutdown(); - // Remove pref observers. PrefService* prefs = GetPrefs(); prefs->RemovePrefObserver(prefs::kSpellCheckDictionary, this); @@ -1530,15 +1519,6 @@ TabRestoreService* ProfileImpl::GetTabRestoreService() { return tab_restore_service_.get(); } -ThumbnailStore* ProfileImpl::GetThumbnailStore() { - if (!thumbnail_store_.get()) { - thumbnail_store_ = new ThumbnailStore; - thumbnail_store_->Init( - GetPath().Append(chrome::kNewTabThumbnailsFilename), this); - } - return thumbnail_store_.get(); -} - history::TopSites* ProfileImpl::GetTopSites() { if (!top_sites_.get()) { top_sites_ = new history::TopSites(this); diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 77fc45f..e462b6c 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -72,7 +72,6 @@ class TabRestoreService; class TemplateURLFetcher; class TemplateURLModel; class ThemeProvider; -class ThumbnailStore; class URLRequestContextGetter; class UserScriptMaster; class UserStyleSheetWatcher; @@ -289,8 +288,6 @@ class Profile { // Returns or creates the ThemeProvider associated with this profile virtual BrowserThemeProvider* GetThemeProvider() = 0; - virtual ThumbnailStore* GetThumbnailStore() = 0; - // Returns the request context information associated with this profile. Call // this only on the UI thread, since it can send notifications that should // happen on the UI thread. @@ -509,7 +506,6 @@ class ProfileImpl : public Profile, virtual void ClearTheme(); virtual Extension* GetTheme(); virtual BrowserThemeProvider* GetThemeProvider(); - virtual ThumbnailStore* GetThumbnailStore(); virtual bool HasCreatedDownloadManager() const; virtual URLRequestContextGetter* GetRequestContext(); virtual URLRequestContextGetter* GetRequestContextForMedia(); @@ -593,7 +589,6 @@ class ProfileImpl : public Profile, scoped_refptr<TransportSecurityPersister> transport_security_persister_; scoped_ptr<PrefService> prefs_; - scoped_refptr<ThumbnailStore> thumbnail_store_; scoped_ptr<TemplateURLFetcher> template_url_fetcher_; scoped_ptr<TemplateURLModel> template_url_model_; scoped_ptr<BookmarkModel> bookmark_bar_model_; diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index d524840..fa17e79 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -71,7 +71,6 @@ #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/tab_contents/thumbnail_generator.h" -#include "chrome/browser/thumbnail_store.h" #include "chrome/browser/translate/page_translated_details.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/thumbnail_store.cc b/chrome/browser/thumbnail_store.cc deleted file mode 100644 index 5ca13de..0000000 --- a/chrome/browser/thumbnail_store.cc +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/thumbnail_store.h" - -#include <string.h> -#include <algorithm> - -#include "app/sql/statement.h" -#include "app/sql/transaction.h" -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/file_util.h" -#include "base/md5.h" -#include "base/string_util.h" -#include "base/thread.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/history/history_notifications.h" -#include "chrome/browser/pref_service.h" -#include "chrome/browser/profile.h" -#include "gfx/codec/jpeg_codec.h" -#include "googleurl/src/gurl.h" -#include "third_party/skia/include/core/SkBitmap.h" - - -ThumbnailStore::ThumbnailStore() - : cache_(NULL), - hs_(NULL), - url_blacklist_(NULL), - disk_data_loaded_(false) { -} - -ThumbnailStore::~ThumbnailStore() { - // Ensure that shutdown was called. - DCHECK(hs_ == 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. - hs_ = profile->GetHistoryService(Profile::EXPLICIT_ACCESS); - - // Store a pointer to a persistent table of blacklisted URLs. - url_blacklist_ = profile->GetPrefs()-> - GetMutableDictionary(prefs::kNTPMostVisitedURLsBlacklist); - DCHECK(url_blacklist_); - - // Get the list of most visited URLs and redirect information from the - // HistoryService. - most_visited_urls_.reset(new MostVisitedMap); - timer_.Start(base::TimeDelta::FromSeconds(kUpdateIntervalSecs), this, - &ThumbnailStore::UpdateURLData); - UpdateURLData(); - - // Register to get notified when the history is cleared. - registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED, - Source<Profile>(profile)); -} - -bool ThumbnailStore::SetPageThumbnail(const GURL& url, - const SkBitmap& thumbnail, - const ThumbnailScore& score, - bool fetch_redirects) { - if (!cache_.get()) - return false; - - if (!ShouldStoreThumbnailForURL(url) || - (cache_->find(url) != cache_->end() && - !ShouldReplaceThumbnailWith((*cache_)[url].score_, score))) - return true; - - base::TimeTicks encode_start = base::TimeTicks::Now(); - - // Encode the SkBitmap to jpeg. - scoped_refptr<RefCountedBytes> jpeg_data = new RefCountedBytes; - SkAutoLockPixels thumbnail_lock(thumbnail); - bool encoded = gfx::JPEGCodec::Encode( - reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)), - gfx::JPEGCodec::FORMAT_BGRA, thumbnail.width(), - thumbnail.height(), - static_cast<int>(thumbnail.rowBytes()), 90, - &jpeg_data->data); - - base::TimeDelta delta = base::TimeTicks::Now() - encode_start; - HISTOGRAM_TIMES("Thumbnail.Encode", delta); - - if (!encoded) - return false; - - // Update the cache_ with the new thumbnail. - (*cache_)[url] = CacheEntry(jpeg_data, score, true); - - // Get redirects for this URL. - if (fetch_redirects) { - hs_->QueryRedirectsTo(url, &consumer_, - NewCallback(this, &ThumbnailStore::OnRedirectsForURLAvailable)); - } - - return true; -} - -bool ThumbnailStore::GetPageThumbnail( - const GURL& url, - RefCountedBytes** data) { - if (!cache_.get() || 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; - } - } - } - - // TODO(meelapshah) bug 14643: check past redirect lists - - if (cache_->find(url) == cache_->end()) - return false; - - *data = (*cache_)[url].data_.get(); - (*data)->AddRef(); - return true; -} - -void ThumbnailStore::Shutdown() { - // We must release our reference to the HistoryService here to prevent - // shutdown issues. Please refer to the comment in HistoryService::Cleanup - // for details. - hs_ = NULL; - - // De-register for notifications. - registrar_.RemoveAll(); - - // Stop the timer to ensure that UpdateURLData is not called during shutdown. - timer_.Stop(); - - // Write the cache to disk. This will schedule the disk operations to be run - // on the file_thread. Note that Join() does not need to be called with the - // file_thread because when the disk operation is scheduled, it will hold a - // reference to |this| keeping this object alive. - CleanCacheData(); -} - -void ThumbnailStore::OnRedirectsForURLAvailable( - HistoryService::Handle handle, - GURL url, - bool success, - history::RedirectList* redirects) { - if (!success) - return; - - DCHECK(redirect_urls_.get()); - - // If A -> B -> C is a redirect chain, then this function would be called - // with url=C and redirects = {B, A}. This is entered into the RedirectMap as - // A => {B -> C}. - if (redirects->empty()) { - (*redirect_urls_)[url] = new RefCountedVector<GURL>; - } else { - const GURL start_url = redirects->back(); - std::reverse(redirects->begin(), redirects->end() - 1); - *(redirects->end() - 1) = url; - (*redirect_urls_)[start_url] = new RefCountedVector<GURL>(*redirects); - } -} - -history::RedirectMap::iterator ThumbnailStore::GetRedirectIteratorForURL( - const GURL& url) const { - for (history::RedirectMap::iterator it = redirect_urls_->begin(); - it != redirect_urls_->end(); ++it) { - if (it->first == url || - (!it->second->data.empty() && it->second->data.back() == url)) - return it; - } - return redirect_urls_->end(); -} - -void ThumbnailStore::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type.value != NotificationType::HISTORY_URLS_DELETED) { - NOTREACHED(); - return; - } - - Details<history::URLsDeletedDetails> url_details(details); - // If all history was cleared, clear all of our data and reset the update - // timer. - if (url_details->all_history) { - most_visited_urls_->clear(); - redirect_urls_->clear(); - cache_->clear(); - timer_.Reset(); - } -} - -void ThumbnailStore::NotifyThumbnailStoreReady() { - NotificationService::current()->Notify( - NotificationType::THUMBNAIL_STORE_READY, - Source<ThumbnailStore>(this), - NotificationService::NoDetails()); -} - -void ThumbnailStore::UpdateURLData() { - DCHECK(url_blacklist_); - - int result_count = ThumbnailStore::kMaxCacheSize + url_blacklist_->size(); - hs_->QueryTopURLsAndRedirects(result_count, &consumer_, - NewCallback(this, &ThumbnailStore::OnURLDataAvailable)); -} - -void ThumbnailStore::OnURLDataAvailable(HistoryService::Handle handle, - bool success, - std::vector<GURL>* urls, - history::RedirectMap* redirects) { - if (!success) - return; - - DCHECK(urls); - DCHECK(redirects); - - // Each element of |urls| is the start of a redirect chain. When thumbnails - // are stored from TabContents, the tails of the redirect chains are - // associated with the image. Since SetPageThumbnail is called frequently, we - // look up the tail end of each element in |urls| and insert that into the - // MostVisitedMap. This way SetPageThumbnail can more quickly check if a - // given url is in the most visited list. - most_visited_urls_->clear(); - for (size_t i = 0; i < urls->size(); ++i) { - history::RedirectMap::iterator it = redirects->find(urls->at(i)); - if (it->second->data.empty()) - (*most_visited_urls_)[urls->at(i)] = GURL(); - else - (*most_visited_urls_)[it->second->data.back()] = urls->at(i); - } - redirect_urls_.reset(new history::RedirectMap(*redirects)); - - if (IsReady()) - NotifyThumbnailStoreReady(); - - CleanCacheData(); -} - -void ThumbnailStore::CleanCacheData() { - if (!cache_.get()) - return; - - scoped_refptr<RefCountedVector<GURL> > urls_to_delete = - new RefCountedVector<GURL>; - Cache* data_to_save = new Cache; // CommitCacheToDB will delete this - - // Iterate the cache, storing urls to be deleted and dirty cache entries to - // be written to disk. - for (Cache::iterator cache_it = cache_->begin(); - cache_it != cache_->end();) { - history::RedirectMap::iterator redirect_it = - GetRedirectIteratorForURL(cache_it->first); - const GURL* url = redirect_it == redirect_urls_->end() ? - NULL : &redirect_it->first; - - // If this URL is blacklisted or not in the most visited list, mark it for - // deletion. Otherwise, if the cache entry is dirty, mark it to be written - // to disk. - if (url == NULL || IsURLBlacklisted(*url) || !IsPopular(*url)) { - urls_to_delete->data.push_back(cache_it->first); - cache_->erase(cache_it++); - } else { - if (cache_it->second.dirty_) { - data_to_save->insert(*cache_it); - cache_it->second.dirty_ = false; - } - ++cache_it; - } - } - - g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &ThumbnailStore::CommitCacheToDB, - urls_to_delete, data_to_save)); -} - -void ThumbnailStore::CommitCacheToDB( - scoped_refptr<RefCountedVector<GURL> > urls_to_delete, - Cache* data) { - scoped_ptr<Cache> data_to_save(data); - if (!db_.is_open()) - return; - - base::TimeTicks db_start = base::TimeTicks::Now(); - - sql::Transaction transaction(&db_); - if (!transaction.Begin()) - return; - - // Delete old thumbnails. - if (urls_to_delete.get()) { - for (std::vector<GURL>::iterator it = urls_to_delete->data.begin(); - it != urls_to_delete->data.end(); ++it) { - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "DELETE FROM thumbnails WHERE url=?")); - if (!statement) - return; - statement.BindString(0, it->spec()); - if (!statement.Run()) - NOTREACHED(); - } - } - - // Update cached thumbnails. - if (data_to_save.get()) { - for (Cache::iterator it = data_to_save->begin(); - it != data_to_save->end(); ++it) { - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "INSERT OR REPLACE INTO thumbnails " - "(url, boring_score, good_clipping, " - "at_top, time_taken, data) " - "VALUES (?,?,?,?,?,?)")); - statement.BindString(0, it->first.spec()); - statement.BindDouble(1, it->second.score_.boring_score); - statement.BindBool(2, it->second.score_.good_clipping); - statement.BindBool(3, it->second.score_.at_top); - statement.BindInt64(4, - it->second.score_.time_at_snapshot.ToInternalValue()); - statement.BindBlob(5, &it->second.data_->data[0], - static_cast<int>(it->second.data_->data.size())); - if (!statement.Run()) - DLOG(WARNING) << "Unable to insert thumbnail for URL"; - } - } - - transaction.Commit(); - - base::TimeDelta delta = base::TimeTicks::Now() - db_start; - HISTOGRAM_TIMES("ThumbnailStore.WriteDBToDisk", delta); -} - -void ThumbnailStore::InitializeFromDB(const FilePath& db_name, - MessageLoop* cb_loop) { - db_.set_page_size(4096); - db_.set_cache_size(64); - db_.set_exclusive_locking(); - if (!db_.Open(db_name)) - return; - - if (!db_.DoesTableExist("thumbnails")) { - if (!db_.Execute("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)")) - return; - } - - if (cb_loop) - GetAllThumbnailsFromDisk(cb_loop); -} - -void ThumbnailStore::GetAllThumbnailsFromDisk(MessageLoop* cb_loop) { - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "SELECT * FROM thumbnails")); - if (!statement) - return; - - Cache* cache = new Cache; - while (statement.Step()) { - // The URL - GURL url(statement.ColumnString(0)); - - // The score. - ThumbnailScore score(statement.ColumnDouble(1), // Boring score - statement.ColumnBool(2), // Good clipping - statement.ColumnBool(3), // At top - base::Time::FromInternalValue( - statement.ColumnInt64(4))); // Time taken - - // The image. - scoped_refptr<RefCountedBytes> data = new RefCountedBytes; - statement.ColumnBlobAsVector(5, &data->data); - (*cache)[url] = CacheEntry(data, score, false); - } - - cb_loop->PostTask(FROM_HERE, - NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache)); -} - -void ThumbnailStore::OnDiskDataAvailable(Cache* cache) { - if (cache) - cache_.reset(cache); - - disk_data_loaded_ = true; - if (IsReady()) - NotifyThumbnailStoreReady(); -} - -bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const { - if (!cache_.get()) - return false; - - if (IsURLBlacklisted(url) || cache_->size() >= kMaxCacheSize) - return false; - - return IsPopular(url); -} - -bool ThumbnailStore::IsURLBlacklisted(const GURL& url) const { - if (url_blacklist_) - return url_blacklist_->HasKey(GetDictionaryKeyForURL(url.spec())); - return false; -} - -std::wstring ThumbnailStore::GetDictionaryKeyForURL( - const std::string& url) const { - return ASCIIToWide(MD5String(url)); -} - -bool ThumbnailStore::IsPopular(const GURL& url) const { - return most_visited_urls_->size() < kMaxCacheSize || - most_visited_urls_->find(url) != most_visited_urls_->end(); -} diff --git a/chrome/browser/thumbnail_store.h b/chrome/browser/thumbnail_store.h deleted file mode 100644 index a26b299..0000000 --- a/chrome/browser/thumbnail_store.h +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_THUMBNAIL_STORE_H_ -#define CHROME_BROWSER_THUMBNAIL_STORE_H_ - -#include <map> -#include <string> -#include <vector> - -#include "app/sql/connection.h" -#include "base/file_path.h" -#include "base/gtest_prod_util.h" -#include "base/message_loop.h" -#include "base/ref_counted.h" -#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/notification_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/ref_counted_util.h" -#include "chrome/common/thumbnail_score.h" - -class DictionaryValue; -class GURL; -class HistoryService; -class Profile; -class SkBitmap; -struct sqlite3; -namespace base { -class Time; -} - -// This storage interface provides storage for the thumbnails used -// by the new_tab_ui. -class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>, - public NotificationObserver { - public: - ThumbnailStore(); - - // Must be called before {Set,Get}PageThumbnail. |db_name| is the location - // of an existing ThumbnailStore database or where to create a new one. - void Init(const FilePath& db_name, Profile* profile); - - // Is the ThumbnailStore ready for GetPageThumbnail requests? - bool IsReady() { return disk_data_loaded_ && redirect_urls_.get(); } - - // Stores the given thumbnail and score with the associated url in the cache. - bool SetPageThumbnail(const GURL& url, - const SkBitmap& thumbnail, - const ThumbnailScore& score, - bool fetch_redirects); // for debugging - - // Sets *data to point to the thumbnail for the given url. - // Returns false if no thumbnail available. - bool GetPageThumbnail(const GURL& url, RefCountedBytes** data); - - // This is called when the browser is shutting down to write all dirty cache - // entries to disk. - void Shutdown(); - - private: - friend class base::RefCountedThreadSafe<ThumbnailStore>; - FRIEND_TEST_ALL_PREFIXES(ThumbnailStoreTest, RetrieveFromCache); - FRIEND_TEST_ALL_PREFIXES(ThumbnailStoreTest, RetrieveFromDisk); - FRIEND_TEST_ALL_PREFIXES(ThumbnailStoreTest, UpdateThumbnail); - FRIEND_TEST_ALL_PREFIXES(ThumbnailStoreTest, FollowRedirects); - friend class ThumbnailStoreTest; - - ~ThumbnailStore(); - - 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; - - // Data structre used to store the top visited URLs. It maps the end of a - // redirect chain to the beginning. If A -> B -> C is a redirect chain and C - // is a top visited url, then this map will contain an entry C => A. - typedef std::map<GURL, GURL> MostVisitedMap; - - // NotificationObserver implementation - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Notify anyone listening that the ThumbnailStore is ready to be used. - void NotifyThumbnailStoreReady(); - - // 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. - void OnURLDataAvailable(HistoryService::Handle handle, - bool success, - std::vector<GURL>* urls, - history::RedirectMap* redirects); - - // The callback for the redirects request to the HistoryService made in - // SetPageThumbnail. If we have a redirect chain A -> B -> C, this function - // will be called with url=C and redirects = {B -> A}. This information gets - // inserted into the RedirectMap as A => {B -> C}. - void OnRedirectsForURLAvailable(HistoryService::Handle handle, - GURL url, - bool success, - history::RedirectList* redirects); - - // Search the RedirectMap for a redirect chain ending at |url|. Returns an - // iterator to an entry in redirect_urls_ if found or redirect_urls_->end(). - history::RedirectMap::iterator GetRedirectIteratorForURL( - const GURL& url) const; - - // Remove stale data -------------------------------------------------------- - - // Remove entries from the in memory thumbnail cache cache that have been - // blacklisted or are not in the top kMaxCacheSize visited sites. Call - // CommitCacheToDB on the file_thread to remove these entries from disk and - // to also write new entries to disk. - void CleanCacheData(); - - // Disk operations ---------------------------------------------------------- - - // 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); - - // 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); - - // 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> > urls_to_delete, - Cache* data); - - // Decide whether to store data --------------------------------------------- - - bool ShouldStoreThumbnailForURL(const GURL& url) const; - - bool IsURLBlacklisted(const GURL& url) const; - - std::wstring GetDictionaryKeyForURL(const std::string& url) const; - - // Returns true if url is in most_visited_urls_. - bool IsPopular(const GURL& url) const; - - - - // Member variables --------------------------------------------------------- - - // The Cache maintained by the object. - scoped_ptr<Cache> cache_; - - // The database holding the thumbnails on disk. - sql::Connection db_; - - // We hold a reference to the history service to query for most visited URLs - // and redirect information. - scoped_refptr<HistoryService> hs_; - - // The most visited urls refreshed every kUpdateIntervalSecs from the - // HistoryService. - scoped_ptr<MostVisitedMap> most_visited_urls_; - - // A pointer to the persistent URL blacklist for this profile. - const DictionaryValue* url_blacklist_; - - // 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/ } - scoped_ptr<history::RedirectMap> redirect_urls_; - - // Timer on which UpdateURLData runs. - base::RepeatingTimer<ThumbnailStore> timer_; - - // Consumer for queries to the HistoryService. - CancelableRequestConsumer consumer_; - - // Registrar to get notified when the history is cleared. - NotificationRegistrar registrar_; - - static const unsigned int kMaxCacheSize = 24; - static const int64 kUpdateIntervalSecs = 360; - - // Has the data from disk been read? - bool disk_data_loaded_; - - DISALLOW_COPY_AND_ASSIGN(ThumbnailStore); -}; - -#endif // CHROME_BROWSER_THUMBNAIL_STORE_H_ diff --git a/chrome/browser/thumbnail_store_unittest.cc b/chrome/browser/thumbnail_store_unittest.cc deleted file mode 100644 index e28765f..0000000 --- a/chrome/browser/thumbnail_store_unittest.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string.h> -#include <algorithm> -#include <iostream> -#include <vector> - -#include "chrome/browser/thumbnail_store.h" - -#include "app/sql/connection.h" -#include "app/sql/statement.h" -#include "base/time.h" -#include "base/file_path.h" -#include "base/file_util.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/tools/profiles/thumbnail-inl.h" -#include "gfx/codec/jpeg_codec.h" -#include "googleurl/src/gurl.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkPixelRef.h" - -inline unsigned int diff(unsigned int a, unsigned int b) { - return a>b ? a-b : b-a; -} - -class ThumbnailStoreTest : public testing::Test { - public: - ThumbnailStoreTest() : score_(.5, true, false), - url_("http://www.google.com/") { - } - - ~ThumbnailStoreTest() { - } - - protected: - void SetUp(); - - void TearDown() { - file_util::Delete(db_name_, 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_; - - 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_; - base::Time time_; -}; - -void ThumbnailStoreTest::SetUp() { - if (!file_util::GetTempDir(&db_name_)) - FAIL(); - - // Delete any old thumbnail files if they exist. - db_name_ = db_name_.AppendASCII("ThumbnailDB"); - file_util::Delete(db_name_, false); - - google_.reset(gfx::JPEGCodec::Decode(kGoogleThumbnail, - sizeof(kGoogleThumbnail))); - weewar_.reset(gfx::JPEGCodec::Decode(kWeewarThumbnail, - sizeof(kWeewarThumbnail))); - - SkAutoLockPixels lock1(*google_); - jpeg_google_ = new RefCountedBytes; - gfx::JPEGCodec::Encode( - reinterpret_cast<unsigned char*>(google_->getAddr32(0, 0)), - gfx::JPEGCodec::FORMAT_BGRA, google_->width(), - google_->height(), - static_cast<int>(google_->rowBytes()), 90, - &(jpeg_google_->data)); - - SkAutoLockPixels lock2(*weewar_); - jpeg_weewar_ = new RefCountedBytes; - gfx::JPEGCodec::Encode( - reinterpret_cast<unsigned char*>(weewar_->getAddr32(0, 0)), - gfx::JPEGCodec::FORMAT_BGRA, weewar_->width(), - weewar_->height(), - static_cast<int>(weewar_->rowBytes()), 90, - &(jpeg_weewar_->data)); - - store_ = new ThumbnailStore; - - store_->cache_.reset(new ThumbnailStore::Cache); - store_->redirect_urls_.reset(new history::RedirectMap); - - store_->most_visited_urls_.reset(new ThumbnailStore::MostVisitedMap); - (*store_->most_visited_urls_)[url_] = GURL(); -} - -void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) { - // Compute the maximum difference in each of the RGBA components across all - // pixels between the retrieved SkBitmap and the original. These - // differences should be small since encoding was done at 90% before - // writing to disk. - - if (image_a->height() != image_b->height() || - image_b->width() != image_b->width() || - image_a->rowBytes() != image_b->rowBytes()) - return; - - SkAutoLockPixels lock_a(*image_a); - SkAutoLockPixels lock_b(*image_b); - - int ppr = image_a->rowBytesAsPixels(); - unsigned int *a, *b; - unsigned int maxv[4]; - memset(maxv, 0, sizeof(maxv)); - - for (int nrows = image_a->height()-1; nrows >= 0; nrows--) { - a = image_a->getAddr32(0, nrows); - b = image_b->getAddr32(0, nrows); - for (int i = 0; i < ppr; i += 4) { - for (int j = 0; j < 4; j++) { - maxv[j] = std::max(diff(*(a+i) >> (j<<3) & 0xff, - *(b+i) >> (j<<3) & 0xff), - maxv[j]); - } - } - } - - std::cout << "Max diff btwn original and encoded image (b,g,r,a) = (" - << maxv[0] << "," - << maxv[1] << "," - << maxv[2] << "," - << maxv[3] << ")" << std::endl; -} - -TEST_F(ThumbnailStoreTest, UpdateThumbnail) { - RefCountedBytes* read_image = NULL; - ThumbnailScore score2(0.1, true, true); - - // 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_, false)); - EXPECT_TRUE(store_->SetPageThumbnail(url_, *weewar_, score2, false)); - - EXPECT_TRUE(store_->GetPageThumbnail(url_, &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())); - - read_image->Release(); -} - -TEST_F(ThumbnailStoreTest, RetrieveFromCache) { - RefCountedBytes* read_image = NULL; - - // Retrieve a thumbnail/score for a page not in the cache. - - EXPECT_FALSE(store_->GetPageThumbnail(GURL("nonexistent"), &read_image)); - - // Store a thumbnail into the cache and retrieve it. - - EXPECT_TRUE(store_->SetPageThumbnail(url_, *google_, score_, false)); - EXPECT_TRUE(store_->GetPageThumbnail(url_, &read_image)); - EXPECT_TRUE(score_.Equals((*store_->cache_)[url_].score_)); - 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())); - - read_image->Release(); -} - -TEST_F(ThumbnailStoreTest, RetrieveFromDisk) { - EXPECT_TRUE(store_->SetPageThumbnail(url_, *google_, score_, false)); - - // Write the thumbnail to disk and retrieve it. - - store_->InitializeFromDB(db_name_, NULL); - // Write to the DB (dirty bit sould be set) - store_->CommitCacheToDB(NULL, new ThumbnailStore::Cache(*store_->cache_)); - store_->cache_->clear(); // Clear it from the cache. - - // Read from the DB. - sql::Statement statement(store_->db_.GetUniqueStatement( - "SELECT * FROM thumbnails")); - EXPECT_TRUE(statement.Step()); - GURL url(statement.ColumnString(0)); - ThumbnailScore score(statement.ColumnDouble(1), - statement.ColumnBool(2), - statement.ColumnBool(3), - base::Time::FromInternalValue( - statement.ColumnInt64(4))); - scoped_refptr<RefCountedBytes> data = new RefCountedBytes; - statement.ColumnBlobAsVector(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], - jpeg_google_->data.size())); -} - -TEST_F(ThumbnailStoreTest, FollowRedirects) { - RefCountedBytes* read_image = NULL; - std::vector<GURL> redirects; - - 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); - - (*store_->most_visited_urls_)[url_] = my_url; - - EXPECT_TRUE(store_->SetPageThumbnail(GURL("google.com"), *google_, score_, - false)); - EXPECT_TRUE(store_->GetPageThumbnail(my_url, &read_image)); - - read_image->Release(); -} |