summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormeelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 01:22:25 +0000
committermeelapshah@chromium.org <meelapshah@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 01:22:25 +0000
commitdaa82dc7442d26d9a50e342c0d9dcee43f287df8 (patch)
treebe3c211a383852579223f57be9c1ee13b84c1f6d /chrome
parentabaa71c990b2d9dd514e9f2eefb1d2cf7b720562 (diff)
downloadchromium_src-daa82dc7442d26d9a50e342c0d9dcee43f287df8.zip
chromium_src-daa82dc7442d26d9a50e342c0d9dcee43f287df8.tar.gz
chromium_src-daa82dc7442d26d9a50e342c0d9dcee43f287df8.tar.bz2
Make ThumbnailStore broadcast a notification when it has finished reading thumbnails from disk.
Make DOMUIThumbnailSource wait for this notification if ThumbnailStore isn't ready yet. Also clean up some of the code. Review URL: http://codereview.chromium.org/155911 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21785 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.cc56
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.h21
-rw-r--r--chrome/browser/history/history.h5
-rw-r--r--chrome/browser/history/history_backend.cc10
-rw-r--r--chrome/browser/profile.cc3
-rw-r--r--chrome/browser/thumbnail_store.cc139
-rw-r--r--chrome/browser/thumbnail_store.h39
-rw-r--r--chrome/browser/thumbnail_store_unittest.cc8
-rw-r--r--chrome/common/chrome_constants.cc1
-rw-r--r--chrome/common/chrome_constants.h1
-rw-r--r--chrome/common/notification_type.h6
11 files changed, 207 insertions, 82 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
index 5a10c7c..230389b 100644
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
+++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/profile.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"
#include "googleurl/src/gurl.h"
#include "grit/theme_resources.h"
@@ -23,20 +24,18 @@ DOMUIThumbnailSource::DOMUIThumbnailSource(Profile* profile)
void DOMUIThumbnailSource::StartDataRequest(const std::string& path,
int request_id) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kThumbnailStore)) {
- RefCountedBytes* data = NULL;
scoped_refptr<ThumbnailStore> store_ = profile_->GetThumbnailStore();
- if (store_->GetPageThumbnail(GURL(path), &data)) {
- // Got the thumbnail.
- SendResponse(request_id, data);
- } else {
- // Don't have the thumbnail so return the default thumbnail.
- if (!default_thumbnail_.get()) {
- default_thumbnail_ = new RefCountedBytes;
- ResourceBundle::GetSharedInstance().LoadImageResourceBytes(
- IDR_DEFAULT_THUMBNAIL, &default_thumbnail_->data);
+ if (!store_->IsReady()) {
+ // Register to be notified when the ThumbnailStore is ready.
+ if (registrar_.IsEmpty()) {
+ registrar_.Add(this, NotificationType::THUMBNAIL_STORE_READY,
+ Source<ThumbnailStore>(store_.get()));
}
- SendResponse(request_id, default_thumbnail_);
+ // Insert into pending_requests.
+ pending_requests_.push_back(std::make_pair(path, request_id));
+ } else {
+ DoDataRequest(path, request_id);
}
return;
} // end --thumbnail-store switch
@@ -55,6 +54,24 @@ void DOMUIThumbnailSource::StartDataRequest(const std::string& path,
}
}
+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 {
+ // Don't have the thumbnail so return the default thumbnail.
+ if (!default_thumbnail_.get()) {
+ default_thumbnail_ = new RefCountedBytes;
+ ResourceBundle::GetSharedInstance().LoadImageResourceBytes(
+ IDR_DEFAULT_THUMBNAIL, &default_thumbnail_->data);
+ }
+ SendResponse(request_id, default_thumbnail_);
+ }
+}
+
void DOMUIThumbnailSource::OnThumbnailDataAvailable(
HistoryService::Handle request_handle,
scoped_refptr<RefCountedBytes> data) {
@@ -74,3 +91,20 @@ void DOMUIThumbnailSource::OnThumbnailDataAvailable(
SendResponse(request_id, default_thumbnail_);
}
}
+
+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 c94967b..4e1555d 100644
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
+++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
@@ -5,20 +5,22 @@
#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_THUMBNAIL_SOURCE_H_
#define CHROME_BROWSER_DOM_UI_DOM_UI_THUMBNAIL_SOURCE_H_
-#include <set>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/history/history.h"
+#include "chrome/common/notification_registrar.h"
class Profile;
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 {
+class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource,
+ public NotificationObserver {
public:
explicit DOMUIThumbnailSource(Profile* profile);
@@ -37,6 +39,14 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
scoped_refptr<RefCountedBytes> data);
private:
+ // 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);
+
Profile* profile_;
CancelableRequestConsumerT<int, 0> cancelable_consumer_;
@@ -44,6 +54,13 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
// database doesn't have a thumbnail for a webpage.
scoped_refptr<RefCountedBytes> default_thumbnail_;
+ // Store requests when the ThumbnailStore isn't ready. When a notification is
+ // received that it is ready, then serve these requests.
+ std::vector<std::pair<std::string, int> > pending_requests_;
+
+ // To register to be notified when the ThumbnailStore is ready.
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(DOMUIThumbnailSource);
};
diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h
index 9aec250..0643139 100644
--- a/chrome/browser/history/history.h
+++ b/chrome/browser/history/history.h
@@ -306,7 +306,10 @@ class HistoryService : public CancelableRequestProvider,
// in the map containing redirects from the URL. For example, if we have the
// redirect chain A -> B -> C and A is a top visited URL, then A will be in
// the vector and "A => {B -> C}" will be in the map.
- typedef Callback2<std::vector<GURL>*, history::RedirectMap*>::Type
+ typedef Callback4<Handle,
+ bool, // Did we get the top urls and redirects?
+ std::vector<GURL>*, // List of top URLs.
+ history::RedirectMap*>::Type // Redirects for top URLs.
QueryTopURLsAndRedirectsCallback;
// Request the top |result_count| most visited URLs and the chain of redirects
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index bdf2351..1ccd7cf 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -1163,7 +1163,7 @@ void HistoryBackend::QueryTopURLsAndRedirects(
if (!db_.get()) {
request->ForwardResult(QueryTopURLsAndRedirectsRequest::TupleType(
- NULL, NULL));
+ request->handle(), false, NULL, NULL));
return;
}
@@ -1176,13 +1176,13 @@ void HistoryBackend::QueryTopURLsAndRedirects(
for (size_t i = 0; i < data.size(); ++i) {
top_urls->push_back(data[i]->GetURL());
- history::RedirectList list;
- GetMostRecentRedirectsFrom(top_urls->back(), &list);
- (*redirects)[top_urls->back()] = new RefCountedVector<GURL>(list);
+ RefCountedVector<GURL>* list = new RefCountedVector<GURL>;
+ GetMostRecentRedirectsFrom(top_urls->back(), &list->data);
+ (*redirects)[top_urls->back()] = list;
}
request->ForwardResult(QueryTopURLsAndRedirectsRequest::TupleType(
- top_urls, redirects));
+ request->handle(), true, top_urls, redirects));
}
void HistoryBackend::GetRedirectsFromSpecificVisit(
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index f32a7bd..5d39188 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -1047,7 +1047,8 @@ 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().Append(chrome::kNewTabThumbnailsFilename), this);
}
return thumbnail_store_.get();
}
diff --git a/chrome/browser/thumbnail_store.cc b/chrome/browser/thumbnail_store.cc
index e6f0e99..4f30c62 100644
--- a/chrome/browser/thumbnail_store.cc
+++ b/chrome/browser/thumbnail_store.cc
@@ -26,7 +26,8 @@ ThumbnailStore::ThumbnailStore()
: cache_(NULL),
db_(NULL),
hs_(NULL),
- url_blacklist_(NULL) {
+ url_blacklist_(NULL),
+ disk_data_loaded_(false) {
}
ThumbnailStore::~ThumbnailStore() {
@@ -34,8 +35,7 @@ ThumbnailStore::~ThumbnailStore() {
DCHECK(hs_ == NULL);
}
-void ThumbnailStore::Init(const FilePath& db_name,
- Profile* profile) {
+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,
@@ -50,7 +50,9 @@ void ThumbnailStore::Init(const FilePath& db_name,
// Get the list of most visited URLs and redirect information from the
// HistoryService.
- seconds_to_next_update_ = kInitialUpdateIntervalSecs;
+ 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.
@@ -139,8 +141,7 @@ void ThumbnailStore::Shutdown() {
// for details.
hs_ = NULL;
- // The source of notifications is the Profile. We may outlive the Profile so
- // we unregister for notifications here.
+ // De-register for notifications.
registrar_.RemoveAll();
// Stop the timer to ensure that UpdateURLData is not called during shutdown.
@@ -161,6 +162,11 @@ void ThumbnailStore::OnRedirectsForURLAvailable(
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 {
@@ -171,9 +177,20 @@ void ThumbnailStore::OnRedirectsForURLAvailable(
}
}
+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) {
+ const NotificationSource& source,
+ const NotificationDetails& details) {
if (type.value != NotificationType::HISTORY_URLS_DELETED) {
NOTREACHED();
return;
@@ -183,37 +200,58 @@ void ThumbnailStore::Observe(NotificationType type,
// If all history was cleared, clear all of our data and reset the update
// timer.
if (url_details->all_history) {
- most_visited_urls_.reset();
- redirect_urls_.reset();
- cache_.reset();
-
- timer_.Stop();
- seconds_to_next_update_ = kInitialUpdateIntervalSecs;
- timer_.Start(base::TimeDelta::FromSeconds(seconds_to_next_update_), this,
- &ThumbnailStore::UpdateURLData);
+ 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_->GetSize();
hs_->QueryTopURLsAndRedirects(result_count, &consumer_,
NewCallback(this, &ThumbnailStore::OnURLDataAvailable));
}
-void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls,
+void ThumbnailStore::OnURLDataAvailable(HistoryService::Handle handle,
+ bool success,
+ std::vector<GURL>* urls,
history::RedirectMap* redirects) {
+ if (!success)
+ return;
+
DCHECK(urls);
DCHECK(redirects);
- most_visited_urls_.reset(new std::vector<GURL>(*urls));
+ // 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));
- CleanCacheData();
- // Schedule the next update.
- if (seconds_to_next_update_ < kMaxUpdateIntervalSecs)
- seconds_to_next_update_ *= 2;
- timer_.Start(base::TimeDelta::FromSeconds(seconds_to_next_update_), this,
- &ThumbnailStore::UpdateURLData);
+ if (IsReady())
+ NotifyThumbnailStoreReady();
+
+ CleanCacheData();
}
void ThumbnailStore::CleanCacheData() {
@@ -228,26 +266,15 @@ void ThumbnailStore::CleanCacheData() {
// be written to disk.
for (Cache::iterator cache_it = cache_->begin();
cache_it != cache_->end();) {
- const GURL* url = NULL;
- // For each URL in the cache, search the RedirectMap for the originating
- // URL.
- for (history::RedirectMap::iterator it = redirect_urls_->begin();
- it != redirect_urls_->end(); ++it) {
- if (cache_it->first == it->first ||
- (it->second->data.size() &&
- cache_it->first == it->second->data.back())) {
- url = &it->first;
- break;
- }
- }
+ 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)) {
- // Note that we don't check whether the cache entry is dirty or not. If
- // it is not dirty, then the thumbnail exists on disk and must be
- // deleted. If it is dirty, it may exist on disk so we delete it anyways.
urls_to_delete->data.push_back(cache_it->first);
cache_->erase(cache_it++);
} else {
@@ -271,6 +298,8 @@ void ThumbnailStore::CommitCacheToDB(
if (!db_)
return;
+ base::TimeTicks db_start = base::TimeTicks::Now();
+
int rv = sqlite3_exec(db_, "BEGIN TRANSACTION", NULL, NULL, NULL);
DCHECK(rv == SQLITE_OK) << "Failed to begin transaction";
@@ -292,7 +321,8 @@ void ThumbnailStore::CommitCacheToDB(
it != data_to_save->end(); ++it) {
SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
"INSERT OR REPLACE INTO thumbnails "
- "(url, boring_score, good_clipping, at_top, time_taken, data) "
+ "(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);
@@ -309,6 +339,9 @@ void ThumbnailStore::CommitCacheToDB(
rv = sqlite3_exec(db_, "COMMIT", NULL, NULL, NULL);
DCHECK(rv == SQLITE_OK) << "Failed to commit transaction";
+
+ base::TimeDelta delta = base::TimeTicks::Now() - db_start;
+ HISTOGRAM_TIMES("ThumbnailStore.WriteDBToDisk", delta);
}
void ThumbnailStore::InitializeFromDB(const FilePath& db_name,
@@ -351,18 +384,23 @@ void ThumbnailStore::InitializeFromDB(const FilePath& db_name,
}
void ThumbnailStore::GetAllThumbnailsFromDisk(MessageLoop* cb_loop) {
- ThumbnailStore::Cache* cache = new ThumbnailStore::Cache;
+ Cache* cache = new Cache;
SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
"SELECT * FROM thumbnails");
while (statement->step() == SQLITE_ROW) {
+ // The URL
GURL url(statement->column_string(0));
+
+ // The score.
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
+
+ // The image.
scoped_refptr<RefCountedBytes> data = new RefCountedBytes;
if (statement->column_blob_as_vector(5, &data->data))
(*cache)[url] = CacheEntry(data, score, false);
@@ -372,17 +410,23 @@ void ThumbnailStore::GetAllThumbnailsFromDisk(MessageLoop* cb_loop) {
NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache));
}
-void ThumbnailStore::OnDiskDataAvailable(ThumbnailStore::Cache* 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 (IsURLBlacklisted(url) || cache_->size() >= ThumbnailStore::kMaxCacheSize)
+ if (!cache_.get())
+ return false;
+
+ if (IsURLBlacklisted(url) || cache_->size() >= kMaxCacheSize)
return false;
- return most_visited_urls_->size() < ThumbnailStore::kMaxCacheSize ||
- IsPopular(url);
+ return IsPopular(url);
}
bool ThumbnailStore::IsURLBlacklisted(const GURL& url) const {
@@ -397,7 +441,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);
+ 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
index 8b5fde8..143cbce 100644
--- a/chrome/browser/thumbnail_store.h
+++ b/chrome/browser/thumbnail_store.h
@@ -41,9 +41,12 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
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.
+ // 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,
@@ -83,11 +86,19 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
// 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
@@ -96,7 +107,9 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
void UpdateURLData();
// The callback for UpdateURLData.
- void OnURLDataAvailable(std::vector<GURL>* urls,
+ 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
@@ -108,6 +121,11 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
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
@@ -165,9 +183,9 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
// and redirect information.
scoped_refptr<HistoryService> hs_;
- // A list of the most_visited_urls_ refreshed every 30mins from the
+ // The most visited urls refreshed every kUpdateIntervalSecs from the
// HistoryService.
- scoped_ptr<std::vector<GURL> > most_visited_urls_;
+ scoped_ptr<MostVisitedMap> most_visited_urls_;
// A pointer to the persistent URL blacklist for this profile.
const DictionaryValue* url_blacklist_;
@@ -178,8 +196,7 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
scoped_ptr<history::RedirectMap> redirect_urls_;
// Timer on which UpdateURLData runs.
- base::OneShotTimer<ThumbnailStore> timer_;
- int seconds_to_next_update_;
+ base::RepeatingTimer<ThumbnailStore> timer_;
// Consumer for queries to the HistoryService.
CancelableRequestConsumer consumer_;
@@ -188,8 +205,10 @@ class ThumbnailStore : public base::RefCountedThreadSafe<ThumbnailStore>,
NotificationRegistrar registrar_;
static const unsigned int kMaxCacheSize = 24;
- static const int64 kInitialUpdateIntervalSecs = 180;
- static const int64 kMaxUpdateIntervalSecs = 3600;
+ static const int64 kUpdateIntervalSecs = 360;
+
+ // Has the data from disk been read?
+ bool disk_data_loaded_;
DISALLOW_COPY_AND_ASSIGN(ThumbnailStore);
};
diff --git a/chrome/browser/thumbnail_store_unittest.cc b/chrome/browser/thumbnail_store_unittest.cc
index 331d5df..cd8f146 100644
--- a/chrome/browser/thumbnail_store_unittest.cc
+++ b/chrome/browser/thumbnail_store_unittest.cc
@@ -96,8 +96,8 @@ void ThumbnailStoreTest::SetUp() {
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_);
+ store_->most_visited_urls_.reset(new ThumbnailStore::MostVisitedMap);
+ (*store_->most_visited_urls_)[url_] = GURL();
}
void ThumbnailStoreTest::PrintPixelDiff(SkBitmap* image_a, SkBitmap* image_b) {
@@ -183,7 +183,7 @@ TEST_F(ThumbnailStoreTest, RetrieveFromDisk) {
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.
+ store_->cache_->clear(); // Clear it from the cache.
// Read from the DB.
SQLITE_UNIQUE_STATEMENT(statement, *store_->statement_cache_,
@@ -215,7 +215,7 @@ TEST_F(ThumbnailStoreTest, FollowRedirects) {
redirects.push_back(url_); // url_ = http://www.google.com/
(*store_->redirect_urls_)[my_url] = new RefCountedVector<GURL>(redirects);
- store_->most_visited_urls_->push_back(my_url);
+ (*store_->most_visited_urls_)[url_] = my_url;
EXPECT_TRUE(store_->SetPageThumbnail(GURL("google.com"), *google_, score_,
false));
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index fbedb7c..2b32993 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -68,6 +68,7 @@ const FilePath::CharType kSafeBrowsingFilename[] = FPL("Safe Browsing");
// chrome_process_util_linux would be broken.
const FilePath::CharType kSingletonSocketFilename[] = FPL("SingletonSocket");
const FilePath::CharType kThumbnailsFilename[] = FPL("Thumbnails");
+const FilePath::CharType kNewTabThumbnailsFilename[] = FPL("Top Thumbnails");
const wchar_t kUserDataDirname[] = L"User Data";
const FilePath::CharType kUserScriptsDirname[] = FPL("User Scripts");
const FilePath::CharType kWebDataFilename[] = FPL("Web Data");
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 4f9f4a1..350c835 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -37,6 +37,7 @@ extern const FilePath::CharType kPreferencesFilename[];
extern const FilePath::CharType kSafeBrowsingFilename[];
extern const FilePath::CharType kSingletonSocketFilename[];
extern const FilePath::CharType kThumbnailsFilename[];
+extern const FilePath::CharType kNewTabThumbnailsFilename[];
extern const wchar_t kUserDataDirname[];
extern const FilePath::CharType kUserScriptsDirname[];
extern const FilePath::CharType kWebDataFilename[];
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 221bf32..04fc94f 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -471,6 +471,12 @@ class NotificationType {
// history_notifications.h).
FAVICON_CHANGED,
+ // Thumbnails---------------------------------------------------------------
+
+ // Set by ThumbnailStore when it was finished loading data from disk on
+ // startup.
+ THUMBNAIL_STORE_READY,
+
// Bookmarks ---------------------------------------------------------------
// Sent when the starred state of a URL changes. A URL is starred if there