summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-24 22:05:33 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-24 22:05:33 +0000
commitba66d9e8298ca4237fdf513f3e84233aa6d8152d (patch)
tree6f81cd2dec16948a2e5d5f3566274a7175d00c95
parentabaf4e6fca4450bb6be70c03fbeb36e33903ad4b (diff)
downloadchromium_src-ba66d9e8298ca4237fdf513f3e84233aa6d8152d.zip
chromium_src-ba66d9e8298ca4237fdf513f3e84233aa6d8152d.tar.gz
chromium_src-ba66d9e8298ca4237fdf513f3e84233aa6d8152d.tar.bz2
Revert 63687 - Refactors TopSites so that it's hopefully easier to maintain and
doesn't suffer the plethora of threading issues that exist with the current version. Here's the breakdown of what was refactored: . TopSitesCache: Contains the most visited urls and thumbnails. . TopSitesBackend: All mutations to topsites data end up calling into the backend on the UI thread. TopSitesBackend processes the method on the DB thread calling through to the TopSitesDatabase. . TopSites: uses two TopSitesCache. One that contains the raw history data, the other contains the processed data (pinned/blacklisted). The processed cache can be accessed on any thread. TopSites waits until history loads to know if it should migrate or use it's own db. I could probably make these execute in parallel, but for now this is how it works. This patch also makes it so the dom ui accesses the thumbnails on the IO thread. BUG=56382 TEST=Make sure all your thumbnails are correctly updated and you don't see problems. Review URL: http://codereview.chromium.org/3440018 TBR=sky@chromium.org Review URL: http://codereview.chromium.org/4048005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63695 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/dom_ui/dom_ui_theme_source.h2
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.cc25
-rw-r--r--chrome/browser/dom_ui/dom_ui_thumbnail_source.h18
-rw-r--r--chrome/browser/dom_ui/most_visited_handler.cc28
-rw-r--r--chrome/browser/history/expire_history_backend_unittest.cc74
-rw-r--r--chrome/browser/history/history.cc9
-rw-r--r--chrome/browser/history/history_backend.cc55
-rw-r--r--chrome/browser/history/history_backend.h5
-rw-r--r--chrome/browser/history/history_backend_unittest.cc8
-rw-r--r--chrome/browser/history/history_database.cc37
-rw-r--r--chrome/browser/history/history_database.h9
-rw-r--r--chrome/browser/history/history_types.cc3
-rw-r--r--chrome/browser/history/history_types.h69
-rw-r--r--chrome/browser/history/thumbnail_database.cc1
-rw-r--r--chrome/browser/history/top_sites.cc1180
-rw-r--r--chrome/browser/history/top_sites.h316
-rw-r--r--chrome/browser/history/top_sites_backend.cc150
-rw-r--r--chrome/browser/history/top_sites_backend.h104
-rw-r--r--chrome/browser/history/top_sites_cache.cc96
-rw-r--r--chrome/browser/history/top_sites_cache.h80
-rw-r--r--chrome/browser/history/top_sites_database.cc3
-rw-r--r--chrome/browser/history/top_sites_database.h9
-rw-r--r--chrome/browser/history/top_sites_unittest.cc1844
-rw-r--r--chrome/browser/profile_impl.cc2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc7
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--chrome/common/notification_type.h6
-rw-r--r--chrome/test/data/profiles/typical_history/Default/Historybin3309568 -> 13774848 bytes
-rw-r--r--chrome/test/data/top_sites/history.19.sql38
-rw-r--r--chrome/test/data/top_sites/thumbnails.3.sql12
-rw-r--r--chrome/test/testing_profile.cc37
-rw-r--r--chrome/test/testing_profile.h6
32 files changed, 1856 insertions, 2383 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.h b/chrome/browser/dom_ui/dom_ui_theme_source.h
index 2d55aaa..61f3abf 100644
--- a/chrome/browser/dom_ui/dom_ui_theme_source.h
+++ b/chrome/browser/dom_ui/dom_ui_theme_source.h
@@ -13,6 +13,8 @@
class Profile;
class RefCountedBytes;
+// ThumbnailSource is the gateway between network-level chrome:
+// requests for thumbnails and the history backend that serves these.
class DOMUIThemeSource : public ChromeURLDataManager::DataSource {
public:
explicit DOMUIThemeSource(Profile* profile);
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
index 4ed9d4a..f17586f 100644
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
+++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.cc
@@ -10,16 +10,14 @@
#include "chrome/browser/history/top_sites.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
+#include "gfx/codec/jpeg_codec.h"
#include "googleurl/src/gurl.h"
#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
DOMUIThumbnailSource::DOMUIThumbnailSource(Profile* profile)
: DataSource(chrome::kChromeUIThumbnailPath, MessageLoop::current()),
profile_(profile) {
- if (history::TopSites::IsEnabled()) {
- // Set TopSites now as Profile isn't thread safe.
- top_sites_ = profile_->GetTopSites();
- }
}
DOMUIThumbnailSource::~DOMUIThumbnailSource() {
@@ -28,11 +26,12 @@ DOMUIThumbnailSource::~DOMUIThumbnailSource() {
void DOMUIThumbnailSource::StartDataRequest(const std::string& path,
bool is_off_the_record,
int request_id) {
- if (top_sites_.get()) {
- scoped_refptr<RefCountedBytes> data;
- if (top_sites_->GetPageThumbnail(GURL(path), &data)) {
+ if (history::TopSites::IsEnabled()) {
+ history::TopSites* top_sites = profile_->GetTopSites();
+ RefCountedBytes* data = NULL;
+ if (top_sites->GetPageThumbnail(GURL(path), &data)) {
// We have the thumbnail.
- SendResponse(request_id, data.get());
+ SendResponse(request_id, data);
} else {
SendDefaultThumbnail(request_id);
}
@@ -59,12 +58,6 @@ std::string DOMUIThumbnailSource::GetMimeType(const std::string&) const {
return "image/png";
}
-MessageLoop* DOMUIThumbnailSource::MessageLoopForRequestPath(
- const std::string& path) const {
- // TopSites can be accessed from the IO thread.
- return top_sites_.get() ? NULL : DataSource::MessageLoopForRequestPath(path);
-}
-
void DOMUIThumbnailSource::SendDefaultThumbnail(int request_id) {
// Use placeholder thumbnail.
if (!default_thumbnail_.get()) {
@@ -78,7 +71,9 @@ void DOMUIThumbnailSource::SendDefaultThumbnail(int request_id) {
void DOMUIThumbnailSource::OnThumbnailDataAvailable(
HistoryService::Handle request_handle,
scoped_refptr<RefCountedBytes> data) {
- int request_id = cancelable_consumer_.GetClientDataForCurrentRequest();
+ HistoryService* hs =
+ profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ int request_id = cancelable_consumer_.GetClientData(hs, request_handle);
// Forward the data along to the networking system.
if (data.get() && !data->data.empty()) {
SendResponse(request_id, data);
diff --git a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
index 8dd3a2d..3c0578b 100644
--- a/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
+++ b/chrome/browser/dom_ui/dom_ui_thumbnail_source.h
@@ -15,13 +15,10 @@
#include "chrome/common/notification_registrar.h"
class Profile;
+class ThumbnailStore;
-namespace history {
-class TopSites;
-}
-
-// ThumbnailSource is the gateway between network-level chrome: requests for
-// thumbnails and the history/top-sites backend that serves these.
+// ThumbnailSource is the gateway between network-level chrome:
+// requests for thumbnails and the history backend that serves these.
class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
public:
explicit DOMUIThumbnailSource(Profile* profile);
@@ -32,9 +29,7 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
bool is_off_the_record,
int request_id);
- virtual std::string GetMimeType(const std::string& path) const;
-
- virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
+ virtual std::string GetMimeType(const std::string&) const;
// Called when thumbnail data is available from the history backend.
void OnThumbnailDataAvailable(HistoryService::Handle request_handle,
@@ -47,15 +42,14 @@ class DOMUIThumbnailSource : public ChromeURLDataManager::DataSource {
void SendDefaultThumbnail(int request_id);
Profile* profile_;
-
CancelableRequestConsumerT<int, 0> cancelable_consumer_;
// Raw PNG representation of the thumbnail to show when the thumbnail
// database doesn't have a thumbnail for a webpage.
scoped_refptr<RefCountedMemory> default_thumbnail_;
- // TopSites. If non-null we're using TopSites.
- scoped_refptr<history::TopSites> top_sites_;
+ // To register to be notified when the ThumbnailStore is ready.
+ NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(DOMUIThumbnailSource);
};
diff --git a/chrome/browser/dom_ui/most_visited_handler.cc b/chrome/browser/dom_ui/most_visited_handler.cc
index ac027b6..bb10fe7 100644
--- a/chrome/browser/dom_ui/most_visited_handler.cc
+++ b/chrome/browser/dom_ui/most_visited_handler.cc
@@ -135,8 +135,7 @@ void MostVisitedHandler::SendPagesValue() {
bool has_blacklisted_urls = !url_blacklist_->empty();
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- has_blacklisted_urls = ts->HasBlacklistedItems();
+ has_blacklisted_urls = ts->HasBlacklistedItems();
}
FundamentalValue first_run(IsFirstRun());
FundamentalValue has_blacklisted_urls_value(has_blacklisted_urls);
@@ -152,11 +151,9 @@ void MostVisitedHandler::StartQueryForMostVisited() {
if (history::TopSites::IsEnabled()) {
// Use TopSites.
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts) {
- ts->GetMostVisitedURLs(
- &topsites_consumer_,
- NewCallback(this, &MostVisitedHandler::OnMostVisitedURLsAvailable));
- }
+ ts->GetMostVisitedURLs(
+ &topsites_consumer_,
+ NewCallback(this, &MostVisitedHandler::OnMostVisitedURLsAvailable));
return;
}
@@ -198,8 +195,7 @@ void MostVisitedHandler::HandleRemoveURLsFromBlacklist(const ListValue* args) {
dom_ui_->GetProfile());
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- ts->RemoveBlacklistedURL(GURL(url));
+ ts->RemoveBlacklistedURL(GURL(url));
return;
}
@@ -214,8 +210,7 @@ void MostVisitedHandler::HandleClearBlacklist(const ListValue* args) {
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- ts->ClearBlacklistedURLs();
+ ts->ClearBlacklistedURLs();
return;
}
@@ -259,8 +254,7 @@ void MostVisitedHandler::HandleAddPinnedURL(const ListValue* args) {
void MostVisitedHandler::AddPinnedURL(const MostVisitedPage& page, int index) {
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- ts->AddPinnedURL(page.url, index);
+ ts->AddPinnedURL(page.url, index);
return;
}
@@ -289,8 +283,7 @@ void MostVisitedHandler::HandleRemovePinnedURL(const ListValue* args) {
void MostVisitedHandler::RemovePinnedURL(const GURL& url) {
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- ts->RemovePinnedURL(url);
+ ts->RemovePinnedURL(url);
return;
}
@@ -449,7 +442,7 @@ void MostVisitedHandler::SetPagesValueFromTopSites(
}
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts && ts->IsURLPinned(url.url))
+ if (ts->IsURLPinned(url.url))
page_value->SetBoolean("pinned", true);
pages_value_->Append(page_value);
}
@@ -525,8 +518,7 @@ void MostVisitedHandler::Observe(NotificationType type,
void MostVisitedHandler::BlacklistURL(const GURL& url) {
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = dom_ui_->GetProfile()->GetTopSites();
- if (ts)
- ts->AddBlacklistedURL(url);
+ ts->AddBlacklistedURL(url);
return;
}
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc
index 3177dde..91129ed 100644
--- a/chrome/browser/history/expire_history_backend_unittest.cc
+++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -8,7 +8,6 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
-#include "base/scoped_temp_dir.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
@@ -32,6 +31,7 @@ using base::TimeDelta;
using base::TimeTicks;
// Filename constants.
+static const FilePath::CharType kTestDir[] = FILE_PATH_LITERAL("ExpireTest");
static const FilePath::CharType kHistoryFile[] = FILE_PATH_LITERAL("History");
static const FilePath::CharType kArchivedHistoryFile[] =
FILE_PATH_LITERAL("Archived History");
@@ -49,8 +49,6 @@ class ExpireHistoryTest : public testing::Test,
public:
ExpireHistoryTest()
: bookmark_model_(NULL),
- ui_thread_(BrowserThread::UI, &message_loop_),
- db_thread_(BrowserThread::DB, &message_loop_),
ALLOW_THIS_IN_INITIALIZER_LIST(expirer_(this, &bookmark_model_)),
now_(Time::Now()) {
}
@@ -87,17 +85,9 @@ class ExpireHistoryTest : public testing::Test,
static bool IsStringInFile(const FilePath& filename, const char* str);
- // Returns the path the db files are created in.
- const FilePath& path() const { return tmp_dir_.path(); }
-
- // This must be destroyed last.
- ScopedTempDir tmp_dir_;
-
BookmarkModel bookmark_model_;
- MessageLoopForUI message_loop_;
- BrowserThread ui_thread_;
- BrowserThread db_thread_;
+ MessageLoop message_loop_;
ExpireHistoryBackend expirer_;
@@ -118,40 +108,43 @@ class ExpireHistoryTest : public testing::Test,
NotificationList;
NotificationList notifications_;
+ // Directory for the history files.
+ FilePath dir_;
+
private:
void SetUp() {
- ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
+ FilePath temp_dir;
+ PathService::Get(base::DIR_TEMP, &temp_dir);
+ dir_ = temp_dir.Append(kTestDir);
+ file_util::Delete(dir_, true);
+ file_util::CreateDirectory(dir_);
- FilePath history_name = path().Append(kHistoryFile);
+ FilePath history_name = dir_.Append(kHistoryFile);
main_db_.reset(new HistoryDatabase);
if (main_db_->Init(history_name, FilePath()) != sql::INIT_OK)
main_db_.reset();
- FilePath archived_name = path().Append(kArchivedHistoryFile);
+ FilePath archived_name = dir_.Append(kArchivedHistoryFile);
archived_db_.reset(new ArchivedDatabase);
if (!archived_db_->Init(archived_name))
archived_db_.reset();
- FilePath thumb_name = path().Append(kThumbnailFile);
+ FilePath thumb_name = dir_.Append(kThumbnailFile);
thumb_db_.reset(new ThumbnailDatabase);
if (thumb_db_->Init(thumb_name, NULL) != sql::INIT_OK)
thumb_db_.reset();
- text_db_.reset(new TextDatabaseManager(path(),
+ text_db_.reset(new TextDatabaseManager(dir_,
main_db_.get(), main_db_.get()));
if (!text_db_->Init(NULL))
text_db_.reset();
expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(),
text_db_.get());
- profile_.CreateTopSites();
- profile_.BlockUntilTopSitesLoaded();
top_sites_ = profile_.GetTopSites();
}
void TearDown() {
- top_sites_ = NULL;
-
ClearLastNotifications();
expirer_.SetDatabases(NULL, NULL, NULL, NULL);
@@ -160,6 +153,8 @@ class ExpireHistoryTest : public testing::Test,
archived_db_.reset();
thumb_db_.reset();
text_db_.reset();
+ TopSites::DeleteTopSites(top_sites_);
+ file_util::Delete(dir_, true);
}
// BroadcastNotificationDelegate implementation.
@@ -314,13 +309,11 @@ bool ExpireHistoryTest::HasFavIcon(FavIconID favicon_id) {
}
bool ExpireHistoryTest::HasThumbnail(URLID url_id) {
- // TODO(sky): fix this. This test isn't really valid for TopSites. For
- // TopSites we should be checking URL always, not the id.
URLRow info;
if (!main_db_->GetURLRow(url_id, &info))
return false;
GURL url = info.url();
- scoped_refptr<RefCountedBytes> data;
+ RefCountedBytes *data;
return top_sites_->GetPageThumbnail(url, &data);
}
@@ -357,8 +350,7 @@ void ExpireHistoryTest::EnsureURLInfoGone(const URLRow& row) {
EXPECT_EQ(0U, visits.size());
// Thumbnail should be gone.
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_FALSE(HasThumbnail(row.id()));
+ EXPECT_FALSE(HasThumbnail(row.id()));
// Check the notifications. There should be a delete notification with this
// URL in it. There should also be a "typed URL changed" notification if the
@@ -447,8 +439,7 @@ TEST_F(ExpireHistoryTest, FLAKY_DeleteURLAndFavicon) {
URLRow last_row;
ASSERT_TRUE(main_db_->GetURLRow(url_ids[2], &last_row));
EXPECT_TRUE(HasFavIcon(last_row.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(url_ids[2]));
+ EXPECT_TRUE(HasThumbnail(url_ids[2]));
VisitVector visits;
main_db_->GetVisitsForURL(url_ids[2], &visits);
@@ -461,14 +452,14 @@ TEST_F(ExpireHistoryTest, FLAKY_DeleteURLAndFavicon) {
visits[0].visit_time);
// Compute the text DB filename.
- FilePath fts_filename = path().Append(
+ FilePath fts_filename = dir_.Append(
TextDatabase::IDToFileName(text_db_->TimeToID(visit_times[3])));
// When checking the file, the database must be closed. We then re-initialize
// it just like the test set-up did.
text_db_.reset();
EXPECT_TRUE(IsStringInFile(fts_filename, "goats"));
- text_db_.reset(new TextDatabaseManager(path(),
+ text_db_.reset(new TextDatabaseManager(dir_,
main_db_.get(), main_db_.get()));
ASSERT_TRUE(text_db_->Init(NULL));
expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(),
@@ -481,7 +472,7 @@ TEST_F(ExpireHistoryTest, FLAKY_DeleteURLAndFavicon) {
// doesn't remove it from the file, we want to be sure we're doing the latter.
text_db_.reset();
EXPECT_FALSE(IsStringInFile(fts_filename, "goats"));
- text_db_.reset(new TextDatabaseManager(path(),
+ text_db_.reset(new TextDatabaseManager(dir_,
main_db_.get(), main_db_.get()));
ASSERT_TRUE(text_db_->Init(NULL));
expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(),
@@ -509,8 +500,7 @@ TEST_F(ExpireHistoryTest, DeleteURLWithoutFavicon) {
URLRow last_row;
ASSERT_TRUE(main_db_->GetURLRow(url_ids[1], &last_row));
EXPECT_TRUE(HasFavIcon(last_row.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(url_ids[1]));
+ EXPECT_TRUE(HasThumbnail(url_ids[1]));
VisitVector visits;
main_db_->GetVisitsForURL(url_ids[1], &visits);
@@ -556,8 +546,7 @@ TEST_F(ExpireHistoryTest, DontDeleteStarredURL) {
ASSERT_EQ(0U, visits.size());
// Should still have the thumbnail.
- // TODO(sky): fix this, see comment in HasThumbnail.
- // ASSERT_TRUE(HasThumbnail(url_row.id()));
+ ASSERT_TRUE(HasThumbnail(url_row.id()));
// Unstar the URL and delete again.
bookmark_model_.SetURLStarred(url, string16(), false);
@@ -615,8 +604,7 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsUnstarred) {
// Verify that the middle URL's favicon and thumbnail is still there.
EXPECT_TRUE(HasFavIcon(url_row1.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(url_row1.id()));
+ EXPECT_TRUE(HasThumbnail(url_row1.id()));
// Verify that the last URL was deleted.
EnsureURLInfoGone(url_row2);
@@ -672,14 +660,12 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsUnstarredRestricted) {
// Verify that the middle URL's favicon and thumbnail is still there.
EXPECT_TRUE(HasFavIcon(url_row1.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(url_row1.id()));
+ EXPECT_TRUE(HasThumbnail(url_row1.id()));
// Verify that the last URL was not touched.
EXPECT_TRUE(main_db_->GetURLRow(url_ids[2], &temp_row));
EXPECT_TRUE(HasFavIcon(url_row2.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(url_row2.id()));
+ EXPECT_TRUE(HasThumbnail(url_row2.id()));
}
// Expire a starred URL, it shouldn't get deleted
@@ -720,11 +706,9 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsStarred) {
// exists in history, this should not be a privacy problem, we only update
// the visit counts in this case for consistency anyway.
EXPECT_TRUE(HasFavIcon(new_url_row1.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(new_url_row1.id()));
+ EXPECT_TRUE(HasThumbnail(new_url_row1.id()));
EXPECT_TRUE(HasFavIcon(new_url_row2.favicon_id()));
- // TODO(sky): fix this, see comment in HasThumbnail.
- // EXPECT_TRUE(HasThumbnail(new_url_row2.id()));
+ EXPECT_TRUE(HasThumbnail(new_url_row2.id()));
}
TEST_F(ExpireHistoryTest, ArchiveHistoryBeforeUnstarred) {
diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc
index 238985c..91323c3 100644
--- a/chrome/browser/history/history.cc
+++ b/chrome/browser/history/history.cc
@@ -770,19 +770,12 @@ void HistoryService::OnDBLoaded() {
NotificationService::current()->Notify(NotificationType::HISTORY_LOADED,
Source<Profile>(profile_),
Details<HistoryService>(this));
- if (profile_ && history::TopSites::IsEnabled()) {
- // TopSites may be null during testing.
- history::TopSites* ts = profile_->GetTopSites();
- if (ts)
- ts->HistoryLoaded();
- }
}
void HistoryService::StartTopSitesMigration() {
if (history::TopSites::IsEnabled()) {
history::TopSites* ts = profile_->GetTopSites();
- if (ts)
- ts->MigrateFromHistory();
+ ts->StartMigration();
}
}
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index 00577bb..fb8e3d3 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -581,9 +581,12 @@ void HistoryBackend::InitImpl(const std::string& languages) {
// Thumbnail database.
thumbnail_db_.reset(new ThumbnailDatabase());
- if (history::TopSites::IsEnabled() && !db_->GetNeedsThumbnailMigration()) {
+ if (history::TopSites::IsEnabled()) {
+ // TODO(sky): once we reenable top sites this needs to be fixed.
+ // if (!db_->needs_version_18_migration()) {
// No convertion needed - use new filename right away.
- thumbnail_name = GetFaviconsFileName();
+ // thumbnail_name = GetFaviconsFileName();
+ // }
}
if (thumbnail_db_->Init(thumbnail_name,
history_publisher_.get()) != sql::INIT_OK) {
@@ -596,9 +599,12 @@ void HistoryBackend::InitImpl(const std::string& languages) {
thumbnail_db_.reset();
}
- if (history::TopSites::IsEnabled() && db_->GetNeedsThumbnailMigration()) {
- VLOG(1) << "Starting TopSites migration";
- delegate_->StartTopSitesMigration();
+ if (history::TopSites::IsEnabled()) {
+ // TODO(sky): fix when reenabling top sites migration.
+ // if (db_->needs_version_18_migration()) {
+ // VLOG(1) << "Starting TopSites migration";
+ // delegate_->StartTopSitesMigration();
+ // }
}
// Archived database.
@@ -1335,16 +1341,6 @@ void HistoryBackend::QueryMostVisitedURLs(
}
MostVisitedURLList* result = &request->value;
- QueryMostVisitedURLsImpl(result_count, days_back, result);
- request->ForwardResult(QueryMostVisitedURLsRequest::TupleType(
- request->handle(), *result));
-}
-
-void HistoryBackend::QueryMostVisitedURLsImpl(int result_count,
- int days_back,
- MostVisitedURLList* result) {
- if (!db_.get())
- return;
ScopedVector<PageUsageData> data;
db_->QuerySegmentUsage(base::Time::Now() -
@@ -1358,6 +1354,9 @@ void HistoryBackend::QueryMostVisitedURLsImpl(int result_count,
MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects);
result->push_back(url);
}
+
+ request->ForwardResult(QueryMostVisitedURLsRequest::TupleType(
+ request->handle(), *result));
}
void HistoryBackend::GetRedirectsFromSpecificVisit(
@@ -1517,19 +1516,6 @@ void HistoryBackend::GetPageThumbnailDirectly(
}
}
-void HistoryBackend::MigrateThumbnailsDatabase() {
- // If there is no History DB, we can't record that the migration was done.
- // It will be recorded on the next run.
- if (db_.get()) {
- // If there is no thumbnail DB, we can still record a successful migration.
- if (thumbnail_db_.get()) {
- thumbnail_db_->RenameAndDropThumbnails(GetThumbnailFileName(),
- GetFaviconsFileName());
- }
- db_->ThumbnailMigrationDone();
- }
-}
-
bool HistoryBackend::GetThumbnailFromOlderRedirect(
const GURL& page_url,
std::vector<unsigned char>* data) {
@@ -2163,4 +2149,17 @@ BookmarkService* HistoryBackend::GetBookmarkService() {
return bookmark_service_;
}
+void HistoryBackend::MigrateThumbnailsDatabase() {
+ // If there is no History DB, we can't record that the migration was done.
+ // It will be recorded on the next run.
+ if (db_.get()) {
+ // If there is no thumbnail DB, we can still record a successful migration.
+ if (thumbnail_db_.get()) {
+ thumbnail_db_->RenameAndDropThumbnails(GetThumbnailFileName(),
+ GetFaviconsFileName());
+ }
+ db_->MigrationToTopSitesDone();
+ }
+}
+
} // namespace history
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h
index 54cbf29..3a5cea3 100644
--- a/chrome/browser/history/history_backend.h
+++ b/chrome/browser/history/history_backend.h
@@ -162,11 +162,6 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
int result_count,
int days_back);
- // QueryMostVisitedURLs without the request.
- void QueryMostVisitedURLsImpl(int result_count,
- int days_back,
- MostVisitedURLList* result);
-
// Computes the most recent URL(s) that the given canonical URL has
// redirected to and returns true on success. There may be more than one
// redirect in a row, so this function will fill the given array with the
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc
index ad16e9c..70760bd 100644
--- a/chrome/browser/history/history_backend_unittest.cc
+++ b/chrome/browser/history/history_backend_unittest.cc
@@ -139,8 +139,7 @@ class HistoryBackendTest : public testing::Test {
backend_->Init(std::string(), false);
}
virtual void TearDown() {
- if (backend_.get())
- backend_->Closing();
+ backend_->Closing();
backend_ = NULL;
mem_backend_.reset();
file_util::Delete(test_dir_, true);
@@ -793,8 +792,6 @@ TEST_F(HistoryBackendTest, RemoveVisitsSource) {
// Test for migration of adding visit_source table.
TEST_F(HistoryBackendTest, MigrationVisitSource) {
ASSERT_TRUE(backend_.get());
- backend_->Closing();
- backend_ = NULL;
FilePath old_history_path;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &old_history_path));
@@ -809,12 +806,11 @@ TEST_F(HistoryBackendTest, MigrationVisitSource) {
FilePath new_history_file = new_history_path.Append(chrome::kHistoryFilename);
ASSERT_TRUE(file_util::CopyFile(old_history_path, new_history_file));
+ backend_->Closing();
backend_ = new HistoryBackend(new_history_path,
new HistoryBackendTestDelegate(this),
&bookmark_model_);
backend_->Init(std::string(), false);
- backend_->Closing();
- backend_ = NULL;
// Now the database should already be migrated.
// Check version first.
diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc
index 3e03504..56ee054 100644
--- a/chrome/browser/history/history_database.cc
+++ b/chrome/browser/history/history_database.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -10,16 +10,15 @@
#include "app/sql/transaction.h"
#include "base/command_line.h"
#include "base/file_util.h"
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#endif
#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "chrome/browser/diagnostics/sqlite_diagnostics.h"
#include "chrome/common/chrome_switches.h"
-#if defined(OS_MACOSX)
-#include "base/mac_util.h"
-#endif
-
namespace history {
namespace {
@@ -27,14 +26,10 @@ namespace {
// Current version number. We write databases at the "current" version number,
// but any previous version that can read the "compatible" one can make do with
// or database without *too* many bad effects.
-static const int kCurrentVersionNumber = 20;
+static const int kCurrentVersionNumber = 19;
static const int kCompatibleVersionNumber = 16;
static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
-// Key in the meta table used to determine if we need to migrate thumbnails out
-// of history.
-static const char kNeedsThumbnailMigrationKey[] = "needs_thumbnail_migration";
-
void ComputeDatabaseMetrics(const FilePath& history_name,
sql::Connection& db) {
if (base::RandInt(1, 100) != 50)
@@ -178,16 +173,6 @@ void HistoryDatabase::Vacuum() {
db_.Execute("VACUUM");
}
-void HistoryDatabase::ThumbnailMigrationDone() {
- meta_table_.SetValue(kNeedsThumbnailMigrationKey, 0);
-}
-
-bool HistoryDatabase::GetNeedsThumbnailMigration() {
- int value = 0;
- return (meta_table_.GetValue(kNeedsThumbnailMigrationKey, &value) &&
- value != 0);
-}
-
bool HistoryDatabase::SetSegmentID(VisitID visit_id, SegmentID segment_id) {
sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
"UPDATE visits SET segment_id = ? WHERE id = ?"));
@@ -304,14 +289,6 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion(
meta_table_.SetVersionNumber(cur_version);
}
- if (cur_version == 19) {
- cur_version++;
- meta_table_.SetVersionNumber(cur_version);
- // Set a key indicating we need to migrate thumbnails. When successfull the
- // key is removed (ThumbnailMigrationDone).
- meta_table_.SetValue(kNeedsThumbnailMigrationKey, 1);
- }
-
// When the version is too old, we just try to continue anyway, there should
// not be a released product that makes a database too old for us to handle.
LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
@@ -345,4 +322,8 @@ void HistoryDatabase::MigrateTimeEpoch() {
}
#endif
+void HistoryDatabase::MigrationToTopSitesDone() {
+ // TODO(sky): implement me.
+}
+
} // namespace history
diff --git a/chrome/browser/history/history_database.h b/chrome/browser/history/history_database.h
index 1f0c219..fe74e89 100644
--- a/chrome/browser/history/history_database.h
+++ b/chrome/browser/history/history_database.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -123,11 +123,8 @@ class HistoryDatabase : public DownloadDatabase,
return needs_version_17_migration_;
}
- // Marks the database as no longer needing migration.
- void ThumbnailMigrationDone();
-
- // Returns true if thumbnails needs to be migrated.
- bool GetNeedsThumbnailMigration();
+ // Update the database version after the TopSites migration.
+ void MigrationToTopSitesDone();
// Visit table functions ----------------------------------------------------
diff --git a/chrome/browser/history/history_types.cc b/chrome/browser/history/history_types.cc
index eebe5a7..408bb93 100644
--- a/chrome/browser/history/history_types.cc
+++ b/chrome/browser/history/history_types.cc
@@ -366,7 +366,4 @@ HistoryAddPageArgs* HistoryAddPageArgs::Clone() const {
visit_source, did_replace_entry);
}
-MostVisitedThumbnails::MostVisitedThumbnails() {
-}
-
} // namespace history
diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h
index 536064a..831c0b0 100644
--- a/chrome/browser/history/history_types.h
+++ b/chrome/browser/history/history_types.h
@@ -544,6 +544,20 @@ struct MostVisitedURL {
}
};
+// Used by TopSites to store the thumbnails.
+struct Images {
+ Images();
+ ~Images();
+
+ scoped_refptr<RefCountedBytes> thumbnail;
+ ThumbnailScore thumbnail_score;
+
+ // TODO(brettw): this will eventually store the favicon.
+ // scoped_refptr<RefCountedBytes> favicon;
+};
+
+typedef std::vector<MostVisitedURL> MostVisitedURLList;
+
// Navigation -----------------------------------------------------------------
// Marshalling structure for AddPage.
@@ -584,61 +598,6 @@ class HistoryAddPageArgs
DISALLOW_COPY_AND_ASSIGN(HistoryAddPageArgs);
};
-// TopSites -------------------------------------------------------------------
-
-typedef std::vector<MostVisitedURL> MostVisitedURLList;
-
-// Used by TopSites to store the thumbnails.
-struct Images {
- Images();
- ~Images();
-
- scoped_refptr<RefCountedBytes> thumbnail;
- ThumbnailScore thumbnail_score;
-
- // TODO(brettw): this will eventually store the favicon.
- // scoped_refptr<RefCountedBytes> favicon;
-};
-
-typedef std::vector<MostVisitedURL> MostVisitedURLList;
-
-struct MostVisitedURLWithRank {
- MostVisitedURL url;
- int rank;
-};
-
-typedef std::vector<MostVisitedURLWithRank> MostVisitedURLWithRankList;
-
-struct TopSitesDelta {
- MostVisitedURLList deleted;
- MostVisitedURLWithRankList added;
- MostVisitedURLWithRankList moved;
-};
-
-typedef std::map<GURL, scoped_refptr<RefCountedBytes> > URLToThumbnailMap;
-
-// Used when migrating most visited thumbnails out of history and into topsites.
-struct ThumbnailMigration {
- MostVisitedURLList most_visited;
- URLToThumbnailMap url_to_thumbnail_map;
-};
-
-typedef std::map<GURL, Images> URLToImagesMap;
-
-class MostVisitedThumbnails
- : public base::RefCountedThreadSafe<MostVisitedThumbnails> {
- public:
- MostVisitedThumbnails();
-
- MostVisitedURLList most_visited;
- URLToImagesMap url_to_images_map;
-
- private:
- friend class base::RefCountedThreadSafe<MostVisitedThumbnails>;
-
- DISALLOW_COPY_AND_ASSIGN(MostVisitedThumbnails);
-};
-
} // namespace history
#endif // CHROME_BROWSER_HISTORY_HISTORY_TYPES_H_
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index e615876..9cd3f9c 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -310,6 +310,7 @@ bool ThumbnailDatabase::GetPageThumbnail(URLID id,
bool ThumbnailDatabase::DeleteThumbnail(URLID id) {
if (use_top_sites_) {
+ LOG(WARNING) << "Use TopSites instead.";
return true; // Not possible after migration to TopSites.
}
diff --git a/chrome/browser/history/top_sites.cc b/chrome/browser/history/top_sites.cc
index 887471d..31ce4ac 100644
--- a/chrome/browser/history/top_sites.cc
+++ b/chrome/browser/history/top_sites.cc
@@ -5,10 +5,10 @@
#include "chrome/browser/history/top_sites.h"
#include <algorithm>
-#include <set>
#include "app/l10n_util.h"
#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/md5.h"
#include "base/string_util.h"
@@ -16,17 +16,14 @@
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/dom_ui/most_visited_handler.h"
-#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/page_usage_data.h"
-#include "chrome/browser/history/top_sites_backend.h"
-#include "chrome/browser/history/top_sites_cache.h"
+#include "chrome/browser/history/top_sites_database.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/thumbnail_score.h"
#include "gfx/codec/jpeg_codec.h"
@@ -47,89 +44,14 @@ static const int64 kUpdateIntervalSecs = 15;
static const int64 kMinUpdateIntervalMinutes = 1;
static const int64 kMaxUpdateIntervalMinutes = 60;
-// IDs of the sites we force into top sites.
-static const int kPrepopulatePageIDs[] =
- { IDS_CHROME_WELCOME_URL, IDS_THEMES_GALLERY_URL };
-
-// Favicons of the sites we force into top sites.
-static const char kPrepopulateFaviconURLs[][54] =
- { "chrome://theme/IDR_NEWTAB_CHROME_WELCOME_PAGE_FAVICON",
- "chrome://theme/IDR_NEWTAB_THEMES_GALLERY_FAVICON" };
-
-static const int kPrepopulateTitleIDs[] =
- { IDS_NEW_TAB_CHROME_WELCOME_PAGE_TITLE,
- IDS_NEW_TAB_THEMES_GALLERY_PAGE_TITLE };
-
-namespace {
-
-// HistoryDBTask used during migration of thumbnails from history to top sites.
-// When run on the history thread it collects the top sites and the
-// corresponding thumbnails. When run back on the ui thread it calls into
-// TopSites::FinishHistoryMigration.
-class LoadThumbnailsFromHistoryTask : public HistoryDBTask {
- public:
- LoadThumbnailsFromHistoryTask(TopSites* top_sites,
- int result_count)
- : top_sites_(top_sites),
- result_count_(result_count) {
- // l10n_util isn't thread safe, so cache for use on the db thread.
- ignore_urls_.insert(l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL));
- ignore_urls_.insert(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL));
- }
-
- virtual bool RunOnDBThread(history::HistoryBackend* backend,
- history::HistoryDatabase* db) {
- // Get the most visited urls.
- backend->QueryMostVisitedURLsImpl(result_count_,
- kDaysOfHistory,
- &data_.most_visited);
-
- // And fetch the thumbnails.
- for (size_t i = 0; i < data_.most_visited.size(); ++i) {
- const GURL& url = data_.most_visited[i].url;
- if (ShouldFetchThumbnailFor(url)) {
- scoped_refptr<RefCountedBytes> data;
- backend->GetPageThumbnailDirectly(url, &data);
- data_.url_to_thumbnail_map[url] = data;
- }
- }
- return true;
- }
-
- virtual void DoneRunOnMainThread() {
- top_sites_->FinishHistoryMigration(data_);
- }
-
- private:
- bool ShouldFetchThumbnailFor(const GURL& url) {
- return ignore_urls_.find(url.spec()) == ignore_urls_.end();
- }
-
- // Set of URLs we don't load thumbnails for. This is created on the UI thread
- // and used on the history thread.
- std::set<std::string> ignore_urls_;
- scoped_refptr<TopSites> top_sites_;
-
- // Number of results to request from history.
- const int result_count_;
-
- ThumbnailMigration data_;
-
- DISALLOW_COPY_AND_ASSIGN(LoadThumbnailsFromHistoryTask);
-};
-
-} // namespace
-
-TopSites::TopSites(Profile* profile)
- : backend_(new TopSitesBackend()),
- cache_(new TopSitesCache()),
- thread_safe_cache_(new TopSitesCache()),
- profile_(profile),
- last_num_urls_changed_(0),
- blacklist_(NULL),
- pinned_urls_(NULL),
- state_(WAITING_FOR_HISTORY_TO_LOAD) {
+TopSites::TopSites(Profile* profile) : profile_(profile),
+ mock_history_service_(NULL),
+ last_num_urls_changed_(0),
+ migration_in_progress_(false),
+ waiting_for_results_(true),
+ blacklist_(NULL),
+ pinned_urls_(NULL) {
if (!profile_)
return;
@@ -148,29 +70,61 @@ TopSites::TopSites(Profile* profile)
// static
bool TopSites::IsEnabled() {
- std::string switch_value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kEnableTopSites);
- return switch_value.empty() || switch_value == "true";
+ return CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableTopSites);
+}
+
+TopSites::~TopSites() {
+ timer_.Stop();
}
void TopSites::Init(const FilePath& db_name) {
- backend_->Init(db_name);
- // Wait for history to finish so that we know if we need to migrate or can
- // read directly from top sites db.
+ db_path_ = db_name;
+ db_.reset(new TopSitesDatabaseImpl());
+ if (!db_->Init(db_name)) {
+ NOTREACHED() << "Failed to initialize database.";
+ return;
+ }
+
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, NewRunnableMethod(
+ this, &TopSites::ReadDatabase));
+
+ // Start the one-shot timer.
+ timer_.Start(base::TimeDelta::FromSeconds(kUpdateIntervalSecs), this,
+ &TopSites::StartQueryForMostVisited);
+}
+
+void TopSites::ReadDatabase() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ std::map<GURL, Images> thumbnails;
+
+ DCHECK(db_.get());
+ MostVisitedURLList top_urls;
+ db_->GetPageThumbnails(&top_urls, &thumbnails);
+ MostVisitedURLList copy(top_urls); // StoreMostVisited destroys the list.
+ StoreMostVisited(&top_urls);
+ if (AddPrepopulatedPages(&copy))
+ UpdateMostVisited(copy);
+
+ AutoLock lock(lock_);
+ for (size_t i = 0; i < top_sites_.size(); i++) {
+ GURL url = top_sites_[i].url;
+ Images thumbnail = thumbnails[url];
+ if (thumbnail.thumbnail.get() && thumbnail.thumbnail->size()) {
+ SetPageThumbnailNoDB(url, thumbnail.thumbnail,
+ thumbnail.thumbnail_score);
+ }
+ }
}
+// Public function that encodes the bitmap into RefCountedBytes and
+// updates the database.
bool TopSites::SetPageThumbnail(const GURL& url,
const SkBitmap& thumbnail,
const ThumbnailScore& score) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (state_ != LOADED)
- return false; // Ignore thumbnails until we're loaded.
-
+ AutoLock lock(lock_);
bool add_temp_thumbnail = false;
- if (!cache_->IsKnownURL(url)) {
- if (cache_->top_sites().size() < kTopSitesNumber) {
+ if (canonical_urls_.find(url) == canonical_urls_.end()) {
+ if (top_sites_.size() < kTopSitesNumber) {
add_temp_thumbnail = true;
} else {
return false; // This URL is not known to us.
@@ -180,8 +134,15 @@ bool TopSites::SetPageThumbnail(const GURL& url,
if (!HistoryService::CanAddURL(url))
return false; // It's not a real webpage.
- scoped_refptr<RefCountedBytes> thumbnail_data;
- if (!EncodeBitmap(thumbnail, &thumbnail_data))
+ scoped_refptr<RefCountedBytes> thumbnail_data = new RefCountedBytes;
+ SkAutoLockPixels thumbnail_lock(thumbnail);
+ bool encoded = gfx::JPEGCodec::Encode(
+ reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)),
+ gfx::JPEGCodec::FORMAT_SkBitmap, thumbnail.width(),
+ thumbnail.height(),
+ static_cast<int>(thumbnail.rowBytes()), 90,
+ &thumbnail_data->data);
+ if (!encoded)
return false;
if (add_temp_thumbnail) {
@@ -192,237 +153,59 @@ bool TopSites::SetPageThumbnail(const GURL& url,
return SetPageThumbnailEncoded(url, thumbnail_data, score);
}
-void TopSites::GetMostVisitedURLs(CancelableRequestConsumer* consumer,
- GetTopSitesCallback* callback) {
- // WARNING: this may be invoked on any thread.
- scoped_refptr<CancelableRequest<GetTopSitesCallback> > request(
- new CancelableRequest<GetTopSitesCallback>(callback));
- // This ensures cancelation of requests when either the consumer or the
- // provider is deleted. Deletion of requests is also guaranteed.
- AddRequest(request, consumer);
- MostVisitedURLList filtered_urls;
- {
- AutoLock lock(lock_);
- if (state_ != LOADED) {
- // A request came in before we finished loading. Put the request in
- // pending_callbacks_ and we'll notify it when we finish loading.
- pending_callbacks_.insert(request);
- return;
- }
-
- filtered_urls = thread_safe_cache_->top_sites();
- }
- request->ForwardResult(GetTopSitesCallback::TupleType(filtered_urls));
-}
-
-bool TopSites::GetPageThumbnail(const GURL& url,
- scoped_refptr<RefCountedBytes>* bytes) {
- // WARNING: this may be invoked on any thread.
- AutoLock lock(lock_);
- return thread_safe_cache_->GetPageThumbnail(url, bytes);
-}
-
-// Returns the index of |url| in |urls|, or -1 if not found.
-static int IndexOf(const MostVisitedURLList& urls, const GURL& url) {
- for (size_t i = 0; i < urls.size(); i++) {
- if (urls[i].url == url)
- return i;
- }
- return -1;
-}
-
-void TopSites::MigrateFromHistory() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- DCHECK(state_ == WAITING_FOR_HISTORY_TO_LOAD);
- state_ = MIGRATING;
- profile_->GetHistoryService(Profile::EXPLICIT_ACCESS)->ScheduleDBTask(
- new LoadThumbnailsFromHistoryTask(
- this,
- num_results_to_request_from_history()),
- &cancelable_consumer_);
- MigratePinnedURLs();
-}
-
-void TopSites::FinishHistoryMigration(const ThumbnailMigration& data) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(state_ == MIGRATING);
-
- SetTopSites(data.most_visited);
-
- for (size_t i = 0; i < data.most_visited.size(); ++i) {
- URLToThumbnailMap::const_iterator image_i =
- data.url_to_thumbnail_map.find(data.most_visited[i].url);
- if (image_i != data.url_to_thumbnail_map.end()) {
- SetPageThumbnailEncoded(data.most_visited[i].url,
- image_i->second,
- ThumbnailScore());
- }
- }
-
- MoveStateToLoaded();
-
- ResetThreadSafeImageCache();
-
- // We've scheduled all the thumbnails and top sites to be written to the top
- // sites db, but it hasn't happened yet. Schedule a request on the db thread
- // that notifies us when done. When done we'll know everything was written and
- // we can tell history to finish its part of migration.
- backend_->DoEmptyRequest(
- &cancelable_consumer_,
- NewCallback(this, &TopSites::OnHistoryMigrationWrittenToDisk));
-}
-
-void TopSites::HistoryLoaded() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (state_ == WAITING_FOR_HISTORY_TO_LOAD) {
- state_ = READING_FROM_DB;
- backend_->GetMostVisitedThumbnails(
- &cancelable_consumer_,
- NewCallback(this, &TopSites::OnGotMostVisitedThumbnails));
- } else {
- DCHECK(state_ == MIGRATING);
- }
-}
-
-bool TopSites::HasBlacklistedItems() const {
- return !blacklist_->empty();
-}
-
-void TopSites::AddBlacklistedURL(const GURL& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- RemovePinnedURL(url);
- Value* dummy = Value::CreateNullValue();
- blacklist_->SetWithoutPathExpansion(GetURLHash(url), dummy);
-
- ResetThreadSafeCache();
-}
-
-void TopSites::RemoveBlacklistedURL(const GURL& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- blacklist_->RemoveWithoutPathExpansion(GetURLHash(url), NULL);
- ResetThreadSafeCache();
-}
-
-bool TopSites::IsBlacklisted(const GURL& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return blacklist_->HasKey(GetURLHash(url));
-}
-
-void TopSites::ClearBlacklistedURLs() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- blacklist_->Clear();
- ResetThreadSafeCache();
-}
-
-void TopSites::AddPinnedURL(const GURL& url, size_t pinned_index) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- GURL old;
- if (GetPinnedURLAtIndex(pinned_index, &old))
- RemovePinnedURL(old);
-
- if (IsURLPinned(url))
- RemovePinnedURL(url);
-
- Value* index = Value::CreateIntegerValue(pinned_index);
- pinned_urls_->SetWithoutPathExpansion(GetURLString(url), index);
-
- ResetThreadSafeCache();
-}
-
-bool TopSites::IsURLPinned(const GURL& url) {
- int tmp;
- return pinned_urls_->GetIntegerWithoutPathExpansion(GetURLString(url), &tmp);
-}
-
-void TopSites::RemovePinnedURL(const GURL& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- pinned_urls_->RemoveWithoutPathExpansion(GetURLString(url), NULL);
-
- ResetThreadSafeCache();
-}
-
-bool TopSites::GetPinnedURLAtIndex(size_t index, GURL* url) {
- for (DictionaryValue::key_iterator it = pinned_urls_->begin_keys();
- it != pinned_urls_->end_keys(); ++it) {
- int current_index;
- if (pinned_urls_->GetIntegerWithoutPathExpansion(*it, &current_index)) {
- if (static_cast<size_t>(current_index) == index) {
- *url = GURL(*it);
- return true;
- }
- }
- }
- return false;
-}
-
-void TopSites::Shutdown() {
- profile_ = NULL;
- // Cancel all requests so that the service doesn't callback to us after we've
- // invoked Shutdown (this could happen if we have a pending request and
- // Shutdown is invoked).
- cancelable_consumer_.CancelAllRequests();
- backend_->Shutdown();
-}
-
-// static
-void TopSites::DiffMostVisited(const MostVisitedURLList& old_list,
- const MostVisitedURLList& new_list,
- TopSitesDelta* delta) {
- // Add all the old URLs for quick lookup. This maps URLs to the corresponding
- // index in the input.
- std::map<GURL, size_t> all_old_urls;
- for (size_t i = 0; i < old_list.size(); i++)
- all_old_urls[old_list[i].url] = i;
+bool TopSites::SetPageThumbnailEncoded(const GURL& url,
+ const RefCountedBytes* thumbnail,
+ const ThumbnailScore& score) {
+ lock_.AssertAcquired();
+ if (!SetPageThumbnailNoDB(url, thumbnail, score))
+ return false;
- // Check all the URLs in the new set to see which ones are new or just moved.
- // When we find a match in the old set, we'll reset its index to our special
- // marker. This allows us to quickly identify the deleted ones in a later
- // pass.
- const size_t kAlreadyFoundMarker = static_cast<size_t>(-1);
- for (size_t i = 0; i < new_list.size(); i++) {
- std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url);
- if (found == all_old_urls.end()) {
- MostVisitedURLWithRank added;
- added.url = new_list[i];
- added.rank = i;
- delta->added.push_back(added);
- } else {
- if (found->second != i) {
- MostVisitedURLWithRank moved;
- moved.url = new_list[i];
- moved.rank = i;
- delta->moved.push_back(moved);
- }
- found->second = kAlreadyFoundMarker;
- }
- }
+ // Update the database.
+ if (!db_.get())
+ return true;
+ std::map<GURL, size_t>::iterator found = canonical_urls_.find(url);
+ if (found == canonical_urls_.end())
+ return false;
+ size_t index = found->second;
- // Any member without the special marker in the all_old_urls list means that
- // there wasn't a "new" URL that mapped to it, so it was deleted.
- for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin();
- i != all_old_urls.end(); ++i) {
- if (i->second != kAlreadyFoundMarker)
- delta->deleted.push_back(old_list[i->second]);
- }
+ MostVisitedURL& most_visited = top_sites_[index];
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, NewRunnableMethod(
+ this, &TopSites::WriteThumbnailToDB,
+ most_visited, index, top_images_[most_visited.url]));
+ return true;
}
-TopSites::~TopSites() {
+void TopSites::WriteThumbnailToDB(const MostVisitedURL& url,
+ int url_rank,
+ const Images& thumbnail) {
+ DCHECK(db_.get());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ db_->SetPageThumbnail(url, url_rank, thumbnail);
}
+// private
bool TopSites::SetPageThumbnailNoDB(const GURL& url,
const RefCountedBytes* thumbnail_data,
const ThumbnailScore& score) {
- // This should only be invoked when we know about the url.
- DCHECK(cache_->IsKnownURL(url));
+ lock_.AssertAcquired();
+
+ std::map<GURL, size_t>::iterator found = canonical_urls_.find(url);
+ if (found == canonical_urls_.end()) {
+ if (top_sites_.size() >= kTopSitesNumber)
+ return false; // This URL is not known to us.
- const MostVisitedURL& most_visited =
- cache_->top_sites()[cache_->GetURLIndex(url)];
- Images* image = cache_->GetImage(url);
+ // We don't have enough Top Sites - add this one too.
+ MostVisitedURL mv;
+ mv.url = url;
+ mv.redirects.push_back(url);
+ top_sites_.push_back(mv);
+ size_t index = top_sites_.size() - 1;
+ StoreRedirectChain(top_sites_[index].redirects, index);
+ found = canonical_urls_.find(url);
+ }
+
+ MostVisitedURL& most_visited = top_sites_[found->second];
+ Images& image = top_images_[most_visited.url];
// When comparing the thumbnail scores, we need to take into account the
// redirect hops, which are not generated when the thumbnail is because the
@@ -431,127 +214,95 @@ bool TopSites::SetPageThumbnailNoDB(const GURL& url,
new_score_with_redirects.redirect_hops_from_dest =
GetRedirectDistanceForURL(most_visited, url);
- if (!ShouldReplaceThumbnailWith(image->thumbnail_score,
+ if (!ShouldReplaceThumbnailWith(image.thumbnail_score,
new_score_with_redirects) &&
- image->thumbnail.get())
+ image.thumbnail.get())
return false; // The one we already have is better.
- image->thumbnail = const_cast<RefCountedBytes*>(thumbnail_data);
- image->thumbnail_score = new_score_with_redirects;
-
- ResetThreadSafeImageCache();
- return true;
-}
-
-bool TopSites::SetPageThumbnailEncoded(const GURL& url,
- const RefCountedBytes* thumbnail,
- const ThumbnailScore& score) {
- if (!SetPageThumbnailNoDB(url, thumbnail, score))
- return false;
-
- // Update the database.
- if (!cache_->IsKnownURL(url))
- return false;
+ // Take ownership of the thumbnail data.
+ image.thumbnail = const_cast<RefCountedBytes*>(thumbnail_data);
+ image.thumbnail_score = new_score_with_redirects;
- size_t index = cache_->GetURLIndex(url);
- const MostVisitedURL& most_visited = cache_->top_sites()[index];
- backend_->SetPageThumbnail(most_visited,
- index,
- *(cache_->GetImage(most_visited.url)));
return true;
}
-// static
-bool TopSites::EncodeBitmap(const SkBitmap& bitmap,
- scoped_refptr<RefCountedBytes>* bytes) {
- *bytes = new RefCountedBytes();
- SkAutoLockPixels bitmap_lock(bitmap);
- return gfx::JPEGCodec::Encode(
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
- gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(),
- bitmap.height(),
- static_cast<int>(bitmap.rowBytes()), 90,
- &((*bytes)->data));
-}
-
-void TopSites::AddTemporaryThumbnail(const GURL& url,
- const RefCountedBytes* thumbnail,
- const ThumbnailScore& score) {
- Images& img = temp_thumbnails_map_[url];
- img.thumbnail = const_cast<RefCountedBytes*>(thumbnail);
- img.thumbnail_score = score;
-}
-
-void TopSites::StartQueryForMostVisited() {
- if (!profile_)
- return;
+void TopSites::GetMostVisitedURLs(CancelableRequestConsumer* consumer,
+ GetTopSitesCallback* callback) {
+ scoped_refptr<CancelableRequest<GetTopSitesCallback> > request(
+ new CancelableRequest<GetTopSitesCallback>(callback));
+ // This ensures cancelation of requests when either the consumer or the
+ // provider is deleted. Deletion of requests is also guaranteed.
+ AddRequest(request, consumer);
+ MostVisitedURLList filtered_urls;
+ {
+ AutoLock lock(lock_);
+ if (waiting_for_results_) {
+ // A request came in before we have any top sites.
+ // We have to keep track of the requests ourselves.
+ pending_callbacks_.insert(request);
+ return;
+ }
+ if (request->canceled())
+ return;
- HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
- // |hs| may be null during unit tests.
- if (hs) {
- hs->QueryMostVisitedURLs(
- num_results_to_request_from_history(),
- kDaysOfHistory,
- &cancelable_consumer_,
- NewCallback(this, &TopSites::OnTopSitesAvailableFromHistory));
+ ApplyBlacklistAndPinnedURLs(top_sites_, &filtered_urls);
}
+ request->ForwardResult(GetTopSitesCallback::TupleType(filtered_urls));
}
-// static
-int TopSites::GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
- const GURL& url) {
- for (size_t i = 0; i < most_visited.redirects.size(); i++) {
- if (most_visited.redirects[i] == url)
- return static_cast<int>(most_visited.redirects.size() - i - 1);
+bool TopSites::GetPageThumbnail(const GURL& url, RefCountedBytes** data) const {
+ AutoLock lock(lock_);
+ std::map<GURL, Images>::const_iterator found =
+ top_images_.find(GetCanonicalURL(url));
+ if (found == top_images_.end()) {
+ found = temp_thumbnails_map_.find(url);
+ if (found == temp_thumbnails_map_.end())
+ return false; // No thumbnail for this URL.
}
- NOTREACHED() << "URL should always be found.";
- return 0;
-}
-
-void TopSites::OnMigrationDone() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!profile_)
- return;
- HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
- // |hs| may be null during unit tests.
- if (!hs)
- return;
- hs->OnTopSitesReady();
+ Images image = found->second;
+ *data = image.thumbnail.get();
+ return true;
}
-// static
-MostVisitedURLList TopSites::GetPrepopulatePages() {
- MostVisitedURLList urls;
- urls.resize(arraysize(kPrepopulatePageIDs));
- for (size_t i = 0; i < arraysize(kPrepopulatePageIDs); ++i) {
- MostVisitedURL& url = urls[i];
- url.url = GURL(l10n_util::GetStringUTF8(kPrepopulatePageIDs[i]));
- url.redirects.push_back(url.url);
- url.favicon_url = GURL(kPrepopulateFaviconURLs[i]);
- url.title = l10n_util::GetStringUTF16(kPrepopulateTitleIDs[i]);
+static int IndexOf(const MostVisitedURLList& urls, const GURL& url) {
+ for (size_t i = 0; i < urls.size(); i++) {
+ if (urls[i].url == url)
+ return i;
}
- return urls;
+ return -1;
}
-// static
bool TopSites::AddPrepopulatedPages(MostVisitedURLList* urls) {
+ // TODO(arv): This needs to get the data from some configurable place.
+ // http://crbug.com/17630
bool added = false;
- MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
- for (size_t i = 0; i < prepopulate_urls.size(); ++i) {
- if (urls->size() < kTopSitesNumber &&
- IndexOf(*urls, prepopulate_urls[i].url) == -1) {
- urls->push_back(prepopulate_urls[i]);
- added = true;
- }
+ GURL welcome_url(l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL));
+ if (urls->size() < kTopSitesNumber && IndexOf(*urls, welcome_url) == -1) {
+ MostVisitedURL url(
+ welcome_url,
+ GURL("chrome://theme/IDR_NEWTAB_CHROME_WELCOME_PAGE_FAVICON"),
+ l10n_util::GetStringUTF16(IDS_NEW_TAB_CHROME_WELCOME_PAGE_TITLE));
+ url.redirects.push_back(welcome_url);
+ urls->push_back(url);
+ added = true;
+ }
+
+ GURL themes_url(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL));
+ if (urls->size() < kTopSitesNumber && IndexOf(*urls, themes_url) == -1) {
+ MostVisitedURL url(
+ themes_url,
+ GURL("chrome://theme/IDR_NEWTAB_THEMES_GALLERY_FAVICON"),
+ l10n_util::GetStringUTF16(IDS_NEW_TAB_THEMES_GALLERY_PAGE_TITLE));
+ url.redirects.push_back(themes_url);
+ urls->push_back(url);
+ added = true;
}
+
return added;
}
void TopSites::MigratePinnedURLs() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
std::map<GURL, size_t> tmp_map;
for (DictionaryValue::key_iterator it = pinned_urls_->begin_keys();
it != pinned_urls_->end_keys(); ++it) {
@@ -576,6 +327,7 @@ void TopSites::MigratePinnedURLs() {
void TopSites::ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls,
MostVisitedURLList* out) {
+ lock_.AssertAcquired();
MostVisitedURLList urls_copy;
for (size_t i = 0; i < urls.size(); i++) {
if (!IsBlacklisted(urls[i].url))
@@ -623,223 +375,521 @@ void TopSites::ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls,
}
std::string TopSites::GetURLString(const GURL& url) {
- return cache_->GetCanonicalURL(url).spec();
+ lock_.AssertAcquired();
+ return GetCanonicalURL(url).spec();
}
std::string TopSites::GetURLHash(const GURL& url) {
+ lock_.AssertAcquired();
// We don't use canonical URLs here to be able to blacklist only one of
// the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'.
return MD5String(url.spec());
}
-base::TimeDelta TopSites::GetUpdateDelay() {
- if (cache_->top_sites().size() <= arraysize(kPrepopulateTitleIDs))
- return base::TimeDelta::FromSeconds(30);
+void TopSites::UpdateMostVisited(MostVisitedURLList most_visited) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes;
- int64 minutes = kMaxUpdateIntervalMinutes -
- last_num_urls_changed_ * range / cache_->top_sites().size();
- return base::TimeDelta::FromMinutes(minutes);
-}
+ std::vector<size_t> added; // Indices into most_visited.
+ std::vector<size_t> deleted; // Indices into top_sites_.
+ std::vector<size_t> moved; // Indices into most_visited.
-// static
-void TopSites::ProcessPendingCallbacks(PendingCallbackSet pending_callbacks,
- const MostVisitedURLList& urls) {
- PendingCallbackSet::iterator i;
- for (i = pending_callbacks.begin();
- i != pending_callbacks.end(); ++i) {
- scoped_refptr<CancelableRequest<GetTopSitesCallback> > request = *i;
- if (!request->canceled())
- request->ForwardResult(GetTopSitesCallback::TupleType(urls));
- }
- pending_callbacks.clear();
-}
+ DiffMostVisited(top_sites_, most_visited, &added, &deleted, &moved);
-void TopSites::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (state_ != LOADED)
- return;
+ // #added == #deleted; #added + #moved = total.
+ last_num_urls_changed_ = added.size() + moved.size();
- if (type == NotificationType::HISTORY_URLS_DELETED) {
- Details<history::URLsDeletedDetails> deleted_details(details);
- if (deleted_details->all_history) {
- SetTopSites(MostVisitedURLList());
- backend_->ResetDatabase();
- } else {
- std::set<size_t> indices_to_delete; // Indices into top_sites_.
- for (std::set<GURL>::iterator i = deleted_details->urls.begin();
- i != deleted_details->urls.end(); ++i) {
- if (cache_->IsKnownURL(*i))
- indices_to_delete.insert(cache_->GetURLIndex(*i));
- }
+ {
+ AutoLock lock(lock_);
- if (indices_to_delete.empty())
- return;
+ // Process the diff: delete from images and disk, add to disk.
+ // Delete all the thumbnails associated with URLs that were deleted.
+ for (size_t i = 0; i < deleted.size(); i++) {
+ const MostVisitedURL& deleted_url = top_sites_[deleted[i]];
+ std::map<GURL, Images>::iterator found =
+ top_images_.find(deleted_url.url);
+ if (found != top_images_.end())
+ top_images_.erase(found);
+ }
+ }
- MostVisitedURLList new_top_sites(cache_->top_sites());
- for (std::set<size_t>::reverse_iterator i = indices_to_delete.rbegin();
- i != indices_to_delete.rend(); i++) {
- size_t index = *i;
- RemovePinnedURL(new_top_sites[index].url);
- new_top_sites.erase(new_top_sites.begin() + index);
- }
- SetTopSites(new_top_sites);
+ // Write the updates to the DB.
+ if (db_.get()) {
+ for (size_t i = 0; i < deleted.size(); i++) {
+ const MostVisitedURL& deleted_url = top_sites_[deleted[i]];
+ if (db_.get())
+ db_->RemoveURL(deleted_url);
}
- StartQueryForMostVisited();
- } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
- if (cache_->top_sites().size() < kTopSitesNumber) {
- NavigationController::LoadCommittedDetails* load_details =
- Details<NavigationController::LoadCommittedDetails>(details).ptr();
- if (!load_details)
- return;
- const GURL& url = load_details->entry->url();
- if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) {
- // Ideally we would just invoke StartQueryForMostVisited, but at the
- // time this is invoked history hasn't been updated, which means if we
- // invoked StartQueryForMostVisited now we could get stale data.
- RestartQueryForTopSitesTimer(base::TimeDelta::FromMilliseconds(1));
+ for (size_t i = 0; i < added.size(); i++) {
+ const MostVisitedURL& added_url = most_visited[added[i]];
+ db_->SetPageThumbnail(added_url, added[i], Images());
+ }
+ for (size_t i = 0; i < moved.size(); i++) {
+ const MostVisitedURL& moved_url = most_visited[moved[i]];
+ db_->UpdatePageRank(moved_url, moved[i]);
+ }
+ }
+
+ StoreMostVisited(&most_visited);
+ if (migration_in_progress_) {
+ // Copy all thumnbails from the history service.
+ for (size_t i = 0; i < top_sites_.size(); i++) {
+ GURL& url = top_sites_[i].url;
+ Images& img = top_images_[url];
+ if (!img.thumbnail.get() || !img.thumbnail->size()) {
+ StartQueryForThumbnail(i);
}
}
}
+
+ // If we are not expecting any thumbnails, migration is done.
+ if (migration_in_progress_ && migration_pending_urls_.empty())
+ OnMigrationDone();
+
+ timer_.Stop();
+ timer_.Start(GetUpdateDelay(), this,
+ &TopSites::StartQueryForMostVisited);
}
-void TopSites::SetTopSites(const MostVisitedURLList& new_top_sites) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void TopSites::OnMigrationDone() {
+ migration_in_progress_ = false;
+ if (!profile_)
+ return;
- MostVisitedURLList top_sites(new_top_sites);
- AddPrepopulatedPages(&top_sites);
+ HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ // |hs| may be null during unit tests.
+ if (!hs)
+ return;
+ hs->OnTopSitesReady();
+}
- TopSitesDelta delta;
- DiffMostVisited(cache_->top_sites(), top_sites, &delta);
- if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty())
- backend_->UpdateTopSites(delta);
+void TopSites::AddTemporaryThumbnail(const GURL& url,
+ const RefCountedBytes* thumbnail,
+ const ThumbnailScore& score) {
+ Images& img = temp_thumbnails_map_[url];
+ img.thumbnail = const_cast<RefCountedBytes*>(thumbnail);
+ img.thumbnail_score = score;
+}
- last_num_urls_changed_ = delta.added.size() + delta.moved.size();
+void TopSites::StartQueryForThumbnail(size_t index) {
+ DCHECK(migration_in_progress_);
+ if (top_sites_[index].url.spec() ==
+ l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL) ||
+ top_sites_[index].url.spec() ==
+ l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL))
+ return; // Don't need thumbnails for prepopulated URLs.
- // We always do the following steps (setting top sites in cache, and resetting
- // thread safe cache ...) as this method is invoked during startup at which
- // point the caches haven't been updated yet.
- cache_->SetTopSites(top_sites);
+ migration_pending_urls_.insert(top_sites_[index].url);
- // See if we have any tmp thumbnails for the new sites.
- if (!temp_thumbnails_map_.empty()) {
- for (size_t i = 0; i < top_sites.size(); ++i) {
- const MostVisitedURL& mv = top_sites[i];
- GURL canonical_url = cache_->GetCanonicalURL(mv.url);
- for (std::map<GURL, Images>::iterator it = temp_thumbnails_map_.begin();
- it != temp_thumbnails_map_.end(); ++it) {
+ if (mock_history_service_) {
+ // Testing with a mockup.
+ // QueryMostVisitedURLs is not virtual, so we have to duplicate the code.
+ // This calls SetClientData.
+ mock_history_service_->GetPageThumbnail(
+ top_sites_[index].url,
+ &cancelable_consumer_,
+ NewCallback(this, &TopSites::OnThumbnailAvailable),
+ index);
+ return;
+ }
+
+ if (!profile_)
+ return;
+
+ HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ // |hs| may be null during unit tests.
+ if (!hs)
+ return;
+ HistoryService::Handle handle =
+ hs->GetPageThumbnail(top_sites_[index].url,
+ &cancelable_consumer_,
+ NewCallback(this, &TopSites::OnThumbnailAvailable));
+ cancelable_consumer_.SetClientData(hs, handle, index);
+}
+
+void TopSites::GenerateCanonicalURLs() {
+ lock_.AssertAcquired();
+ canonical_urls_.clear();
+ for (size_t i = 0; i < top_sites_.size(); i++) {
+ const MostVisitedURL& mv = top_sites_[i];
+ StoreRedirectChain(mv.redirects, i);
+ }
+}
+
+void TopSites::StoreMostVisited(MostVisitedURLList* most_visited) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ MostVisitedURLList filtered_urls;
+ PendingCallbackSet callbacks;
+ {
+ AutoLock lock(lock_);
+ top_sites_.clear();
+ // Take ownership of the most visited data.
+ top_sites_.swap(*most_visited);
+ waiting_for_results_ = false;
+
+ // Save the redirect information for quickly mapping to the canonical URLs.
+ GenerateCanonicalURLs();
+
+ for (size_t i = 0; i < top_sites_.size(); i++) {
+ const MostVisitedURL& mv = top_sites_[i];
+ std::map<GURL, Images>::iterator it = temp_thumbnails_map_.begin();
+ GURL canonical_url = GetCanonicalURL(mv.url);
+ for (; it != temp_thumbnails_map_.end(); it++) {
// Must map all temp URLs to canonical ones.
// temp_thumbnails_map_ contains non-canonical URLs, because
// when we add a temp thumbnail, redirect chain is not known.
// This is slow, but temp_thumbnails_map_ should have very few URLs.
- if (canonical_url == cache_->GetCanonicalURL(it->first)) {
- SetPageThumbnailEncoded(mv.url,
- it->second.thumbnail,
+ if (canonical_url == GetCanonicalURL(it->first)) {
+ SetPageThumbnailEncoded(mv.url, it->second.thumbnail,
it->second.thumbnail_score);
temp_thumbnails_map_.erase(it);
break;
}
}
}
- }
+ if (top_sites_.size() >= kTopSitesNumber)
+ temp_thumbnails_map_.clear();
- if (top_sites.size() >= kTopSitesNumber)
- temp_thumbnails_map_.clear();
+ if (pending_callbacks_.empty())
+ return;
- ResetThreadSafeCache();
- ResetThreadSafeImageCache();
+ ApplyBlacklistAndPinnedURLs(top_sites_, &filtered_urls);
+ callbacks.swap(pending_callbacks_);
+ } // lock_ is released.
+ // Process callbacks outside the lock - ForwardResults may cause
+ // thread switches.
+ ProcessPendingCallbacks(callbacks, filtered_urls);
+}
+
+void TopSites::StoreRedirectChain(const RedirectList& redirects,
+ size_t destination) {
+ lock_.AssertAcquired();
+ if (redirects.empty()) {
+ NOTREACHED();
+ return;
+ }
- // Restart the timer that queries history for top sites. This is done to
- // ensure we stay in sync with history.
- RestartQueryForTopSitesTimer(GetUpdateDelay());
+ // Map all the redirected URLs to the destination.
+ for (size_t i = 0; i < redirects.size(); i++) {
+ // If this redirect is already known, don't replace it with a new one.
+ if (canonical_urls_.find(redirects[i]) == canonical_urls_.end())
+ canonical_urls_[redirects[i]] = destination;
+ }
}
-int TopSites::num_results_to_request_from_history() const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+GURL TopSites::GetCanonicalURL(const GURL& url) const {
+ lock_.AssertAcquired();
+ std::map<GURL, size_t>::const_iterator found = canonical_urls_.find(url);
+ if (found == canonical_urls_.end())
+ return url; // Unknown URL - return unchanged.
+ return top_sites_[found->second].url;
+}
- return kTopSitesNumber + blacklist_->size();
+// static
+int TopSites::GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
+ const GURL& url) {
+ for (size_t i = 0; i < most_visited.redirects.size(); i++) {
+ if (most_visited.redirects[i] == url)
+ return static_cast<int>(most_visited.redirects.size() - i - 1);
+ }
+ NOTREACHED() << "URL should always be found.";
+ return 0;
}
-void TopSites::MoveStateToLoaded() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+// static
+void TopSites::DiffMostVisited(const MostVisitedURLList& old_list,
+ const MostVisitedURLList& new_list,
+ std::vector<size_t>* added_urls,
+ std::vector<size_t>* deleted_urls,
+ std::vector<size_t>* moved_urls) {
+ added_urls->clear();
+ deleted_urls->clear();
+ moved_urls->clear();
- MostVisitedURLList filtered_urls;
- PendingCallbackSet pending_callbacks;
- {
- AutoLock lock(lock_);
+ // Add all the old URLs for quick lookup. This maps URLs to the corresponding
+ // index in the input.
+ std::map<GURL, size_t> all_old_urls;
+ for (size_t i = 0; i < old_list.size(); i++)
+ all_old_urls[old_list[i].url] = i;
+
+ // Check all the URLs in the new set to see which ones are new or just moved.
+ // When we find a match in the old set, we'll reset its index to our special
+ // marker. This allows us to quickly identify the deleted ones in a later
+ // pass.
+ const size_t kAlreadyFoundMarker = static_cast<size_t>(-1);
+ for (size_t i = 0; i < new_list.size(); i++) {
+ std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url);
+ if (found == all_old_urls.end()) {
+ added_urls->push_back(i);
+ } else {
+ if (found->second != i)
+ moved_urls->push_back(i);
+ found->second = kAlreadyFoundMarker;
+ }
+ }
- DCHECK(state_ != LOADED);
- state_ = LOADED;
+ // Any member without the special marker in the all_old_urls list means that
+ // there wasn't a "new" URL that mapped to it, so it was deleted.
+ for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin();
+ i != all_old_urls.end(); ++i) {
+ if (i->second != kAlreadyFoundMarker)
+ deleted_urls->push_back(i->second);
+ }
+}
- if (!pending_callbacks_.empty()) {
- filtered_urls = thread_safe_cache_->top_sites();
- pending_callbacks.swap(pending_callbacks_);
+void TopSites::StartQueryForMostVisited() {
+ if (mock_history_service_) {
+ // Testing with a mockup.
+ // QueryMostVisitedURLs is not virtual, so we have to duplicate the code.
+ mock_history_service_->QueryMostVisitedURLs(
+ kTopSitesNumber + blacklist_->size(),
+ kDaysOfHistory,
+ &cancelable_consumer_,
+ NewCallback(this, &TopSites::OnTopSitesAvailable));
+ } else {
+ if (!profile_)
+ return;
+
+ HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ // |hs| may be null during unit tests.
+ if (hs) {
+ hs->QueryMostVisitedURLs(
+ kTopSitesNumber + blacklist_->size(),
+ kDaysOfHistory,
+ &cancelable_consumer_,
+ NewCallback(this, &TopSites::OnTopSitesAvailable));
+ } else {
+ VLOG(1) << "History Service not available.";
}
}
+}
- ProcessPendingCallbacks(pending_callbacks, filtered_urls);
+void TopSites::StartMigration() {
+ VLOG(1) << "Starting migration to TopSites.";
+ migration_in_progress_ = true;
+ StartQueryForMostVisited();
+ MigratePinnedURLs();
+}
- NotificationService::current()->Notify(NotificationType::TOP_SITES_LOADED,
- Source<Profile>(profile_),
- Details<TopSites>(this));
+bool TopSites::HasBlacklistedItems() const {
+ AutoLock lock(lock_);
+ return !blacklist_->empty();
}
-void TopSites::ResetThreadSafeCache() {
+void TopSites::AddBlacklistedURL(const GURL& url) {
AutoLock lock(lock_);
- MostVisitedURLList cached;
- ApplyBlacklistAndPinnedURLs(cache_->top_sites(), &cached);
- thread_safe_cache_->SetTopSites(cached);
+ RemovePinnedURLLocked(url);
+ Value* dummy = Value::CreateNullValue();
+ blacklist_->SetWithoutPathExpansion(GetURLHash(url), dummy);
+}
+
+bool TopSites::IsBlacklisted(const GURL& url) {
+ lock_.AssertAcquired();
+ bool result = blacklist_->HasKey(GetURLHash(url));
+ return result;
}
-void TopSites::ResetThreadSafeImageCache() {
+void TopSites::RemoveBlacklistedURL(const GURL& url) {
AutoLock lock(lock_);
- thread_safe_cache_->SetThumbnails(cache_->images());
- thread_safe_cache_->RemoveUnreferencedThumbnails();
+ blacklist_->RemoveWithoutPathExpansion(GetURLHash(url), NULL);
}
-void TopSites::RestartQueryForTopSitesTimer(base::TimeDelta delta) {
- timer_.Stop();
- timer_.Start(delta, this, &TopSites::StartQueryForMostVisited);
+void TopSites::ClearBlacklistedURLs() {
+ blacklist_->Clear();
}
-void TopSites::OnHistoryMigrationWrittenToDisk(TopSitesBackend::Handle handle) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void TopSites::AddPinnedURL(const GURL& url, size_t pinned_index) {
+ GURL old;
+ if (GetPinnedURLAtIndex(pinned_index, &old)) {
+ RemovePinnedURL(old);
+ }
- if (!profile_)
- return;
+ if (IsURLPinned(url)) {
+ RemovePinnedURL(url);
+ }
- HistoryService* history =
- profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
- if (history)
- history->OnTopSitesReady();
+ Value* index = Value::CreateIntegerValue(pinned_index);
+ AutoLock lock(lock_);
+ pinned_urls_->SetWithoutPathExpansion(GetURLString(url), index);
}
-void TopSites::OnGotMostVisitedThumbnails(
- CancelableRequestProvider::Handle handle,
- scoped_refptr<MostVisitedThumbnails> data) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state_, READING_FROM_DB);
+void TopSites::RemovePinnedURL(const GURL& url) {
+ AutoLock lock(lock_);
+ RemovePinnedURLLocked(url);
+}
+
+void TopSites::RemovePinnedURLLocked(const GURL& url) {
+ lock_.AssertAcquired();
+ pinned_urls_->RemoveWithoutPathExpansion(GetURLString(url), NULL);
+}
+
+bool TopSites::IsURLPinned(const GURL& url) {
+ AutoLock lock(lock_);
+ int tmp;
+ bool result = pinned_urls_->GetIntegerWithoutPathExpansion(
+ GetURLString(url), &tmp);
+ return result;
+}
+
+bool TopSites::GetPinnedURLAtIndex(size_t index, GURL* url) {
+ for (DictionaryValue::key_iterator it = pinned_urls_->begin_keys();
+ it != pinned_urls_->end_keys(); ++it) {
+ int current_index;
+ if (pinned_urls_->GetIntegerWithoutPathExpansion(*it, &current_index)) {
+ if (static_cast<size_t>(current_index) == index) {
+ *url = GURL(*it);
+ return true;
+ }
+ }
+ }
+ return false;
+}
- // Set the top sites directly in the cache so that SetTopSites diffs
- // correctly.
- cache_->SetTopSites(data->most_visited);
- SetTopSites(data->most_visited);
- cache_->SetThumbnails(data->url_to_images_map);
+// static
+void TopSites::DeleteTopSites(scoped_refptr<TopSites>& ptr) {
+ if (!ptr.get() || !MessageLoop::current())
+ return;
+ if (BrowserThread::IsWellKnownThread(BrowserThread::UI)) {
+ ptr = NULL;
+ } else {
+ // Need to roll our own UI thread.
+ BrowserThread ui_loop(BrowserThread::UI, MessageLoop::current());
+ ptr = NULL;
+ MessageLoop::current()->RunAllPending();
+ }
+}
- ResetThreadSafeImageCache();
+void TopSites::ClearProfile() {
+ profile_ = NULL;
+}
- MoveStateToLoaded();
+base::TimeDelta TopSites::GetUpdateDelay() {
+ AutoLock lock(lock_);
+ if (top_sites_.size() == 0)
+ return base::TimeDelta::FromSeconds(30);
- // Start a timer that refreshes top sites from history.
- RestartQueryForTopSitesTimer(
- base::TimeDelta::FromSeconds(kUpdateIntervalSecs));
+ int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes;
+ int64 minutes = kMaxUpdateIntervalMinutes -
+ last_num_urls_changed_ * range / top_sites_.size();
+ return base::TimeDelta::FromMinutes(minutes);
}
-void TopSites::OnTopSitesAvailableFromHistory(
+void TopSites::OnTopSitesAvailable(
CancelableRequestProvider::Handle handle,
MostVisitedURLList pages) {
- SetTopSites(pages);
+ AddPrepopulatedPages(&pages);
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, NewRunnableMethod(
+ this, &TopSites::UpdateMostVisited, pages));
+}
+
+// static
+void TopSites::ProcessPendingCallbacks(PendingCallbackSet pending_callbacks,
+ const MostVisitedURLList& urls) {
+ PendingCallbackSet::iterator i;
+ for (i = pending_callbacks.begin();
+ i != pending_callbacks.end(); ++i) {
+ scoped_refptr<CancelableRequest<GetTopSitesCallback> > request = *i;
+ if (!request->canceled())
+ request->ForwardResult(GetTopSitesCallback::TupleType(urls));
+ }
+ pending_callbacks.clear();
+}
+
+void TopSites::OnThumbnailAvailable(CancelableRequestProvider::Handle handle,
+ scoped_refptr<RefCountedBytes> thumbnail) {
+ size_t index;
+ if (mock_history_service_) {
+ index = handle;
+ } else {
+ if (!profile_)
+ return;
+
+ HistoryService* hs = profile_ ->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ if (!hs)
+ return;
+ index = cancelable_consumer_.GetClientData(hs, handle);
+ }
+ DCHECK(static_cast<size_t>(index) < top_sites_.size());
+
+ if (migration_in_progress_)
+ migration_pending_urls_.erase(top_sites_[index].url);
+
+ if (thumbnail.get() && thumbnail->size()) {
+ const MostVisitedURL& url = top_sites_[index];
+ AutoLock lock(lock_);
+ SetPageThumbnailEncoded(url.url, thumbnail, ThumbnailScore());
+ }
+
+ if (migration_in_progress_ && migration_pending_urls_.empty() &&
+ !mock_history_service_)
+ OnMigrationDone();
+}
+
+void TopSites::SetMockHistoryService(MockHistoryService* mhs) {
+ mock_history_service_ = mhs;
+}
+
+void TopSites::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ AutoLock lock(lock_);
+ if (type == NotificationType::HISTORY_URLS_DELETED) {
+ Details<history::URLsDeletedDetails> deleted_details(details);
+ if (deleted_details->all_history) {
+ top_sites_.clear();
+ BrowserThread::PostTask(
+ BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(this, &TopSites::ResetDatabase));
+ } else {
+ std::set<size_t> indices_to_delete; // Indices into top_sites_.
+ std::set<GURL>::iterator it;
+ for (it = deleted_details->urls.begin();
+ it != deleted_details->urls.end(); ++it) {
+ std::map<GURL,size_t>::const_iterator found = canonical_urls_.find(*it);
+ if (found != canonical_urls_.end())
+ indices_to_delete.insert(found->second);
+ }
+
+ for (std::set<size_t>::reverse_iterator i = indices_to_delete.rbegin();
+ i != indices_to_delete.rend(); i++) {
+ size_t index = *i;
+ RemovePinnedURLLocked(top_sites_[index].url);
+ top_sites_.erase(top_sites_.begin() + index);
+ }
+ }
+ // Canonical URLs are not valid any more.
+ GenerateCanonicalURLs();
+ StartQueryForMostVisited();
+ } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
+ if (top_sites_.size() < kTopSitesNumber) {
+ NavigationController::LoadCommittedDetails* load_details =
+ Details<NavigationController::LoadCommittedDetails>(details).ptr();
+ if (!load_details)
+ return;
+ GURL url = load_details->entry->url();
+ if (canonical_urls_.find(url) == canonical_urls_.end() &&
+ HistoryService::CanAddURL(url)) {
+ // Add this page to the known pages in case the thumbnail comes
+ // in before we get the results.
+ MostVisitedURL mv;
+ mv.url = url;
+ mv.redirects.push_back(url);
+ top_sites_.push_back(mv);
+ size_t index = top_sites_.size() - 1;
+ StoreRedirectChain(top_sites_[index].redirects, index);
+ }
+ StartQueryForMostVisited();
+ }
+ }
+}
+
+void TopSites::ResetDatabase() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ db_.reset(new TopSitesDatabaseImpl());
+ file_util::Delete(db_path_, false);
+ if (!db_->Init(db_path_)) {
+ NOTREACHED() << "Failed to initialize database.";
+ return;
+ }
}
} // namespace history
diff --git a/chrome/browser/history/top_sites.h b/chrome/browser/history/top_sites.h
index 1290cff..f080c05 100644
--- a/chrome/browser/history/top_sites.h
+++ b/chrome/browser/history/top_sites.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -27,26 +27,30 @@
#include "googleurl/src/gurl.h"
class DictionaryValue;
-class FilePath;
class SkBitmap;
class Profile;
namespace history {
-class TopSitesCache;
class TopSitesBackend;
+class TopSitesDatabase;
class TopSitesTest;
+typedef std::vector<MostVisitedURL> MostVisitedURLList;
+
// Stores the data for the top "most visited" sites. This includes a cache of
// the most visited data from history, as well as the corresponding thumbnails
// of those sites.
//
-// This class allows requests for most visited urls and thumbnails on any
-// thread. All other methods must be invoked on the UI thread. All mutations
-// to internal state happen on the UI thread and are scheduled to update the
-// db using TopSitesBackend.
+// This class IS threadsafe. It is designed to be used from the UI thread of
+// the browser (where history requests must be kicked off and received from)
+// and from the I/O thread (where new tab page requests come in). Handling the
+// new tab page requests on the I/O thread without proxying to the UI thread is
+// a nontrivial performance win, especially when the browser is starting and
+// the UI thread is busy.
class TopSites :
- public base::RefCountedThreadSafe<TopSites>,
+ public base::RefCountedThreadSafe<TopSites,
+ BrowserThread::DeleteOnUIThread>,
public NotificationObserver,
public CancelableRequestProvider {
public:
@@ -55,6 +59,21 @@ class TopSites :
// Returns whether top sites is enabled.
static bool IsEnabled();
+ class MockHistoryService {
+ // A mockup of a HistoryService used for testing TopSites.
+ public:
+ virtual HistoryService::Handle QueryMostVisitedURLs(
+ int result_count, int days_back,
+ CancelableRequestConsumerBase* consumer,
+ HistoryService::QueryMostVisitedURLsCallback* callback) = 0;
+ virtual ~MockHistoryService() {}
+ virtual void GetPageThumbnail(
+ const GURL& page_url,
+ CancelableRequestConsumerTSimple<size_t>* consumer,
+ HistoryService::ThumbnailDataCallback* callback,
+ size_t index) = 0;
+ };
+
// Initializes TopSites.
void Init(const FilePath& db_name);
@@ -71,27 +90,18 @@ class TopSites :
PendingCallbackSet;
// Returns a list of most visited URLs via a callback.
- // This may be invoked on any thread.
// NOTE: the callback may be called immediately if we have the data cached.
void GetMostVisitedURLs(CancelableRequestConsumer* consumer,
GetTopSitesCallback* callback);
// Get a thumbnail for a given page. Returns true iff we have the thumbnail.
- // This may be invoked on any thread.
- // As this method may be invoked on any thread the ref count needs to be
- // upped before this method returns, so this takes a scoped_refptr*.
- bool GetPageThumbnail(const GURL& url,
- scoped_refptr<RefCountedBytes>* bytes);
+ bool GetPageThumbnail(const GURL& url, RefCountedBytes** data) const;
- // Start reading thumbnails from the ThumbnailDatabase.
- void MigrateFromHistory();
+ // For testing with a HistoryService mock.
+ void SetMockHistoryService(MockHistoryService* mhs);
- // Invoked with data from migrating thumbnails out of history.
- void FinishHistoryMigration(const ThumbnailMigration& data);
-
- // Invoked from history when it finishes loading. If MigrateFromHistory was
- // not invoked at this point then we load from the top sites service.
- void HistoryLoaded();
+ // Start reading thumbnails from the ThumbnailDatabase.
+ void StartMigration();
// Blacklisted URLs
@@ -104,9 +114,6 @@ class TopSites :
// Removes a URL from the blacklist.
void RemoveBlacklistedURL(const GURL& url);
- // Returns true if the URL is blacklisted.
- bool IsBlacklisted(const GURL& url);
-
// Clear the blacklist.
void ClearBlacklistedURLs();
@@ -125,39 +132,34 @@ class TopSites :
// is a URL pinned at |index|.
bool GetPinnedURLAtIndex(size_t index, GURL* out);
- // Shuts down top sites.
- void Shutdown();
+ // TopSites must be deleted on a UI thread. This happens
+ // automatically in a real browser, but in unit_tests we don't have
+ // a real UI thread. Use this function to delete a TopSites object.
+ static void DeleteTopSites(scoped_refptr<TopSites>& ptr);
- // Generates the diff of things that happened between "old" and "new."
- //
- // The URLs that are in "new" but not "old" will be have their index into
- // "new" put in |added_urls|. The URLs that are in "old" but not "new" will
- // have their index into "old" put into |deleted_urls|.
- //
- // URLs appearing in both old and new lists but having different indices will
- // have their index into "new" be put into |moved_urls|.
- static void DiffMostVisited(const MostVisitedURLList& old_list,
- const MostVisitedURLList& new_list,
- TopSitesDelta* delta);
+ // Sets the profile pointer to NULL. This is for the case where
+ // TopSites outlives the profile, since TopSites is refcounted.
+ void ClearProfile();
private:
- friend class base::RefCountedThreadSafe<TopSites>;
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
+ friend class DeleteTask<TopSites>;
friend class TopSitesTest;
-
- // Enumeration of the possible states we can be in.
- enum LoadState {
- // Initial state. We wait for history to load to know if we need to migrate.
- WAITING_FOR_HISTORY_TO_LOAD,
-
- // We're migrating thumbnails from history to top sites.
- MIGRATING,
-
- // Waiting on data from top sites.
- READING_FROM_DB,
-
- // Finished loading.
- LOADED
- };
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, GetMostVisited);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, RealDatabase);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, MockDatabase);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, DeleteNotifications);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, PinnedURLsDeleted);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, GetUpdateDelay);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, Migration);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, QueueingRequestsForTopSites);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, CancelingRequestsForTopSites);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, AddTemporaryThumbnail);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, Blacklisting);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, PinnedURLs);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, BlacklistingAndPinnedURLs);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, AddPrepopulatedPages);
+ FRIEND_TEST_ALL_PREFIXES(TopSitesTest, GetPageThumbnail);
~TopSites();
@@ -174,131 +176,176 @@ class TopSites :
const RefCountedBytes* thumbnail,
const ThumbnailScore& score);
- // Encodes the bitmap to bytes for storage to the db. Returns true if the
- // bitmap was successfully encoded.
- static bool EncodeBitmap(const SkBitmap& bitmap,
- scoped_refptr<RefCountedBytes>* bytes);
-
- // Add a thumbnail for an unknown url. See temp_thumbnails_map_.
- void AddTemporaryThumbnail(const GURL& url,
- const RefCountedBytes* thumbnail,
- const ThumbnailScore& score);
-
// Query history service for the list of available thumbnails.
void StartQueryForMostVisited();
- // Finds the given URL in the redirect chain for the given TopSite, and
- // returns the distance from the destination in hops that the given URL is.
- // The URL is assumed to be in the list. The destination is 0.
- static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
- const GURL& url);
+ // Query history service for the thumbnail for a given url. |index|
+ // is the index into top_sites_.
+ void StartQueryForThumbnail(size_t index);
- // Called after TopSites completes migration.
- void OnMigrationDone();
+ // Called when history service returns a list of top URLs.
+ void OnTopSitesAvailable(CancelableRequestProvider::Handle handle,
+ MostVisitedURLList data);
- // Returns the set of prepopulate pages.
- static MostVisitedURLList GetPrepopulatePages();
+ // Returns a list of urls to each pending callback.
+ static void ProcessPendingCallbacks(PendingCallbackSet pending_callbacks,
+ const MostVisitedURLList& urls);
- // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|.
- // Returns true if any pages were added.
- static bool AddPrepopulatedPages(MostVisitedURLList* urls);
+ // Called when history service returns a thumbnail.
+ void OnThumbnailAvailable(CancelableRequestProvider::Handle handle,
+ scoped_refptr<RefCountedBytes> thumbnail);
- // Convert pinned_urls_ dictionary to the new format. Use URLs as
- // dictionary keys.
- void MigratePinnedURLs();
+ // Sets canonical_urls_ from top_sites_.
+ void GenerateCanonicalURLs();
- // Takes |urls|, produces it's copy in |out| after removing
- // blacklisted URLs and reordering pinned URLs.
- void ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls,
- MostVisitedURLList* out);
+ // Saves the set of the top URLs visited by this user. The 0th item is the
+ // most popular.
+ // DANGER! This will clear all data from the input argument.
+ void StoreMostVisited(MostVisitedURLList* most_visited);
- // Converts a url into a canonical string representation.
- std::string GetURLString(const GURL& url);
+ // Saves the given set of redirects. The redirects are in order of the
+ // given vector, so [0] -> [1] -> [2].
+ void StoreRedirectChain(const RedirectList& redirects,
+ size_t destination);
- // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
- std::string GetURLHash(const GURL& url);
+ // Each item in the most visited view can redirect elsewhere. This returns
+ // the canonical URL one identifying the site if the given URL does appear
+ // in the "top sites" list.
+ //
+ // If the given URL is not in the top sites, this will return an empty GURL.
+ GURL GetCanonicalURL(const GURL& url) const;
- // Returns the delay until the next update of history is needed.
- // Uses num_urls_changed
- base::TimeDelta GetUpdateDelay();
+ // Finds the given URL in the redirect chain for the given TopSite, and
+ // returns the distance from the destination in hops that the given URL is.
+ // The URL is assumed to be in the list. The destination is 0.
+ static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
+ const GURL& url);
- // Executes all of the callbacks in |pending_callbacks|. This is used after
- // we finish loading if any requests came in before we loaded.
- static void ProcessPendingCallbacks(PendingCallbackSet pending_callbacks,
- const MostVisitedURLList& urls);
+ // Generates the diff of things that happened between "old" and "new."
+ //
+ // The URLs that are in "new" but not "old" will be have their index into
+ // "new" put in |added_urls|. The URLs that are in "old" but not "new" will
+ // have their index into "old" put into |deleted_urls|.
+ //
+ // URLs appearing in both old and new lists but having different indices will
+ // have their index into "new" be put into |moved_urls|.
+ static void DiffMostVisited(const MostVisitedURLList& old_list,
+ const MostVisitedURLList& new_list,
+ std::vector<size_t>* added_urls,
+ std::vector<size_t>* deleted_urls,
+ std::vector<size_t>* moved_urls);
// Implementation of NotificationObserver.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
- // Resets top_sites_ and updates the db (in the background). All mutations to
- // top_sites_ *must* go through this.
- void SetTopSites(const MostVisitedURLList& new_top_sites);
+ // Returns true if the URL is blacklisted.
+ bool IsBlacklisted(const GURL& url);
- // Returns the number of most visted results to request from history. This
- // changes depending upon how many urls have been blacklisted.
- int num_results_to_request_from_history() const;
+ // A variant of RemovePinnedURL that must be called within a lock.
+ void RemovePinnedURLLocked(const GURL& url);
- // Invoked when transitioning to LOADED. Notifies any queued up callbacks.
- void MoveStateToLoaded();
+ // Returns the delay until the next update of history is needed.
+ // Uses num_urls_changed
+ base::TimeDelta GetUpdateDelay();
- void ResetThreadSafeCache();
+ // The following methods must be run on the DB thread since they
+ // access the database.
- void ResetThreadSafeImageCache();
+ // Reads the database from disk. Called on startup to get the last
+ // known top sites.
+ void ReadDatabase();
- // Stops and starts timer with a delay of |delta|.
- void RestartQueryForTopSitesTimer(base::TimeDelta delta);
+ // Write a thumbnail to database.
+ void WriteThumbnailToDB(const MostVisitedURL& url,
+ int url_rank,
+ const Images& thumbnail);
- // Callback after TopSitesBackend has finished migration. This tells history
- // to finish it's side of migration (nuking thumbnails on disk).
- void OnHistoryMigrationWrittenToDisk(
- CancelableRequestProvider::Handle handle);
+ // Updates the top sites list and writes the difference to disk.
+ void UpdateMostVisited(MostVisitedURLList most_visited);
- // Callback from TopSites with the top sites/thumbnails.
- void OnGotMostVisitedThumbnails(CancelableRequestProvider::Handle handle,
- scoped_refptr<MostVisitedThumbnails> data);
+ // Deletes the database file, then reinitializes the database.
+ void ResetDatabase();
- // Called when history service returns a list of top URLs.
- void OnTopSitesAvailableFromHistory(CancelableRequestProvider::Handle handle,
- MostVisitedURLList data);
+ // Called after TopSites completes migration.
+ void OnMigrationDone();
- scoped_refptr<TopSitesBackend> backend_;
+ // Add a thumbnail for an unknown url. See temp_thumbnails_map_.
+ void AddTemporaryThumbnail(const GURL& url,
+ const RefCountedBytes* thumbnail,
+ const ThumbnailScore& score);
- // The top sites data.
- scoped_ptr<TopSitesCache> cache_;
+ // Add prepopulated pages: 'welcome to Chrome' and themes gallery.
+ // Returns true if any pages were added.
+ bool AddPrepopulatedPages(MostVisitedURLList* urls);
- // Copy of the top sites data that may be accessed on any thread (assuming
- // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and
- // pinned urls applied (|cache_| does not).
- scoped_ptr<TopSitesCache> thread_safe_cache_;
+ // Convert pinned_urls_ dictionary to the new format. Use URLs as
+ // dictionary keys.
+ void MigratePinnedURLs();
- Profile* profile_;
+ // Takes |urls|, produces it's copy in |out| after removing
+ // blacklisted URLs and reordering pinned URLs.
+ void ApplyBlacklistAndPinnedURLs(const MostVisitedURLList& urls,
+ MostVisitedURLList* out);
- // Lock used to access |thread_safe_cache_|.
+ // Converts a url into a canonical string representation.
+ std::string GetURLString(const GURL& url);
+
+ // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
+ std::string GetURLHash(const GURL& url);
+
+ Profile* profile_;
+ // A mockup to use for testing. If NULL, use the real HistoryService
+ // from the profile_. See SetMockHistoryService.
+ MockHistoryService* mock_history_service_;
+ CancelableRequestConsumerTSimple<size_t> cancelable_consumer_;
mutable Lock lock_;
- CancelableRequestConsumer cancelable_consumer_;
+ // The cached version of the top sites. The 0th item in this vector is the
+ // #1 site.
+ MostVisitedURLList top_sites_;
+
+ // The images corresponding to the top_sites. This is indexed by the URL of
+ // the top site, so this doesn't have to be shuffled around when the ordering
+ // changes of the top sites. Some top_sites_ entries may not have images.
+ std::map<GURL, Images> top_images_;
- // Timer that asks history for the top sites. This is used to make sure our
- // data stays in sync with history.
+ // Generated from the redirects to and from the most visited pages, this
+ // maps the redirects to the index into top_sites_ that contains it.
+ std::map<GURL, size_t> canonical_urls_;
+
+ // Timer for updating TopSites data.
base::OneShotTimer<TopSites> timer_;
+ scoped_ptr<TopSitesDatabase> db_;
+ FilePath db_path_;
+
NotificationRegistrar registrar_;
// The number of URLs changed on the last update.
size_t last_num_urls_changed_;
+ // Are we in the middle of migration from ThumbnailsDatabase to
+ // TopSites?
+ bool migration_in_progress_;
+
+ // URLs for which we are expecting thumbnails.
+ std::set<GURL> migration_pending_urls_;
+
// The map of requests for the top sites list. Can only be
// non-empty at startup. After we read the top sites from the DB, we'll
// always have a cached list.
PendingCallbackSet pending_callbacks_;
+ // Are we waiting for the top sites from HistoryService?
+ bool waiting_for_results_;
+
// Stores thumbnails for unknown pages. When SetPageThumbnail is
// called, if we don't know about that URL yet and we don't have
// enough Top Sites (new profile), we store it until the next
- // SetTopSites call.
- URLToImagesMap temp_thumbnails_map_;
+ // UpdateMostVisitedURLs call.
+ std::map<GURL, Images> temp_thumbnails_map_;
// Blacklisted and pinned URLs are stored in Preferences.
@@ -309,13 +356,12 @@ class TopSites :
// PrefService.
DictionaryValue* blacklist_;
- // This is a dictionary for the pinned URLs for the the most visited part of
- // the new tab page. Key is the URL, value is index where it is pinned at (may
- // be the same as key). This is owned by the PrefService.
+ // This is a dictionary for the pinned URLs for the the most visited
+ // part of the new tab page. Key is the URL, value is
+ // index where it is pinned at (may be the same as key). This is
+ // owned by the PrefService.
DictionaryValue* pinned_urls_;
- LoadState state_;
-
DISALLOW_COPY_AND_ASSIGN(TopSites);
};
diff --git a/chrome/browser/history/top_sites_backend.cc b/chrome/browser/history/top_sites_backend.cc
deleted file mode 100644
index 81ceaf1..0000000
--- a/chrome/browser/history/top_sites_backend.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2010 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/history/top_sites_backend.h"
-
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/history/top_sites_database.h"
-
-namespace history {
-
-TopSitesBackend::TopSitesBackend()
- : db_(new TopSitesDatabaseImpl()) {
-}
-
-void TopSitesBackend::Init(const FilePath& path) {
- db_path_ = path;
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this, &TopSitesBackend::InitDBOnDBThread, path));
-}
-
-void TopSitesBackend::Shutdown() {
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this, &TopSitesBackend::ShutdownDBOnDBThread));
-}
-
-TopSitesBackend::Handle TopSitesBackend::GetMostVisitedThumbnails(
- CancelableRequestConsumerBase* consumer,
- GetMostVisitedThumbnailsCallback* callback) {
- GetMostVisitedThumbnailsRequest* request =
- new GetMostVisitedThumbnailsRequest(callback);
- request->value = new MostVisitedThumbnails;
- AddRequest(request, consumer);
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this,
- &TopSitesBackend::GetMostVisitedThumbnailsOnDBThread,
- scoped_refptr<GetMostVisitedThumbnailsRequest>(request)));
- return request->handle();
-}
-
-void TopSitesBackend::UpdateTopSites(const TopSitesDelta& delta) {
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this, &TopSitesBackend::UpdateTopSitesOnDBThread, delta));
-}
-
-void TopSitesBackend::SetPageThumbnail(const MostVisitedURL& url,
- int url_rank,
- const Images& thumbnail) {
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this, &TopSitesBackend::SetPageThumbnailOnDBThread, url,
- url_rank, thumbnail));
-}
-
-void TopSitesBackend::ResetDatabase() {
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this, &TopSitesBackend::ResetDatabaseOnDBThread, db_path_));
-}
-
-TopSitesBackend::Handle TopSitesBackend::DoEmptyRequest(
- CancelableRequestConsumerBase* consumer,
- EmptyRequestCallback* callback) {
- EmptyRequestRequest* request = new EmptyRequestRequest(callback);
- AddRequest(request, consumer);
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE, NewRunnableMethod(
- this,
- &TopSitesBackend::DoEmptyRequestOnDBThread,
- scoped_refptr<EmptyRequestRequest>(request)));
- return request->handle();
-}
-
-TopSitesBackend::~TopSitesBackend() {
- DCHECK(!db_.get()); // Shutdown should have happened first (which results in
- // nulling out db).
-}
-
-void TopSitesBackend::InitDBOnDBThread(const FilePath& path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- if (!db_->Init(path)) {
- NOTREACHED() << "Failed to initialize database.";
- db_.reset();
- }
-}
-
-void TopSitesBackend::ShutdownDBOnDBThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- db_.reset();
-}
-
-void TopSitesBackend::GetMostVisitedThumbnailsOnDBThread(
- scoped_refptr<GetMostVisitedThumbnailsRequest> request) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-
- if (request->canceled())
- return;
-
- if (db_.get()) {
- db_->GetPageThumbnails(&(request->value->most_visited),
- &(request->value->url_to_images_map));
- }
- request->ForwardResult(GetMostVisitedThumbnailsRequest::TupleType(
- request->handle(),
- request->value));
-}
-
-void TopSitesBackend::UpdateTopSitesOnDBThread(const TopSitesDelta& delta) {
- if (!db_.get())
- return;
-
- for (size_t i = 0; i < delta.deleted.size(); ++i)
- db_->RemoveURL(delta.deleted[i]);
-
- for (size_t i = 0; i < delta.added.size(); ++i)
- db_->SetPageThumbnail(delta.added[i].url, delta.added[i].rank, Images());
-
- for (size_t i = 0; i < delta.moved.size(); ++i)
- db_->UpdatePageRank(delta.moved[i].url, delta.moved[i].rank);
-}
-
-void TopSitesBackend::SetPageThumbnailOnDBThread(const MostVisitedURL& url,
- int url_rank,
- const Images& thumbnail) {
- if (!db_.get())
- return;
-
- db_->SetPageThumbnail(url, url_rank, thumbnail);
-}
-
-void TopSitesBackend::ResetDatabaseOnDBThread(const FilePath& file_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- db_.reset(NULL);
- file_util::Delete(db_path_, false);
- db_.reset(new TopSitesDatabaseImpl());
- InitDBOnDBThread(db_path_);
-}
-
-void TopSitesBackend::DoEmptyRequestOnDBThread(
- scoped_refptr<EmptyRequestRequest> request) {
- request->ForwardResult(EmptyRequestRequest::TupleType(request->handle()));
-}
-
-} // namespace history
diff --git a/chrome/browser/history/top_sites_backend.h b/chrome/browser/history/top_sites_backend.h
deleted file mode 100644
index a992b06..0000000
--- a/chrome/browser/history/top_sites_backend.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2010 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_HISTORY_TOP_SITES_BACKEND_H_
-#define CHROME_BROWSER_HISTORY_TOP_SITES_BACKEND_H_
-#pragma once
-
-#include "base/file_path.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/cancelable_request.h"
-#include "chrome/browser/history/history_types.h"
-
-class FilePath;
-
-namespace history {
-
-class TopSitesDatabase;
-
-// Service used by TopSites to have db interaction happen on the DB thread. All
-// public methods are invoked on the ui thread and get funneled to the DB
-// thread.
-class TopSitesBackend
- : public base::RefCountedThreadSafe<TopSitesBackend>,
- public CancelableRequestProvider {
- public:
- TopSitesBackend();
-
- void Init(const FilePath& path);
-
- // Schedules the db to be shutdown.
- void Shutdown();
-
- typedef Callback2<Handle, scoped_refptr<MostVisitedThumbnails> >::Type
- GetMostVisitedThumbnailsCallback;
- typedef CancelableRequest1<TopSitesBackend::GetMostVisitedThumbnailsCallback,
- scoped_refptr<MostVisitedThumbnails> >
- GetMostVisitedThumbnailsRequest;
-
- // Fetches MostVisitedThumbnails.
- Handle GetMostVisitedThumbnails(CancelableRequestConsumerBase* consumer,
- GetMostVisitedThumbnailsCallback* callback);
-
- // Updates top sites database from the specified delta.
- void UpdateTopSites(const TopSitesDelta& delta);
-
- // Sets the thumbnail.
- void SetPageThumbnail(const MostVisitedURL& url,
- int url_rank,
- const Images& thumbnail);
-
- // Deletes the database and recreates it.
- void ResetDatabase();
-
- typedef Callback1<Handle>::Type EmptyRequestCallback;
- typedef CancelableRequest<TopSitesBackend::EmptyRequestCallback>
- EmptyRequestRequest;
-
- // Schedules a request that does nothing on the DB thread, but then notifies
- // the callback on the calling thread. This is used to make sure the db has
- // finished processing a request.
- Handle DoEmptyRequest(CancelableRequestConsumerBase* consumer,
- EmptyRequestCallback* callback);
-
- private:
- friend class base::RefCountedThreadSafe<TopSitesBackend>;
-
- ~TopSitesBackend();
-
- // Invokes Init on the db_.
- void InitDBOnDBThread(const FilePath& path);
-
- // Shuts down the db.
- void ShutdownDBOnDBThread();
-
- // Does the work of getting the most visted thumbnails.
- void GetMostVisitedThumbnailsOnDBThread(
- scoped_refptr<GetMostVisitedThumbnailsRequest> request);
-
- // Updates top sites.
- void UpdateTopSitesOnDBThread(const TopSitesDelta& delta);
-
- // Sets the thumbnail.
- void SetPageThumbnailOnDBThread(const MostVisitedURL& url,
- int url_rank,
- const Images& thumbnail);
-
- // Resets the database.
- void ResetDatabaseOnDBThread(const FilePath& file_path);
-
- // Notifies the request.
- void DoEmptyRequestOnDBThread(scoped_refptr<EmptyRequestRequest> request);
-
- FilePath db_path_;
-
- scoped_ptr<TopSitesDatabase> db_;
-
- DISALLOW_COPY_AND_ASSIGN(TopSitesBackend);
-};
-
-} // namespace history
-
-#endif // CHROME_BROWSER_HISTORY_TOP_SITES_BACKEND_H_
diff --git a/chrome/browser/history/top_sites_cache.cc b/chrome/browser/history/top_sites_cache.cc
deleted file mode 100644
index 9bae928..0000000
--- a/chrome/browser/history/top_sites_cache.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2010 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/history/top_sites_cache.h"
-
-#include "base/logging.h"
-#include "base/ref_counted_memory.h"
-
-namespace history {
-
-TopSitesCache::TopSitesCache() {
-}
-
-TopSitesCache::~TopSitesCache() {
-}
-
-void TopSitesCache::SetTopSites(const MostVisitedURLList& top_sites) {
- top_sites_ = top_sites;
- GenerateCanonicalURLs();
-}
-
-void TopSitesCache::SetThumbnails(const URLToImagesMap& images) {
- images_ = images;
-}
-
-void TopSitesCache::SetPageThumbnail(const GURL& url,
- RefCountedBytes* thumbnail,
- const ThumbnailScore& score) {
- Images& img = images_[GetCanonicalURL(url)];
- img.thumbnail = thumbnail;
- img.thumbnail_score = score;
-}
-
-Images* TopSitesCache::GetImage(const GURL& url) {
- return &images_[GetCanonicalURL(url)];
-}
-
-bool TopSitesCache::GetPageThumbnail(const GURL& url,
- scoped_refptr<RefCountedBytes>* bytes) {
- std::map<GURL, Images>::const_iterator found =
- images_.find(GetCanonicalURL(url));
- if (found != images_.end()) {
- *bytes = found->second.thumbnail.get();
- return true;
- }
- return false;
-}
-
-GURL TopSitesCache::GetCanonicalURL(const GURL& url) {
- std::map<GURL, size_t>::const_iterator i = canonical_urls_.find(url);
- return i == canonical_urls_.end() ? url : top_sites_[i->second].url;
-}
-
-bool TopSitesCache::IsKnownURL(const GURL& url) {
- return canonical_urls_.find(url) != canonical_urls_.end();
-}
-
-size_t TopSitesCache::GetURLIndex(const GURL& url) {
- DCHECK(IsKnownURL(url));
- return canonical_urls_[url];
-}
-
-void TopSitesCache::RemoveUnreferencedThumbnails() {
- for (URLToImagesMap::iterator i = images_.begin(); i != images_.end(); ) {
- if (IsKnownURL(i->first)) {
- ++i;
- } else {
- URLToImagesMap::iterator next_i = i;
- ++next_i;
- images_.erase(i);
- i = next_i;
- }
- }
-}
-
-void TopSitesCache::GenerateCanonicalURLs() {
- canonical_urls_.clear();
- for (size_t i = 0; i < top_sites_.size(); i++)
- StoreRedirectChain(top_sites_[i].redirects, i);
-}
-
-void TopSitesCache::StoreRedirectChain(const RedirectList& redirects,
- size_t destination) {
- // redirects is empty if the user pinned a site and there are not enough top
- // sites before the pinned site.
-
- // Map all the redirected URLs to the destination.
- for (size_t i = 0; i < redirects.size(); i++) {
- // If this redirect is already known, don't replace it with a new one.
- if (canonical_urls_.find(redirects[i]) == canonical_urls_.end())
- canonical_urls_[redirects[i]] = destination;
- }
-}
-
-} // namespace history
diff --git a/chrome/browser/history/top_sites_cache.h b/chrome/browser/history/top_sites_cache.h
deleted file mode 100644
index 7cedd9f..0000000
--- a/chrome/browser/history/top_sites_cache.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2010 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_HISTORY_TOP_SITES_CACHE_H_
-#define CHROME_BROWSER_HISTORY_TOP_SITES_CACHE_H_
-#pragma once
-
-#include <map>
-
-#include "base/ref_counted.h"
-#include "chrome/browser/history/history_types.h"
-
-class RefCountedBytes;
-
-namespace history {
-
-// TopSitesCache caches the top sites and thumbnails for TopSites.
-class TopSitesCache {
- public:
- TopSitesCache();
- ~TopSitesCache();
-
- // The top sites.
- void SetTopSites(const MostVisitedURLList& top_sites);
- const MostVisitedURLList& top_sites() const { return top_sites_; }
-
- // The thumbnails.
- void SetThumbnails(const URLToImagesMap& images);
- const URLToImagesMap& images() const { return images_; }
-
- // Set a thumbnail.
- void SetPageThumbnail(const GURL& url,
- RefCountedBytes* thumbnail,
- const ThumbnailScore& score);
-
- // Returns the thumbnail as an Image for the specified url. This adds an entry
- // for |url| if one has not yet been added.
- Images* GetImage(const GURL& url);
-
- // Fetches the thumbnail for the specified url. Returns true if there is a
- // thumbnail for the specified url.
- bool GetPageThumbnail(const GURL& url,
- scoped_refptr<RefCountedBytes>* bytes);
-
- // Returns the canonical URL for |url|.
- GURL GetCanonicalURL(const GURL& url);
-
- // Returns true if |url| is known.
- bool IsKnownURL(const GURL& url);
-
- // Returns the index into |top_sites_| for |url|.
- size_t GetURLIndex(const GURL& url);
-
- // Removes any thumbnails that are no longer referenced by the top sites.
- void RemoveUnreferencedThumbnails();
-
- private:
- // Generates the set of canonical urls from |top_sites_|.
- void GenerateCanonicalURLs();
-
- // Stores a set of redirects. This is used by GenerateCanonicalURLs.
- void StoreRedirectChain(const RedirectList& redirects, size_t destination);
-
- // The top sites.
- MostVisitedURLList top_sites_;
-
- // The images. These map from canonical url to image.
- URLToImagesMap images_;
-
- // Generated from the redirects to and from the most visited pages, this maps
- // the redirects to the index into top_sites_ that contains it.
- std::map<GURL, size_t> canonical_urls_;
-
- DISALLOW_COPY_AND_ASSIGN(TopSitesCache);
-};
-
-} // namespace history
-
-#endif // CHROME_BROWSER_HISTORY_TOP_SITES_CACHE_H_
diff --git a/chrome/browser/history/top_sites_database.cc b/chrome/browser/history/top_sites_database.cc
index 6752be0..05a588a 100644
--- a/chrome/browser/history/top_sites_database.cc
+++ b/chrome/browser/history/top_sites_database.cc
@@ -51,7 +51,8 @@ bool TopSitesDatabaseImpl::InitThumbnailTable() {
}
void TopSitesDatabaseImpl::GetPageThumbnails(MostVisitedURLList* urls,
- URLToImagesMap* thumbnails) {
+ std::map<GURL,
+ Images>* thumbnails) {
sql::Statement statement(db_.GetCachedStatement(
SQL_FROM_HERE,
"SELECT url, url_rank, title, thumbnail, redirects, "
diff --git a/chrome/browser/history/top_sites_database.h b/chrome/browser/history/top_sites_database.h
index fdd3267..edfb4e5 100644
--- a/chrome/browser/history/top_sites_database.h
+++ b/chrome/browser/history/top_sites_database.h
@@ -11,12 +11,16 @@
#include "app/sql/connection.h"
#include "base/ref_counted.h"
-#include "chrome/browser/history/history_types.h"
#include "chrome/browser/history/url_database.h" // For DBCloseScoper.
class FilePath;
class RefCountedMemory;
class SkBitmap;
+class Images;
+
+namespace base {
+class Time;
+}
namespace history {
@@ -31,7 +35,8 @@ class TopSitesDatabase {
// Returns a list of all URLs currently in the table.
virtual void GetPageThumbnails(MostVisitedURLList* urls,
- URLToImagesMap* thumbnails) = 0;
+ std::map<GURL,
+ Images>* thumbnails) = 0;
// Set a thumbnail for a URL. |url_rank| is the position of the URL
// in the list of TopURLs, zero-based.
diff --git a/chrome/browser/history/top_sites_unittest.cc b/chrome/browser/history/top_sites_unittest.cc
index ae994f6..160b275 100644
--- a/chrome/browser/history/top_sites_unittest.cc
+++ b/chrome/browser/history/top_sites_unittest.cc
@@ -3,26 +3,18 @@
// found in the LICENSE file.
#include "app/l10n_util.h"
-#include "base/command_line.h"
#include "base/file_util.h"
-#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/dom_ui/most_visited_handler.h"
-#include "chrome/browser/history/history_backend.h"
-#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history_marshaling.h"
-#include "chrome/browser/history/history_notifications.h"
-#include "chrome/browser/history/top_sites.h"
-#include "chrome/browser/history/top_sites_backend.h"
-#include "chrome/browser/history/top_sites_cache.h"
#include "chrome/browser/history/top_sites_database.h"
-#include "chrome/common/chrome_constants.h"
+#include "chrome/browser/history/history_notifications.h"
#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
#include "chrome/test/testing_profile.h"
#include "chrome/tools/profiles/thumbnail-inl.h"
#include "gfx/codec/jpeg_codec.h"
@@ -33,368 +25,247 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
+
namespace history {
-namespace {
+static const unsigned char kBlob[] =
+ "12346102356120394751634516591348710478123649165419234519234512349134";
-// Used by WaitForHistory, see it for details.
-class WaitForHistoryTask : public HistoryDBTask {
+class TopSitesTest : public testing::Test {
public:
- WaitForHistoryTask() {}
-
- virtual bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) {
- return true;
+ TopSitesTest() : number_of_callbacks_(0) {
}
-
- virtual void DoneRunOnMainThread() {
- MessageLoop::current()->Quit();
+ ~TopSitesTest() {
}
- private:
- DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
-};
-
-// Used for querying top sites. Either runs sequentially, or runs a nested
-// nested message loop until the response is complete. The later is used when
-// TopSites is queried before it finishes loading.
-class TopSitesQuerier {
- public:
- TopSitesQuerier() : number_of_callbacks_(0), waiting_(false) {}
-
- // Queries top sites. If |wait| is true a nested message loop is run until the
- // callback is notified.
- void QueryTopSites(TopSites* top_sites, bool wait) {
- int start_number_of_callbacks = number_of_callbacks_;
- top_sites->GetMostVisitedURLs(
- &consumer_,
- NewCallback(this, &TopSitesQuerier::OnTopSitesAvailable));
- if (wait && start_number_of_callbacks == number_of_callbacks_) {
- waiting_ = true;
- MessageLoop::current()->Run();
- }
+ TopSites& top_sites() { return *top_sites_; }
+ MostVisitedURLList& urls() { return urls_; }
+ Profile& profile() {return *profile_;}
+ FilePath& file_name() { return file_name_; }
+ RefCountedBytes* google_thumbnail() { return google_thumbnail_; }
+ RefCountedBytes* random_thumbnail() { return random_thumbnail_; }
+ RefCountedBytes* weewar_thumbnail() { return weewar_thumbnail_; }
+ CancelableRequestConsumer* consumer() { return &consumer_; }
+ size_t number_of_callbacks() {return number_of_callbacks_; }
+ // Prepopulated URLs - added at the back of TopSites.
+ GURL welcome_url() {
+ return GURL(l10n_util::GetStringUTF8(IDS_CHROME_WELCOME_URL));
}
-
- void CancelRequest() {
- consumer_.CancelAllRequests();
- }
-
- void set_urls(const MostVisitedURLList& urls) { urls_ = urls; }
- const MostVisitedURLList& urls() const { return urls_; }
-
- int number_of_callbacks() const { return number_of_callbacks_; }
-
- private:
- // Callback for TopSites::GetMostVisitedURLs.
- void OnTopSitesAvailable(history::MostVisitedURLList data) {
- urls_ = data;
- number_of_callbacks_++;
- if (waiting_) {
- MessageLoop::current()->Quit();
- waiting_ = false;
- }
- }
-
- CancelableRequestConsumer consumer_;
- MostVisitedURLList urls_;
- int number_of_callbacks_;
- bool waiting_;
-
- DISALLOW_COPY_AND_ASSIGN(TopSitesQuerier);
-};
-
-// Extracts the data from |t1| into a SkBitmap. This is intended for usage of
-// thumbnail data, which is stored as jpgs.
-SkBitmap ExtractThumbnail(const RefCountedBytes& t1) {
- scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(t1.front(),
- t1.data.size()));
- return image.get() ? *image : SkBitmap();
-}
-
-// Returns true if t1 and t2 contain the same data.
-bool ThumbnailsAreEqual(RefCountedBytes* t1, RefCountedBytes* t2) {
- if (!t1 || !t2)
- return false;
- if (t1->data.size() != t2->data.size())
- return false;
- return std::equal(t1->data.begin(),
- t1->data.end(),
- t2->data.begin());
-}
-
-} // namespace
-
-class TopSitesTest : public testing::Test {
- public:
- TopSitesTest()
- : ui_thread_(BrowserThread::UI, &message_loop_),
- db_thread_(BrowserThread::DB, &message_loop_),
- original_command_line_(*CommandLine::ForCurrentProcess()) {
+ GURL themes_url() {
+ return GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL));
}
virtual void SetUp() {
- CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTopSites);
profile_.reset(new TestingProfile);
- if (CreateHistoryAndTopSites()) {
- profile_->CreateHistoryService(false, false);
- profile_->CreateTopSites();
- profile_->BlockUntilTopSitesLoaded();
- }
+ top_sites_ = new TopSites(profile_.get());
+
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ file_name_ = temp_dir_.path().AppendASCII("TopSites.db");
+ EXPECT_TRUE(file_util::Delete(file_name_, false));
+
+ std::vector<unsigned char> random_data(kBlob, kBlob + sizeof(kBlob));
+ std::vector<unsigned char> google_data(kGoogleThumbnail,
+ kGoogleThumbnail +
+ sizeof(kGoogleThumbnail));
+ std::vector<unsigned char> weewar_data(kWeewarThumbnail,
+ kWeewarThumbnail +
+ sizeof(kWeewarThumbnail));
+ random_thumbnail_ = new RefCountedBytes(random_data);
+ google_thumbnail_ = new RefCountedBytes(google_data);
+ weewar_thumbnail_ = new RefCountedBytes(weewar_data);
}
virtual void TearDown() {
profile_.reset();
- *CommandLine::ForCurrentProcess() = original_command_line_;
- }
-
- // Returns true if history and top sites should be created in SetUp.
- virtual bool CreateHistoryAndTopSites() {
- return true;
- }
-
- // Gets the thumbnail for |url| from TopSites.
- SkBitmap GetThumbnail(const GURL& url) {
- scoped_refptr<RefCountedBytes> data;
- return top_sites()->GetPageThumbnail(url, &data) ?
- ExtractThumbnail(*data.get()) : SkBitmap();
- }
-
- // Creates a bitmap of the specified color.
- SkBitmap CreateBitmap(SkColor color) {
- SkBitmap thumbnail;
- thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
- thumbnail.allocPixels();
- thumbnail.eraseColor(color);
- return thumbnail;
- }
-
- // Forces top sites to load top sites from history, then recreates top sites.
- // Recreating top sites makes sure the changes from history are saved and
- // loaded from the db.
- void RefreshTopSitesAndRecreate() {
- StartQueryForMostVisited();
- WaitForHistory();
- RecreateTopSitesAndBlock();
- }
-
- // Blocks the caller until history processes a task. This is useful if you
- // need to wait until you know history has processed a task.
- void WaitForHistory() {
- history_service()->ScheduleDBTask(new WaitForHistoryTask(), &consumer_);
- MessageLoop::current()->Run();
+ TopSites::DeleteTopSites(top_sites_);
+ EXPECT_TRUE(file_util::Delete(file_name_, false));
}
- // Waits for top sites to finish processing a task. This is useful if you need
- // to wait until top sites finishes processing a task.
- void WaitForTopSites() {
- top_sites()->backend_->DoEmptyRequest(
- &consumer_,
- NewCallback(this, &TopSitesTest::QuitCallback));
- MessageLoop::current()->Run();
+ // Callback for TopSites::GetMostVisitedURLs.
+ void OnTopSitesAvailable(history::MostVisitedURLList data) {
+ urls_ = data;
+ number_of_callbacks_++;
}
- TopSites* top_sites() { return profile_->GetTopSites(); }
- CancelableRequestConsumer* consumer() { return &consumer_; }
- TestingProfile* profile() {return profile_.get();}
- HistoryService* history_service() {
- return profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ // Wrappers that allow private TopSites functions to be called from the
+ // individual tests without making them all be friends.
+ GURL GetCanonicalURL(const GURL& url) const {
+ AutoLock lock(top_sites_->lock_); // The function asserts it's in the lock.
+ return top_sites_->GetCanonicalURL(url);
}
- MostVisitedURLList GetPrepopulatePages() {
- return TopSites::GetPrepopulatePages();
+ void StoreMostVisited(std::vector<MostVisitedURL>* urls) {
+ top_sites_->StoreMostVisited(urls);
}
- // Returns true if the TopSitesQuerier contains the prepopulate data starting
- // at |start_index|.
- void ContainsPrepopulatePages(const TopSitesQuerier& querier,
- size_t start_index) {
- MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
- ASSERT_LE(start_index + prepopulate_urls.size(), querier.urls().size());
- for (size_t i = 0; i < prepopulate_urls.size(); ++i) {
- EXPECT_EQ(prepopulate_urls[i].url.spec(),
- querier.urls()[start_index + i].url.spec()) << " @ index " <<
- i;
- }
+ static void DiffMostVisited(const std::vector<MostVisitedURL>& old_list,
+ const std::vector<MostVisitedURL>& new_list,
+ std::vector<size_t>* added_urls,
+ std::vector<size_t>* deleted_urls,
+ std::vector<size_t>* moved_urls) {
+ TopSites::DiffMostVisited(old_list, new_list,
+ added_urls, deleted_urls, moved_urls);
}
- // Used for callbacks from history.
- void EmptyCallback() {
+ Lock& lock() {
+ return top_sites_->lock_;
}
- // Quit the current message loop when invoked. Useful when running a nested
- // message loop.
- void QuitCallback(TopSitesBackend::Handle handle) {
- MessageLoop::current()->Quit();
- }
+ private:
+ scoped_refptr<TopSites> top_sites_;
+ MostVisitedURLList urls_;
+ size_t number_of_callbacks_;
+ scoped_ptr<TestingProfile> profile_;
+ ScopedTempDir temp_dir_;
+ FilePath file_name_; // Database filename.
+ scoped_refptr<RefCountedBytes> google_thumbnail_;
+ scoped_refptr<RefCountedBytes> random_thumbnail_;
+ scoped_refptr<RefCountedBytes> weewar_thumbnail_;
+ MessageLoop message_loop_;
+ CancelableRequestConsumer consumer_;
- // Adds a page to history.
- void AddPageToHistory(const GURL& url) {
- RedirectList redirects;
- redirects.push_back(url);
- history_service()->AddPage(
- url, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
- redirects, history::SOURCE_BROWSED, false);
- }
+ DISALLOW_COPY_AND_ASSIGN(TopSitesTest);
+};
- // Adds a page to history.
- void AddPageToHistory(const GURL& url, const string16& title) {
- RedirectList redirects;
- redirects.push_back(url);
- history_service()->AddPage(
- url, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
- redirects, history::SOURCE_BROWSED, false);
- history_service()->SetPageTitle(url, title);
- }
- // Adds a page to history.
- void AddPageToHistory(const GURL& url,
- const string16& title,
- const history::RedirectList& redirects,
- base::Time time) {
- history_service()->AddPage(
- url, time, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
- redirects, history::SOURCE_BROWSED, false);
- history_service()->SetPageTitle(url, title);
+// A mockup of a HistoryService used for testing TopSites.
+class MockHistoryServiceImpl : public TopSites::MockHistoryService {
+ public:
+ MockHistoryServiceImpl() : num_thumbnail_requests_(0) {}
+
+ // Calls the callback directly with the results.
+ HistoryService::Handle QueryMostVisitedURLs(
+ int result_count, int days_back,
+ CancelableRequestConsumerBase* consumer,
+ HistoryService::QueryMostVisitedURLsCallback* callback) {
+ callback->Run(CancelableRequestProvider::Handle(0), // Handle is unused.
+ most_visited_urls_);
+ delete callback;
+ return 0;
}
- // Delets a url.
- void DeleteURL(const GURL& url) {
- history_service()->DeleteURL(url);
+ // Add a page to the end of the pages list.
+ void AppendMockPage(const GURL& url,
+ const string16& title) {
+ MostVisitedURL page;
+ page.url = url;
+ page.title = title;
+ page.redirects = RedirectList();
+ page.redirects.push_back(url);
+ most_visited_urls_.push_back(page);
}
- // Returns true if the thumbnail equals the specified bytes.
- bool ThumbnailEqualsBytes(const SkBitmap& image, RefCountedBytes* bytes) {
- scoped_refptr<RefCountedBytes> encoded_image;
- EncodeBitmap(image, &encoded_image);
- return ThumbnailsAreEqual(encoded_image, bytes);
+ // Removes the last URL in the list.
+ void RemoveMostVisitedURL() {
+ most_visited_urls_.pop_back();
}
- // Recreates top sites. This forces top sites to reread from the db.
- void RecreateTopSitesAndBlock() {
- // Recreate TopSites and wait for it to load.
- profile()->CreateTopSites();
- // As history already loaded we have to fake this call.
- HistoryLoaded();
- profile()->BlockUntilTopSitesLoaded();
+ virtual void GetPageThumbnail(
+ const GURL& url,
+ CancelableRequestConsumerTSimple<size_t>* consumer,
+ HistoryService::ThumbnailDataCallback* callback,
+ size_t index) {
+ num_thumbnail_requests_++;
+ MostVisitedURL mvu;
+ mvu.url = url;
+ MostVisitedURLList::iterator pos = std::find(most_visited_urls_.begin(),
+ most_visited_urls_.end(),
+ mvu);
+ EXPECT_TRUE(pos != most_visited_urls_.end()) << url.spec();
+ scoped_refptr<RefCountedBytes> thumbnail;
+ callback->Run(index, thumbnail);
+ delete callback;
}
- // Wrappers that allow private TopSites functions to be called from the
- // individual tests without making them all be friends.
- GURL GetCanonicalURL(const GURL& url) {
- return top_sites()->cache_->GetCanonicalURL(url);
+ void ResetNumberOfThumbnailRequests() {
+ num_thumbnail_requests_ = 0;
}
- void SetTopSites(const MostVisitedURLList& new_top_sites) {
- top_sites()->SetTopSites(new_top_sites);
+ int GetNumberOfThumbnailRequests() {
+ return num_thumbnail_requests_;
}
- void StartQueryForMostVisited() {
- top_sites()->StartQueryForMostVisited();
- }
+ private:
+ MostVisitedURLList most_visited_urls_;
+ int num_thumbnail_requests_; // Number of calls to GetPageThumbnail.
+};
- bool EncodeBitmap(const SkBitmap& image,
- scoped_refptr<RefCountedBytes>* bytes) {
- return TopSites::EncodeBitmap(image, bytes);
- }
- void HistoryLoaded() {
- top_sites()->HistoryLoaded();
+// A mockup of a TopSitesDatabase used for testing TopSites.
+class MockTopSitesDatabaseImpl : public TopSitesDatabase {
+ public:
+ virtual void GetPageThumbnails(MostVisitedURLList* urls,
+ std::map<GURL, Images>* thumbnails) {
+ // Return a copy of the vector.
+ *urls = top_sites_list_;
+ *thumbnails = thumbnails_map_;
}
- void SetLastNumUrlsChanged(size_t value) {
- top_sites()->last_num_urls_changed_ = value;
+ virtual void SetPageThumbnail(const MostVisitedURL& url, int url_rank,
+ const Images& thumbnail) {
+ SetPageRank(url, url_rank);
+ // Update thubmnail
+ thumbnails_map_[url.url] = thumbnail;
}
- size_t last_num_urls_changed() { return top_sites()->last_num_urls_changed_; }
-
- base::TimeDelta GetUpdateDelay() {
- return top_sites()->GetUpdateDelay();
+ virtual void UpdatePageRank(const MostVisitedURL& url, int new_rank) {
+ MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
+ top_sites_list_.end(),
+ url);
+ // Is it in the right position?
+ int rank = pos - top_sites_list_.begin();
+ if (rank != new_rank) {
+ // Move the URL to a new position.
+ top_sites_list_.erase(pos);
+ top_sites_list_.insert(top_sites_list_.begin() + new_rank, url);
+ }
}
- bool IsTopSitesLoaded() { return top_sites()->state_ == TopSites::LOADED; }
-
- bool AddPrepopulatedPages(MostVisitedURLList* urls) {
- return TopSites::AddPrepopulatedPages(urls);
+ virtual void SetPageRank(const MostVisitedURL& url, int url_rank) {
+ // Check if this url is in the list, and at which position.
+ MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
+ top_sites_list_.end(),
+ url);
+ if (pos == top_sites_list_.end()) {
+ // Add it to the list.
+ top_sites_list_.insert(top_sites_list_.begin() + url_rank, url);
+ } else {
+ UpdatePageRank(url, url_rank);
+ }
}
- private:
- MessageLoopForUI message_loop_;
- BrowserThread ui_thread_;
- BrowserThread db_thread_;
- scoped_ptr<TestingProfile> profile_;
- CancelableRequestConsumer consumer_;
- CommandLine original_command_line_;
+ // Get a thumbnail for a given page. Returns true iff we have the thumbnail.
+ virtual bool GetPageThumbnail(const GURL& url,
+ Images* thumbnail) {
+ std::map<GURL, Images>::const_iterator found =
+ thumbnails_map_.find(url);
+ if (found == thumbnails_map_.end())
+ return false; // No thumbnail for this URL.
- DISALLOW_COPY_AND_ASSIGN(TopSitesTest);
-}; // Class TopSitesTest
-
-class TopSitesMigrationTest : public TopSitesTest {
- public:
- TopSitesMigrationTest() {}
-
- virtual void SetUp() {
- TopSitesTest::SetUp();
-
- FilePath data_path;
- ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
- data_path = data_path.AppendASCII("top_sites");
-
- // Set up history and thumbnails as they would be before migration.
- ASSERT_NO_FATAL_FAILURE(
- ExecuteSQL(data_path.AppendASCII("history.19.sql"),
- profile()->GetPath().Append(chrome::kHistoryFilename)));
- ASSERT_NO_FATAL_FAILURE(
- ExecuteSQL(data_path.AppendASCII("thumbnails.3.sql"),
- profile()->GetPath().Append(chrome::kThumbnailsFilename)));
-
- profile()->CreateHistoryService(false, false);
- profile()->CreateTopSites();
- profile()->BlockUntilTopSitesLoaded();
- }
-
- // Returns true if history and top sites should be created in SetUp.
- virtual bool CreateHistoryAndTopSites() {
- return false;
+ thumbnail->thumbnail = found->second.thumbnail;
+ thumbnail->thumbnail_score = found->second.thumbnail_score;
+ return true;
}
- protected:
- // Assertions for the migration test. This is extracted into a standalone
- // method so that it can be invoked twice.
- void MigrationAssertions() {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- // We shouldn't have gotten a callback.
- EXPECT_EQ(1, querier.number_of_callbacks());
-
- // The data we loaded should contain google and yahoo.
- ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(GURL("http://google.com/"), querier.urls()[0].url);
- EXPECT_EQ(GURL("http://yahoo.com/"), querier.urls()[1].url);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
-
- SkBitmap goog_thumbnail = GetThumbnail(GURL("http://google.com/"));
- EXPECT_EQ(1, goog_thumbnail.width());
-
- SkBitmap yahoo_thumbnail = GetThumbnail(GURL("http://yahoo.com/"));
- EXPECT_EQ(2, yahoo_thumbnail.width());
-
- // Favicon assertions are handled in ThumbnailDatabase.
+ virtual bool RemoveURL(const MostVisitedURL& url) {
+ // Comparison by url.
+ MostVisitedURLList::iterator pos = std::find(top_sites_list_.begin(),
+ top_sites_list_.end(),
+ url);
+ if (pos == top_sites_list_.end()) {
+ return false;
+ }
+ top_sites_list_.erase(pos);
+ thumbnails_map_.erase(url.url);
+ return true;
}
private:
- // Executes the sql from the file |sql_path| in the database at |db_path|.
- void ExecuteSQL(const FilePath& sql_path,
- const FilePath& db_path) {
- std::string sql;
- ASSERT_TRUE(file_util::ReadFileToString(sql_path, &sql));
- sql::Connection connection;
- ASSERT_TRUE(connection.Open(db_path));
- ASSERT_TRUE(connection.Execute(sql.c_str()));
- }
-
- DISALLOW_COPY_AND_ASSIGN(TopSitesMigrationTest);
+ MostVisitedURLList top_sites_list_; // Keeps the URLs sorted by score (rank).
+ std::map<GURL, Images> thumbnails_map_;
};
+
// Helper function for appending a URL to a vector of "most visited" URLs,
// using the default values for everything but the URL.
static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
@@ -405,6 +276,18 @@ static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
list->push_back(mv);
}
+// Returns true if t1 and t2 contain the same data.
+static bool ThumbnailsAreEqual(RefCountedBytes* t1,
+ RefCountedBytes* t2) {
+ if (!t1 || !t2)
+ return false;
+ if (t1->data.size() != t2->data.size())
+ return false;
+ return std::equal(t1->data.begin(),
+ t1->data.end(),
+ t2->data.begin());
+}
+
// Same as AppendMostVisitedURL except that it adds a redirect from the first
// URL to the second.
static void AppendMostVisitedURLWithRedirect(
@@ -417,8 +300,8 @@ static void AppendMostVisitedURLWithRedirect(
list->push_back(mv);
}
-// Tests GetCanonicalURL.
TEST_F(TopSitesTest, GetCanonicalURL) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
// Have two chains:
// google.com -> www.google.com
// news.google.com (no redirects)
@@ -429,7 +312,7 @@ TEST_F(TopSitesTest, GetCanonicalURL) {
std::vector<MostVisitedURL> most_visited;
AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
AppendMostVisitedURL(&most_visited, news);
- SetTopSites(most_visited);
+ StoreMostVisited(&most_visited);
// Random URLs not in the database are returned unchanged.
GURL result = GetCanonicalURL(GURL("http://fark.com/"));
@@ -448,7 +331,6 @@ TEST_F(TopSitesTest, GetCanonicalURL) {
EXPECT_EQ(dest, result);
}
-// Tests DiffMostVisited.
TEST_F(TopSitesTest, DiffMostVisited) {
GURL stays_the_same("http://staysthesame/");
GURL gets_added_1("http://getsadded1/");
@@ -467,25 +349,26 @@ TEST_F(TopSitesTest, DiffMostVisited) {
AppendMostVisitedURL(&new_list, gets_added_2); // 2 (added)
AppendMostVisitedURL(&new_list, gets_moved_1); // 3 (moved from 2)
- history::TopSitesDelta delta;
- history::TopSites::DiffMostVisited(old_list, new_list, &delta);
+ std::vector<size_t> added;
+ std::vector<size_t> deleted;
+ std::vector<size_t> moved;
+ DiffMostVisited(old_list, new_list, &added, &deleted, &moved);
- ASSERT_EQ(2u, delta.added.size());
- ASSERT_TRUE(gets_added_1 == delta.added[0].url.url);
- ASSERT_EQ(1, delta.added[0].rank);
- ASSERT_TRUE(gets_added_2 == delta.added[1].url.url);
- ASSERT_EQ(2, delta.added[1].rank);
+ ASSERT_EQ(2u, added.size());
+ ASSERT_EQ(1u, deleted.size());
+ ASSERT_EQ(1u, moved.size());
- ASSERT_EQ(1u, delta.deleted.size());
- ASSERT_TRUE(gets_deleted_1 == delta.deleted[0].url);
+ // There should be 2 URLs added, we don't assume what order they're in inside
+ // the result vector.
+ EXPECT_TRUE(added[0] == 1 || added[1] == 1);
+ EXPECT_TRUE(added[0] == 2 || added[1] == 2);
- ASSERT_EQ(1u, delta.moved.size());
- ASSERT_TRUE(gets_moved_1 == delta.moved[0].url.url);
- ASSERT_EQ(3, delta.moved[0].rank);
+ EXPECT_EQ(1u, deleted[0]);
+ EXPECT_EQ(3u, moved[0]);
}
-// Tests SetPageThumbnail.
TEST_F(TopSitesTest, SetPageThumbnail) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
GURL url1a("http://google.com/");
GURL url1b("http://www.google.com/");
GURL url2("http://images.google.com/");
@@ -501,10 +384,13 @@ TEST_F(TopSitesTest, SetPageThumbnail) {
list.push_back(mv);
// Save our most visited data containing that one site.
- SetTopSites(list);
+ StoreMostVisited(&list);
// Create a dummy thumbnail.
- SkBitmap thumbnail(CreateBitmap(SK_ColorWHITE));
+ SkBitmap thumbnail;
+ thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
+ thumbnail.allocPixels();
+ thumbnail.eraseRGB(0x00, 0x00, 0x00);
base::Time now = base::Time::Now();
ThumbnailScore low_score(1.0, true, true, now);
@@ -512,117 +398,96 @@ TEST_F(TopSitesTest, SetPageThumbnail) {
ThumbnailScore high_score(0.0, true, true, now);
// Setting the thumbnail for invalid pages should fail.
- EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
- thumbnail, medium_score));
+ EXPECT_FALSE(top_sites().SetPageThumbnail(invalid_url,
+ thumbnail, medium_score));
// Setting the thumbnail for url2 should succeed, lower scores shouldn't
// replace it, higher scores should.
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, medium_score));
- EXPECT_FALSE(top_sites()->SetPageThumbnail(url2, thumbnail, low_score));
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, high_score));
+ EXPECT_TRUE(top_sites().SetPageThumbnail(url2, thumbnail, medium_score));
+ EXPECT_FALSE(top_sites().SetPageThumbnail(url2, thumbnail, low_score));
+ EXPECT_TRUE(top_sites().SetPageThumbnail(url2, thumbnail, high_score));
// Set on the redirect source should succeed. It should be replacable by
// the same score on the redirect destination, which in turn should not
// be replaced by the source again.
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url1b, thumbnail, medium_score));
- EXPECT_FALSE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
-}
-
-// Makes sure a thumbnail is correctly removed when the page is removed.
-TEST_F(TopSitesTest, ThumbnailRemoved) {
- GURL url("http://google.com/");
-
- // Configure top sites with 'google.com'.
- std::vector<MostVisitedURL> list;
- AppendMostVisitedURL(&list, url);
- SetTopSites(list);
-
- // Create a dummy thumbnail.
- SkBitmap thumbnail(CreateBitmap(SK_ColorRED));
-
- base::Time now = base::Time::Now();
- ThumbnailScore low_score(1.0, true, true, now);
- ThumbnailScore medium_score(0.5, true, true, now);
- ThumbnailScore high_score(0.0, true, true, now);
-
- // Set the thumbnail.
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url, thumbnail, medium_score));
-
- // Make sure the thumbnail was actually set.
- scoped_refptr<RefCountedBytes> result;
- EXPECT_TRUE(top_sites()->GetPageThumbnail(url, &result));
- EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
-
- // Reset the thumbnails and make sure we don't get it back.
- SetTopSites(MostVisitedURLList());
- EXPECT_FALSE(top_sites()->GetPageThumbnail(url, &result));
+ EXPECT_TRUE(top_sites().SetPageThumbnail(url1a, thumbnail, medium_score));
+ EXPECT_TRUE(top_sites().SetPageThumbnail(url1b, thumbnail, medium_score));
+ EXPECT_FALSE(top_sites().SetPageThumbnail(url1a, thumbnail, medium_score));
}
-// Tests GetPageThumbnail.
TEST_F(TopSitesTest, GetPageThumbnail) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
MostVisitedURLList url_list;
- MostVisitedURL url1;
- url1.url = GURL("http://asdf.com");
+ MostVisitedURL url1(GURL("http://asdf.com"), GURL(), string16());
url1.redirects.push_back(url1.url);
url_list.push_back(url1);
- MostVisitedURL url2;
- url2.url = GURL("http://gmail.com");
+ MostVisitedURL url2(GURL("http://gmail.com"), GURL(), string16());
url2.redirects.push_back(url2.url);
url2.redirects.push_back(GURL("http://mail.google.com"));
url_list.push_back(url2);
- SetTopSites(url_list);
+ top_sites().UpdateMostVisited(url_list);
+ MessageLoop::current()->RunAllPending();
// Create a dummy thumbnail.
- SkBitmap thumbnail(CreateBitmap(SK_ColorWHITE));
+ SkBitmap thumbnail;
+ thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
+ thumbnail.allocPixels();
+ thumbnail.eraseRGB(0x00, 0x00, 0x00);
ThumbnailScore score(0.5, true, true, base::Time::Now());
- scoped_refptr<RefCountedBytes> result;
- EXPECT_TRUE(top_sites()->SetPageThumbnail(url1.url, thumbnail, score));
- EXPECT_TRUE(top_sites()->GetPageThumbnail(url1.url, &result));
+ RefCountedBytes* result = NULL;
+ EXPECT_TRUE(top_sites().SetPageThumbnail(url1.url, thumbnail, score));
+ EXPECT_TRUE(top_sites().GetPageThumbnail(url1.url, &result));
- EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://gmail.com"),
+ EXPECT_TRUE(top_sites().SetPageThumbnail(GURL("http://gmail.com"),
thumbnail, score));
- EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://gmail.com"),
- &result));
+ EXPECT_TRUE(top_sites().GetPageThumbnail(GURL("http://gmail.com"),
+ &result));
// Get a thumbnail via a redirect.
- EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://mail.google.com"),
- &result));
+ EXPECT_TRUE(top_sites().GetPageThumbnail(GURL("http://mail.google.com"),
+ &result));
- EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://mail.google.com"),
+ EXPECT_TRUE(top_sites().SetPageThumbnail(GURL("http://mail.google.com"),
thumbnail, score));
- EXPECT_TRUE(top_sites()->GetPageThumbnail(url2.url, &result));
+ EXPECT_TRUE(top_sites().GetPageThumbnail(url2.url, &result));
- EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
+ scoped_ptr<SkBitmap> out_bitmap(gfx::JPEGCodec::Decode(result->front(),
+ result->size()));
+ EXPECT_EQ(0, memcmp(thumbnail.getPixels(), out_bitmap->getPixels(),
+ thumbnail.getSize()));
}
-// Tests GetMostVisitedURLs.
TEST_F(TopSitesTest, GetMostVisited) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
GURL news("http://news.google.com/");
GURL google("http://google.com/");
- AddPageToHistory(news);
- AddPageToHistory(google);
-
- StartQueryForMostVisited();
- WaitForHistory();
-
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(1, querier.number_of_callbacks());
-
+ MockHistoryServiceImpl hs;
+ hs.AppendMockPage(news, ASCIIToUTF16("Google News"));
+ hs.AppendMockPage(google, ASCIIToUTF16("Google"));
+ top_sites().SetMockHistoryService(&hs);
+
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
// 2 extra prepopulated URLs.
- ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(news, querier.urls()[0].url);
- EXPECT_EQ(google, querier.urls()[1].url);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ(news, urls()[0].url);
+ EXPECT_EQ(google, urls()[1].url);
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
}
-// Makes sure changes done to top sites get mirrored to the db.
-TEST_F(TopSitesTest, SaveToDB) {
+TEST_F(TopSitesTest, MockDatabase) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ MockTopSitesDatabaseImpl* db = new MockTopSitesDatabaseImpl;
+ // |db| is destroyed when the top_sites is destroyed in TearDown.
+ top_sites().db_.reset(db);
MostVisitedURL url;
GURL asdf_url("http://asdf.com");
string16 asdf_title(ASCIIToUTF16("ASDF"));
@@ -631,62 +496,155 @@ TEST_F(TopSitesTest, SaveToDB) {
GURL news_url("http://news.google.com");
string16 news_title(ASCIIToUTF16("Google News"));
- // Add asdf_url to history.
- AddPageToHistory(asdf_url, asdf_title);
-
- // Make TopSites reread from the db.
- StartQueryForMostVisited();
- WaitForHistory();
-
- // Add a thumbnail.
- SkBitmap tmp_bitmap(CreateBitmap(SK_ColorBLUE));
- ASSERT_TRUE(top_sites()->SetPageThumbnail(asdf_url, tmp_bitmap,
- ThumbnailScore()));
+ url.url = asdf_url;
+ url.title = asdf_title;
+ url.redirects.push_back(url.url);
+ Images thumbnail;
+ db->SetPageThumbnail(url, 0, thumbnail);
- RecreateTopSitesAndBlock();
+ top_sites().ReadDatabase();
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
- ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(asdf_url, querier.urls()[0].url);
- EXPECT_EQ(asdf_title, querier.urls()[0].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
-
- scoped_refptr<RefCountedBytes> read_data;
- EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, &read_data));
- EXPECT_TRUE(ThumbnailEqualsBytes(tmp_bitmap, read_data.get()));
- }
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_EQ(asdf_url, urls()[0].url);
+ EXPECT_EQ(asdf_title, urls()[0].title);
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
MostVisitedURL url2;
url2.url = google_url;
url2.title = google_title;
url2.redirects.push_back(url2.url);
- AddPageToHistory(url2.url, url2.title);
-
// Add new thumbnail at rank 0 and shift the other result to 1.
- ASSERT_TRUE(top_sites()->SetPageThumbnail(google_url,
- tmp_bitmap,
- ThumbnailScore()));
+ db->SetPageThumbnail(url2, 0, thumbnail);
+
+ top_sites().ReadDatabase();
+
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ(google_url, urls()[0].url);
+ EXPECT_EQ(google_title, urls()[0].title);
+ EXPECT_EQ(asdf_url, urls()[1].url);
+ EXPECT_EQ(asdf_title, urls()[1].title);
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
+
+ MockHistoryServiceImpl hs;
+ // Add one old, one new URL to the history.
+ hs.AppendMockPage(google_url, google_title);
+ hs.AppendMockPage(news_url, news_title);
+ top_sites().SetMockHistoryService(&hs);
+
+ // This writes the new data to the DB.
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
+
+ std::map<GURL, Images> thumbnails;
+ MostVisitedURLList result;
+ db->GetPageThumbnails(&result, &thumbnails);
+ ASSERT_EQ(4u, result.size());
+ EXPECT_EQ(google_title, result[0].title);
+ EXPECT_EQ(news_title, result[1].title);
+}
- // Make TopSites reread from the db.
- RefreshTopSitesAndRecreate();
+// Test TopSitesDatabaseImpl.
+TEST_F(TopSitesTest, TopSitesDB) {
+ TopSitesDatabaseImpl db;
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
- ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(asdf_url, querier.urls()[0].url);
- EXPECT_EQ(asdf_title, querier.urls()[0].title);
- EXPECT_EQ(google_url, querier.urls()[1].url);
- EXPECT_EQ(google_title, querier.urls()[1].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
- }
+ ASSERT_TRUE(db.Init(file_name()));
+
+ MostVisitedURL url;
+ GURL asdf_url("http://asdf.com");
+ string16 asdf_title(ASCIIToUTF16("ASDF"));
+ GURL google_url("http://google.com");
+ string16 google_title(ASCIIToUTF16("Google"));
+ GURL news_url("http://news.google.com");
+ string16 news_title(ASCIIToUTF16("Google News"));
+
+ url.url = asdf_url;
+ url.title = asdf_title;
+ url.redirects.push_back(url.url);
+ Images thumbnail;
+ thumbnail.thumbnail = random_thumbnail();
+ // Add asdf at rank 0.
+ db.SetPageThumbnail(url, 0, thumbnail);
+
+ Images result;
+ EXPECT_TRUE(db.GetPageThumbnail(url.url, &result));
+ EXPECT_EQ(thumbnail.thumbnail->data.size(), result.thumbnail->data.size());
+ EXPECT_TRUE(ThumbnailsAreEqual(thumbnail.thumbnail, result.thumbnail));
+
+ MostVisitedURLList urls;
+ std::map<GURL, Images> thumbnails;
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(1u, urls.size());
+ EXPECT_EQ(asdf_url, urls[0].url);
+ EXPECT_EQ(asdf_title, urls[0].title);
+
+ url.url = google_url;
+ url.title = google_title;
+
+ // Add google at rank 1 - no rank shifting.
+ db.SetPageThumbnail(url, 1, thumbnail);
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(2u, urls.size());
+ EXPECT_EQ(asdf_url, urls[0].url);
+ EXPECT_EQ(asdf_title, urls[0].title);
+ EXPECT_EQ(google_url, urls[1].url);
+ EXPECT_EQ(google_title, urls[1].title);
+
+ url.url = news_url;
+ url.title = news_title;
+
+ // Add news at rank 1 - shift google to rank 2.
+ db.SetPageThumbnail(url, 1, thumbnail);
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ EXPECT_EQ(asdf_url, urls[0].url);
+ EXPECT_EQ(news_url, urls[1].url);
+ EXPECT_EQ(google_url, urls[2].url);
+
+ // Move news at rank 0 - shift the rest up.
+ db.SetPageThumbnail(url, 0, thumbnail);
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ EXPECT_EQ(news_url, urls[0].url);
+ EXPECT_EQ(asdf_url, urls[1].url);
+ EXPECT_EQ(google_url, urls[2].url);
+
+ // Move news at rank 2 - shift the rest down.
+ db.SetPageThumbnail(url, 2, thumbnail);
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(3u, urls.size());
+ EXPECT_EQ(asdf_url, urls[0].url);
+ EXPECT_EQ(google_url, urls[1].url);
+ EXPECT_EQ(news_url, urls[2].url);
+
+ // Delete asdf.
+ url.url = asdf_url;
+ db.RemoveURL(url);
+
+ db.GetPageThumbnails(&urls, &thumbnails);
+ ASSERT_EQ(2u, urls.size());
+ EXPECT_EQ(google_url, urls[0].url);
+ EXPECT_EQ(news_url, urls[1].url);
}
-// More permutations of saving to db.
+// Test TopSites with a real database.
TEST_F(TopSitesTest, RealDatabase) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ TopSitesDatabaseImpl* db = new TopSitesDatabaseImpl;
+
+ ASSERT_TRUE(db->Init(file_name()));
+ // |db| is destroyed when the top_sites is destroyed in TearDown.
+ top_sites().db_.reset(db);
MostVisitedURL url;
GURL asdf_url("http://asdf.com");
string16 asdf_title(ASCIIToUTF16("ASDF"));
@@ -700,106 +658,130 @@ TEST_F(TopSitesTest, RealDatabase) {
url.url = asdf_url;
url.title = asdf_title;
url.redirects.push_back(url.url);
- SkBitmap asdf_thumbnail(CreateBitmap(SK_ColorRED));
- ASSERT_TRUE(top_sites()->SetPageThumbnail(
- asdf_url, asdf_thumbnail, ThumbnailScore()));
-
- base::Time add_time(base::Time::Now());
- AddPageToHistory(url.url, url.title, url.redirects, add_time);
-
- RefreshTopSitesAndRecreate();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(asdf_url, querier.urls()[0].url);
- EXPECT_EQ(asdf_title, querier.urls()[0].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
-
- scoped_refptr<RefCountedBytes> read_data;
- EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, &read_data));
- EXPECT_TRUE(ThumbnailEqualsBytes(asdf_thumbnail, read_data.get()));
- }
+ Images thumbnail;
+ thumbnail.thumbnail = random_thumbnail();
+ db->SetPageThumbnail(url, 0, thumbnail);
+
+ top_sites().ReadDatabase();
+
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_EQ(asdf_url, urls()[0].url);
+ EXPECT_EQ(asdf_title, urls()[0].title);
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
+
+ Images img_result;
+ db->GetPageThumbnail(asdf_url, &img_result);
+ EXPECT_TRUE(img_result.thumbnail != NULL);
+ EXPECT_TRUE(ThumbnailsAreEqual(random_thumbnail(), img_result.thumbnail));
+
+ RefCountedBytes* thumbnail_result;
+ EXPECT_TRUE(top_sites().GetPageThumbnail(asdf_url, &thumbnail_result));
+ EXPECT_TRUE(thumbnail_result != NULL);
+ EXPECT_TRUE(ThumbnailsAreEqual(random_thumbnail(), thumbnail_result));
MostVisitedURL url2;
- url2.url = google3_url;
+ url2.url = google1_url;
url2.title = google_title;
url2.redirects.push_back(google1_url);
url2.redirects.push_back(google2_url);
url2.redirects.push_back(google3_url);
- AddPageToHistory(google3_url, url2.title, url2.redirects,
- add_time - base::TimeDelta::FromMinutes(1));
- // Add google twice so that it becomes the first visited site.
- AddPageToHistory(google3_url, url2.title, url2.redirects,
- add_time - base::TimeDelta::FromMinutes(2));
+ // Add new thumbnail at rank 0 and shift the other result to 1.
+ Images g_thumbnail;
+ g_thumbnail.thumbnail = google_thumbnail();
+ db->SetPageThumbnail(url2, 0, g_thumbnail);
+
+ top_sites().ReadDatabase();
+
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ(google1_url, urls()[0].url);
+ EXPECT_EQ(google_title, urls()[0].title);
+ EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &thumbnail_result));
+ EXPECT_TRUE(ThumbnailsAreEqual(google_thumbnail(), thumbnail_result));
+ ASSERT_EQ(3u, urls()[0].redirects.size());
+ EXPECT_EQ(google1_url, urls()[0].redirects[0]);
+ EXPECT_EQ(google2_url, urls()[0].redirects[1]);
+ EXPECT_EQ(google3_url, urls()[0].redirects[2]);
+
+ EXPECT_EQ(asdf_url, urls()[1].url);
+ EXPECT_EQ(asdf_title, urls()[1].title);
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
+
+ MockHistoryServiceImpl hs;
+ // Add one old, one new URL to the history.
+ hs.AppendMockPage(google1_url, google_title);
+ hs.AppendMockPage(news_url, news_title);
+ top_sites().SetMockHistoryService(&hs);
+
+ // This requests data from History Service and writes it to the DB.
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
+
+ std::map<GURL, Images> thumbnails;
+ MostVisitedURLList results;
+ db->GetPageThumbnails(&results, &thumbnails);
+ ASSERT_EQ(4u, results.size());
+ EXPECT_EQ(google_title, results[0].title);
+ EXPECT_EQ(news_title, results[1].title);
+
+ scoped_ptr<SkBitmap> weewar_bitmap(
+ gfx::JPEGCodec::Decode(weewar_thumbnail()->front(),
+ weewar_thumbnail()->size()));
- SkBitmap google_thumbnail(CreateBitmap(SK_ColorBLUE));
- ASSERT_TRUE(top_sites()->SetPageThumbnail(
- url2.url, google_thumbnail, ThumbnailScore()));
+ base::Time now = base::Time::Now();
+ ThumbnailScore low_score(1.0, true, true, now);
+ ThumbnailScore medium_score(0.5, true, true, now);
+ ThumbnailScore high_score(0.0, true, true, now);
- RefreshTopSitesAndRecreate();
+ // 1. Set to weewar. (Writes the thumbnail to the DB.)
+ EXPECT_TRUE(top_sites().SetPageThumbnail(google1_url,
+ *weewar_bitmap,
+ medium_score));
+ RefCountedBytes* out_1;
+ Images out_2;
+ EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &out_1));
- {
- scoped_refptr<RefCountedBytes> read_data;
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(google1_url, querier.urls()[0].url);
- EXPECT_EQ(google_title, querier.urls()[0].title);
- ASSERT_EQ(3u, querier.urls()[0].redirects.size());
- EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
- EXPECT_TRUE(ThumbnailEqualsBytes(google_thumbnail, read_data.get()));
-
- EXPECT_EQ(asdf_url, querier.urls()[1].url);
- EXPECT_EQ(asdf_title, querier.urls()[1].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
- }
+ MessageLoop::current()->RunAllPending();
- SkBitmap weewar_bitmap(CreateBitmap(SK_ColorYELLOW));
+ db->GetPageThumbnail(url2.url, &out_2);
+ EXPECT_TRUE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
- base::Time thumbnail_time(base::Time::Now());
- ThumbnailScore low_score(1.0, true, true, thumbnail_time);
- ThumbnailScore medium_score(0.5, true, true, thumbnail_time);
- ThumbnailScore high_score(0.0, true, true, thumbnail_time);
-
- // 1. Set to weewar. (Writes the thumbnail to the DB.)
- EXPECT_TRUE(top_sites()->SetPageThumbnail(google3_url,
- weewar_bitmap,
- medium_score));
- RefreshTopSitesAndRecreate();
- {
- scoped_refptr<RefCountedBytes> read_data;
- EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
- EXPECT_TRUE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
- }
-
- SkBitmap google_bitmap(CreateBitmap(SK_ColorGREEN));
+ scoped_ptr<SkBitmap> google_bitmap(
+ gfx::JPEGCodec::Decode(google_thumbnail()->front(),
+ google_thumbnail()->size()));
// 2. Set to google - low score.
- EXPECT_FALSE(top_sites()->SetPageThumbnail(google3_url,
- google_bitmap,
- low_score));
+ EXPECT_FALSE(top_sites().SetPageThumbnail(google1_url,
+ *google_bitmap,
+ low_score));
// 3. Set to google - high score.
- EXPECT_TRUE(top_sites()->SetPageThumbnail(google1_url,
- google_bitmap,
- high_score));
-
+ EXPECT_TRUE(top_sites().SetPageThumbnail(google1_url,
+ *google_bitmap,
+ high_score));
// Check that the thumbnail was updated.
- RefreshTopSitesAndRecreate();
- {
- scoped_refptr<RefCountedBytes> read_data;
- EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, &read_data));
- EXPECT_FALSE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
- EXPECT_TRUE(ThumbnailEqualsBytes(google_bitmap, read_data.get()));
- }
+ EXPECT_TRUE(top_sites().GetPageThumbnail(google1_url, &out_1));
+ EXPECT_FALSE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
+ MessageLoop::current()->RunAllPending();
+
+ // Read the new thumbnail from the DB - should match what's in TopSites.
+ db->GetPageThumbnail(url2.url, &out_2);
+ EXPECT_TRUE(ThumbnailsAreEqual(out_1, out_2.thumbnail));
+ EXPECT_TRUE(high_score.Equals(out_2.thumbnail_score));
}
TEST_F(TopSitesTest, DeleteNotifications) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
GURL google1_url("http://google.com");
GURL google2_url("http://google.com/redirect");
GURL google3_url("http://www.google.com");
@@ -807,70 +789,61 @@ TEST_F(TopSitesTest, DeleteNotifications) {
GURL news_url("http://news.google.com");
string16 news_title(ASCIIToUTF16("Google News"));
- AddPageToHistory(google1_url, google_title);
- AddPageToHistory(news_url, news_title);
-
- RefreshTopSitesAndRecreate();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(4u, querier.urls().size());
- }
-
- DeleteURL(news_url);
-
- // Wait for history to process the deletion.
- WaitForHistory();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(google_title, querier.urls()[0].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
- }
-
- // Now reload. This verifies topsites actually wrote the deletion to disk.
- RefreshTopSitesAndRecreate();
+ MockHistoryServiceImpl hs;
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_EQ(google_title, querier.urls()[0].title);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
- }
-
- DeleteURL(google1_url);
-
- // Wait for history to process the deletion.
- WaitForHistory();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
- }
+ top_sites().Init(file_name());
- // Now reload. This verifies topsites actually wrote the deletion to disk.
- RefreshTopSitesAndRecreate();
+ hs.AppendMockPage(google1_url, google_title);
+ hs.AppendMockPage(news_url, news_title);
+ top_sites().SetMockHistoryService(&hs);
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
- ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
- }
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ // 2 extra prepopulated URLs.
+ ASSERT_EQ(4u, urls().size());
+
+ hs.RemoveMostVisitedURL();
+
+ history::URLsDeletedDetails history_details;
+ history_details.all_history = false;
+ Details<URLsDeletedDetails> details(&history_details);
+ top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
+ Source<Profile> (&profile()),
+ details);
+ MessageLoop::current()->RunAllPending();
+
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_EQ(google_title, urls()[0].title);
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
+
+ hs.RemoveMostVisitedURL();
+ history_details.all_history = true;
+ details = Details<HistoryDetails>(&history_details);
+ top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
+ Source<Profile> (&profile()),
+ details);
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(2u, urls().size());
+ EXPECT_EQ(welcome_url(), urls()[0].url);
+ EXPECT_EQ(themes_url(), urls()[1].url);
}
TEST_F(TopSitesTest, PinnedURLsDeleted) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
GURL google1_url("http://google.com");
GURL google2_url("http://google.com/redirect");
GURL google3_url("http://www.google.com");
@@ -878,132 +851,132 @@ TEST_F(TopSitesTest, PinnedURLsDeleted) {
GURL news_url("http://news.google.com");
string16 news_title(ASCIIToUTF16("Google News"));
- AddPageToHistory(google1_url, google_title);
- AddPageToHistory(news_url, news_title);
-
- RefreshTopSitesAndRecreate();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- // 2 extra prepopulated URLs.
- ASSERT_EQ(4u, querier.urls().size());
- }
-
- top_sites()->AddPinnedURL(news_url, 3);
- EXPECT_TRUE(top_sites()->IsURLPinned(news_url));
+ MockHistoryServiceImpl hs;
- DeleteURL(news_url);
- WaitForHistory();
+ top_sites().Init(file_name());
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
-
- // 2 extra prepopulated URLs.
- ASSERT_EQ(3u, querier.urls().size());
- EXPECT_FALSE(top_sites()->IsURLPinned(news_url));
- }
-
- history_service()->ExpireHistoryBetween(
- std::set<GURL>(), base::Time(), base::Time(),
- consumer(), NewCallback(static_cast<TopSitesTest*>(this),
- &TopSitesTest::EmptyCallback)),
- WaitForHistory();
-
- {
- TopSitesQuerier querier;
- querier.QueryTopSites(top_sites(), false);
+ hs.AppendMockPage(google1_url, google_title);
+ hs.AppendMockPage(news_url, news_title);
+ top_sites().SetMockHistoryService(&hs);
- // 2 extra prepopulated URLs.
- ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
- EXPECT_FALSE(top_sites()->IsURLPinned(google1_url));
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
- }
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(1u, number_of_callbacks());
+ // 2 extra prepopulated URLs.
+ ASSERT_EQ(4u, urls().size());
+
+ top_sites().AddPinnedURL(news_url, 3);
+ EXPECT_TRUE(top_sites().IsURLPinned(news_url));
+
+ hs.RemoveMostVisitedURL();
+ history::URLsDeletedDetails history_details;
+ history_details.all_history = false;
+ history_details.urls.insert(news_url);
+ Details<URLsDeletedDetails> details(&history_details);
+ top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
+ Source<Profile> (&profile()),
+ details);
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(2u, number_of_callbacks());
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_FALSE(top_sites().IsURLPinned(news_url));
+
+ hs.RemoveMostVisitedURL();
+ history_details.all_history = true;
+ details = Details<HistoryDetails>(&history_details);
+ top_sites().Observe(NotificationType::HISTORY_URLS_DELETED,
+ Source<Profile> (&profile()),
+ details);
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(2u, urls().size());
+ MessageLoop::current()->RunAllPending();
+
+ top_sites().StartQueryForMostVisited();
+ MessageLoop::current()->RunAllPending();
+ top_sites().GetMostVisitedURLs(
+ consumer(),
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(2u, urls().size());
+ EXPECT_EQ(welcome_url(), urls()[0].url);
+ EXPECT_EQ(themes_url(), urls()[1].url);
}
-// Makes sure GetUpdateDelay is updated appropriately.
TEST_F(TopSitesTest, GetUpdateDelay) {
- SetLastNumUrlsChanged(0);
- EXPECT_EQ(30, GetUpdateDelay().InSeconds());
+ top_sites().last_num_urls_changed_ = 0;
+ EXPECT_EQ(30, top_sites().GetUpdateDelay().InSeconds());
- MostVisitedURLList url_list;
- url_list.resize(20);
- GURL tmp_url(GURL("http://x"));
- for (size_t i = 0; i < url_list.size(); ++i) {
- url_list[i].url = tmp_url;
- url_list[i].redirects.push_back(tmp_url);
- }
- SetTopSites(url_list);
- EXPECT_EQ(20u, last_num_urls_changed());
- SetLastNumUrlsChanged(0);
- EXPECT_EQ(60, GetUpdateDelay().InMinutes());
+ top_sites().top_sites_.resize(20);
+ top_sites().last_num_urls_changed_ = 0;
+ EXPECT_EQ(60, top_sites().GetUpdateDelay().InMinutes());
- SetLastNumUrlsChanged(3);
- EXPECT_EQ(52, GetUpdateDelay().InMinutes());
+ top_sites().last_num_urls_changed_ = 3;
+ EXPECT_EQ(52, top_sites().GetUpdateDelay().InMinutes());
- SetLastNumUrlsChanged(20);
- EXPECT_EQ(1, GetUpdateDelay().InMinutes());
+ top_sites().last_num_urls_changed_ = 20;
+ EXPECT_EQ(1, top_sites().GetUpdateDelay().InMinutes());
}
-TEST_F(TopSitesMigrationTest, Migrate) {
- EXPECT_TRUE(IsTopSitesLoaded());
-
- // Make sure the data was migrated to top sites.
- ASSERT_NO_FATAL_FAILURE(MigrationAssertions());
-
- // We need to wait for top sites and history to finish processing requests.
- WaitForTopSites();
- WaitForHistory();
+TEST_F(TopSitesTest, Migration) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ GURL google1_url("http://google.com");
+ string16 google_title(ASCIIToUTF16("Google"));
+ GURL news_url("http://news.google.com");
+ string16 news_title(ASCIIToUTF16("Google News"));
- // Make sure there is no longer a Thumbnails file on disk.
- ASSERT_FALSE(file_util::PathExists(
- profile()->GetPath().Append(chrome::kThumbnailsFilename)));
+ MockHistoryServiceImpl hs;
- // Make sure the favicon was migrated over correctly.
+ top_sites().Init(file_name());
- // Recreate top sites and make sure everything is still there.
- RecreateTopSitesAndBlock();
+ hs.AppendMockPage(google1_url, google_title);
+ hs.AppendMockPage(news_url, news_title);
+ top_sites().SetMockHistoryService(&hs);
+ MessageLoop::current()->RunAllPending();
- ASSERT_NO_FATAL_FAILURE(MigrationAssertions());
+ top_sites().StartMigration();
+ EXPECT_TRUE(top_sites().migration_in_progress_);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(2, hs.GetNumberOfThumbnailRequests());
+ EXPECT_FALSE(top_sites().migration_in_progress_);
}
-// Verifies that callbacks are notified correctly if requested before top sites
-// has loaded.
-TEST_F(TopSitesTest, NotifyCallbacksWhenLoaded) {
- // Recreate top sites. It won't be loaded now.
- profile()->CreateTopSites();
-
- EXPECT_FALSE(IsTopSitesLoaded());
-
- TopSitesQuerier querier1;
- TopSitesQuerier querier2;
- TopSitesQuerier querier3;
-
- // Starts the queries.
- querier1.QueryTopSites(top_sites(), false);
- querier2.QueryTopSites(top_sites(), false);
- querier3.QueryTopSites(top_sites(), false);
-
- // We shouldn't have gotten a callback.
- EXPECT_EQ(0, querier1.number_of_callbacks());
- EXPECT_EQ(0, querier2.number_of_callbacks());
- EXPECT_EQ(0, querier3.number_of_callbacks());
-
- // Wait for loading to complete.
- HistoryLoaded();
- profile()->BlockUntilTopSitesLoaded();
-
- // Now we should have gotten the callbacks.
- EXPECT_EQ(1, querier1.number_of_callbacks());
- EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
- EXPECT_EQ(1, querier2.number_of_callbacks());
- EXPECT_EQ(GetPrepopulatePages().size(), querier2.urls().size());
- EXPECT_EQ(1, querier3.number_of_callbacks());
- EXPECT_EQ(GetPrepopulatePages().size(), querier3.urls().size());
-
- // Reset the top sites.
+TEST_F(TopSitesTest, QueueingRequestsForTopSites) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ CancelableRequestConsumer c1;
+ CancelableRequestConsumer c2;
+ CancelableRequestConsumer c3;
+ top_sites().GetMostVisitedURLs(
+ &c1,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ top_sites().GetMostVisitedURLs(
+ &c2,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ top_sites().GetMostVisitedURLs(
+ &c3,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ EXPECT_EQ(0u, number_of_callbacks());
+ EXPECT_EQ(0u, urls().size());
+
MostVisitedURLList pages;
MostVisitedURL url;
url.url = GURL("http://1.com/");
@@ -1012,109 +985,109 @@ TEST_F(TopSitesTest, NotifyCallbacksWhenLoaded) {
url.url = GURL("http://2.com/");
url.redirects.push_back(url.url);
pages.push_back(url);
- SetTopSites(pages);
-
- // Recreate top sites. It won't be loaded now.
- profile()->CreateTopSites();
-
- EXPECT_FALSE(IsTopSitesLoaded());
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
- TopSitesQuerier querier4;
+ EXPECT_EQ(3u, number_of_callbacks());
- // Query again.
- querier4.QueryTopSites(top_sites(), false);
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://1.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://2.com/", urls()[1].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
- // We shouldn't have gotten a callback.
- EXPECT_EQ(0, querier4.number_of_callbacks());
- // Wait for loading to complete.
- HistoryLoaded();
- profile()->BlockUntilTopSitesLoaded();
-
- // Now we should have gotten the callbacks.
- EXPECT_EQ(1, querier4.number_of_callbacks());
- ASSERT_EQ(2u + GetPrepopulatePages().size(), querier4.urls().size());
-
- EXPECT_EQ("http://1.com/", querier4.urls()[0].url.spec());
- EXPECT_EQ("http://2.com/", querier4.urls()[1].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier4, 2));
-
- // Reset the top sites again, this time don't reload.
url.url = GURL("http://3.com/");
url.redirects.push_back(url.url);
pages.push_back(url);
- SetTopSites(pages);
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
- // Query again.
- TopSitesQuerier querier5;
- querier5.QueryTopSites(top_sites(), true);
+ top_sites().GetMostVisitedURLs(
+ &c3,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
- EXPECT_EQ(1, querier5.number_of_callbacks());
+ EXPECT_EQ(4u, number_of_callbacks());
+
+ ASSERT_EQ(5u, urls().size());
+ EXPECT_EQ("http://1.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://2.com/", urls()[1].url.spec());
+ EXPECT_EQ("http://3.com/", urls()[2].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[3].url);
+ EXPECT_EQ(themes_url(), urls()[4].url);
- ASSERT_EQ(3u + GetPrepopulatePages().size(), querier5.urls().size());
- EXPECT_EQ("http://1.com/", querier5.urls()[0].url.spec());
- EXPECT_EQ("http://2.com/", querier5.urls()[1].url.spec());
- EXPECT_EQ("http://3.com/", querier5.urls()[2].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier5, 3));
}
-// Makes sure canceled requests are not notified.
TEST_F(TopSitesTest, CancelingRequestsForTopSites) {
- // Recreate top sites. It won't be loaded now.
- profile()->CreateTopSites();
-
- EXPECT_FALSE(IsTopSitesLoaded());
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ CancelableRequestConsumer c1;
+ CancelableRequestConsumer c2;
+ top_sites().GetMostVisitedURLs(
+ &c1,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ top_sites().GetMostVisitedURLs(
+ &c2,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
- TopSitesQuerier querier1;
- TopSitesQuerier querier2;
-
- // Starts the queries.
- querier1.QueryTopSites(top_sites(), false);
- querier2.QueryTopSites(top_sites(), false);
+ {
+ CancelableRequestConsumer c3;
+ top_sites().GetMostVisitedURLs(
+ &c3,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ // c3 is out of scope, and the request should be cancelled.
+ }
- // We shouldn't have gotten a callback.
- EXPECT_EQ(0, querier1.number_of_callbacks());
- EXPECT_EQ(0, querier2.number_of_callbacks());
+ // No requests until OnTopSitesAvailable is called.
+ EXPECT_EQ(0u, number_of_callbacks());
+ EXPECT_EQ(0u, urls().size());
- querier2.CancelRequest();
+ MostVisitedURLList pages;
+ MostVisitedURL url;
+ url.url = GURL("http://1.com/");
+ url.redirects.push_back(url.url);
+ pages.push_back(url);
+ url.url = GURL("http://2.com/");
+ pages.push_back(url);
- // Wait for loading to complete.
- HistoryLoaded();
- profile()->BlockUntilTopSitesLoaded();
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
- // The first callback should succeed.
- EXPECT_EQ(1, querier1.number_of_callbacks());
- EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
+ // 1 request was canceled.
+ EXPECT_EQ(2u, number_of_callbacks());
- // And the canceled callback should not be notified.
- EXPECT_EQ(0, querier2.number_of_callbacks());
+ // 2 extra prepopulated URLs.
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://1.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://2.com/", urls()[1].url.spec());
}
-// Makes sure temporary thumbnails are copied over correctly.
TEST_F(TopSitesTest, AddTemporaryThumbnail) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
GURL unknown_url("http://news.google.com/");
GURL invalid_url("chrome://thumb/http://google.com/");
GURL url1a("http://google.com/");
GURL url1b("http://www.google.com/");
// Create a dummy thumbnail.
- SkBitmap thumbnail(CreateBitmap(SK_ColorRED));
+ SkBitmap thumbnail;
+ thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
+ thumbnail.allocPixels();
+ thumbnail.eraseRGB(0x00, 0x00, 0x00);
ThumbnailScore medium_score(0.5, true, true, base::Time::Now());
// Don't store thumbnails for Javascript URLs.
- EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
- thumbnail,
- medium_score));
+ EXPECT_FALSE(top_sites().SetPageThumbnail(invalid_url,
+ thumbnail, medium_score));
// Store thumbnails for unknown (but valid) URLs temporarily - calls
// AddTemporaryThumbnail.
- EXPECT_TRUE(top_sites()->SetPageThumbnail(unknown_url,
- thumbnail,
- medium_score));
-
- // We shouldn't get the thumnail back though (the url isn't in to sites yet).
- scoped_refptr<RefCountedBytes> out;
- EXPECT_FALSE(top_sites()->GetPageThumbnail(unknown_url, &out));
+ EXPECT_TRUE(top_sites().SetPageThumbnail(unknown_url,
+ thumbnail, medium_score));
std::vector<MostVisitedURL> list;
@@ -1125,15 +1098,19 @@ TEST_F(TopSitesTest, AddTemporaryThumbnail) {
mv.redirects.push_back(url1b);
list.push_back(mv);
- // Update URLs. This should result in using thumbnail.
- SetTopSites(list);
+ // Update URLs - use temporary thumbnails.
+ top_sites().UpdateMostVisited(list);
- ASSERT_TRUE(top_sites()->GetPageThumbnail(unknown_url, &out));
- EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, out.get()));
+ RefCountedBytes* out = NULL;
+ ASSERT_TRUE(top_sites().GetPageThumbnail(unknown_url, &out));
+ scoped_ptr<SkBitmap> out_bitmap(gfx::JPEGCodec::Decode(out->front(),
+ out->size()));
+ EXPECT_EQ(0, memcmp(thumbnail.getPixels(), out_bitmap->getPixels(),
+ thumbnail.getSize()));
}
-// Tests variations of blacklisting.
TEST_F(TopSitesTest, Blacklisting) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
MostVisitedURLList pages;
MostVisitedURL url, url1;
url.url = GURL("http://bbc.com/");
@@ -1143,83 +1120,91 @@ TEST_F(TopSitesTest, Blacklisting) {
url1.redirects.push_back(url1.url);
pages.push_back(url1);
- SetTopSites(pages);
- EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
-
- // Blacklist google.com.
- top_sites()->AddBlacklistedURL(GURL("http://google.com/"));
-
- GURL prepopulate_url = GetPrepopulatePages()[0].url;
-
- EXPECT_TRUE(top_sites()->HasBlacklistedItems());
- EXPECT_TRUE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
- EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
- EXPECT_FALSE(top_sites()->IsBlacklisted(prepopulate_url));
-
- // Make sure the blacklisted site isn't returned in the results.
+ CancelableRequestConsumer c;
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
{
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
+ Lock& l = lock();
+ AutoLock lock(l); // IsBlacklisted must be in a lock.
+ EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://bbc.com/")));
}
- // Recreate top sites and make sure blacklisted url was correctly read.
- RecreateTopSitesAndBlock();
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
- }
+ EXPECT_EQ(1u, number_of_callbacks());
- // Blacklist one of the prepopulate urls.
- top_sites()->AddBlacklistedURL(prepopulate_url);
- EXPECT_TRUE(top_sites()->HasBlacklistedItems());
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[1].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
+ EXPECT_FALSE(top_sites().HasBlacklistedItems());
- // Make sure the blacklisted prepopulate url isn't returned.
+ top_sites().AddBlacklistedURL(GURL("http://google.com/"));
+ EXPECT_TRUE(top_sites().HasBlacklistedItems());
{
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(1u + GetPrepopulatePages().size() - 1, q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- for (size_t i = 1; i < q.urls().size(); ++i)
- EXPECT_NE(prepopulate_url.spec(), q.urls()[i].url.spec());
+ Lock& l = lock();
+ AutoLock lock(l); // IsBlacklisted must be in a lock.
+ EXPECT_TRUE(top_sites().IsBlacklisted(GURL("http://google.com/")));
+ EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://bbc.com/")));
+ EXPECT_FALSE(top_sites().IsBlacklisted(welcome_url()));
}
- // Mark google as no longer blacklisted.
- top_sites()->RemoveBlacklistedURL(GURL("http://google.com/"));
- EXPECT_TRUE(top_sites()->HasBlacklistedItems());
- EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
-
- // Make sure google is returned now.
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(2u, number_of_callbacks());
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
+
+ top_sites().AddBlacklistedURL(welcome_url());
+ EXPECT_TRUE(top_sites().HasBlacklistedItems());
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(2u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ(themes_url(), urls()[1].url);
+
+ top_sites().RemoveBlacklistedURL(GURL("http://google.com/"));
+ EXPECT_TRUE(top_sites().HasBlacklistedItems());
{
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(2u + GetPrepopulatePages().size() - 1, q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
- EXPECT_NE(prepopulate_url.spec(), q.urls()[2].url.spec());
+ Lock& l = lock();
+ AutoLock lock(l); // IsBlacklisted must be in a lock.
+ EXPECT_FALSE(top_sites().IsBlacklisted(GURL("http://google.com/")));
}
- // Remove all blacklisted sites.
- top_sites()->ClearBlacklistedURLs();
- EXPECT_FALSE(top_sites()->HasBlacklistedItems());
-
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
- }
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(3u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[1].url.spec());
+ EXPECT_EQ(themes_url(), urls()[2].url);
+
+ top_sites().ClearBlacklistedURLs();
+ EXPECT_FALSE(top_sites().HasBlacklistedItems());
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[1].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
}
-// Tests variations of pinning/unpinning urls.
TEST_F(TopSitesTest, PinnedURLs) {
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
MostVisitedURLList pages;
MostVisitedURL url, url1;
url.url = GURL("http://bbc.com/");
@@ -1229,106 +1214,127 @@ TEST_F(TopSitesTest, PinnedURLs) {
url1.redirects.push_back(url1.url);
pages.push_back(url1);
- SetTopSites(pages);
-
- EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://bbc.com/")));
-
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
- }
-
- top_sites()->AddPinnedURL(GURL("http://google.com/"), 3);
- EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://bbc.com/")));
- EXPECT_FALSE(top_sites()->IsURLPinned(GetPrepopulatePages()[0].url));
-
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- ASSERT_EQ(4u, q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
- EXPECT_EQ("http://google.com/", q.urls()[3].url.spec());
- }
-
- top_sites()->RemovePinnedURL(GURL("http://google.com/"));
- EXPECT_FALSE(top_sites()->IsURLPinned(GURL("http://google.com/")));
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
-
- ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
- EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
- }
-
- GURL prepopulate_url = GetPrepopulatePages()[0].url;
- top_sites()->AddPinnedURL(GURL("http://bbc.com"), 1);
- top_sites()->AddPinnedURL(prepopulate_url, 0);
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
-
- ASSERT_EQ(3u + GetPrepopulatePages().size() - 1, q.urls().size());
- EXPECT_EQ(prepopulate_url, q.urls()[0].url);
- EXPECT_EQ("http://bbc.com/", q.urls()[1].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[2].url.spec());
- if (GetPrepopulatePages().size() > 1)
- EXPECT_EQ(GetPrepopulatePages()[1].url, q.urls()[3].url);
- }
-
- // Recreate and make sure state remains the same.
- RecreateTopSitesAndBlock();
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
-
- ASSERT_EQ(3u + GetPrepopulatePages().size() - 1, q.urls().size());
- EXPECT_EQ(prepopulate_url, q.urls()[0].url);
- EXPECT_EQ("http://bbc.com/", q.urls()[1].url.spec());
- EXPECT_EQ("http://google.com/", q.urls()[2].url.spec());
- if (GetPrepopulatePages().size() > 1)
- EXPECT_EQ(GetPrepopulatePages()[1].url, q.urls()[3].url);
- }
+ CancelableRequestConsumer c;
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://bbc.com/")));
+
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[1].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
+
+ top_sites().AddPinnedURL(GURL("http://google.com/"), 3);
+ EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://bbc.com/")));
+ EXPECT_FALSE(top_sites().IsURLPinned(welcome_url()));
+
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ EXPECT_EQ(2u, number_of_callbacks());
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
+ EXPECT_EQ("http://google.com/", urls()[3].url.spec());
+
+ top_sites().RemovePinnedURL(GURL("http://google.com/"));
+ EXPECT_FALSE(top_sites().IsURLPinned(GURL("http://google.com/")));
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://bbc.com/", urls()[0].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[1].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[2].url);
+ EXPECT_EQ(themes_url(), urls()[3].url);
+
+ top_sites().AddPinnedURL(GURL("http://bbc.com"), 1);
+ top_sites().AddPinnedURL(themes_url(), 0);
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ(themes_url(), urls()[0].url);
+ EXPECT_EQ("http://bbc.com/", urls()[1].url.spec());
+ EXPECT_EQ("http://google.com/", urls()[2].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[3].url);
+
+ top_sites().RemovePinnedURL(GURL("http://bbc.com"));
+ top_sites().RemovePinnedURL(themes_url());
+
+ top_sites().AddPinnedURL(welcome_url(), 1);
+ top_sites().AddPinnedURL(GURL("http://bbc.com"), 3);
+
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ ASSERT_EQ(4u, urls().size());
+ EXPECT_EQ("http://google.com/", urls()[0].url.spec());
+ EXPECT_EQ(welcome_url(), urls()[1].url);
+ EXPECT_EQ(themes_url(), urls()[2].url);
+ EXPECT_EQ("http://bbc.com/", urls()[3].url.spec());
}
-// Tests blacklisting and pinning.
TEST_F(TopSitesTest, BlacklistingAndPinnedURLs) {
- MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
- if (prepopulate_urls.size() < 2)
- return;
-
- top_sites()->AddPinnedURL(prepopulate_urls[0].url, 1);
- top_sites()->AddBlacklistedURL(prepopulate_urls[1].url);
-
- {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
+ BrowserThread db_loop(BrowserThread::DB, MessageLoop::current());
+ MostVisitedURLList pages;
+ CancelableRequestConsumer c;
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+ top_sites().OnTopSitesAvailable(0, pages);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(2u, urls().size());
+ EXPECT_EQ(welcome_url(), urls()[0].url);
+ EXPECT_EQ(themes_url(), urls()[1].url);
+
+ top_sites().AddPinnedURL(themes_url(), 1);
+ top_sites().AddBlacklistedURL(welcome_url());
+
+ top_sites().GetMostVisitedURLs(
+ &c,
+ NewCallback(static_cast<TopSitesTest*>(this),
+ &TopSitesTest::OnTopSitesAvailable));
+
+ ASSERT_EQ(2u, urls().size());
+ EXPECT_EQ(GURL(), urls()[0].url);
+ EXPECT_EQ(themes_url(), urls()[1].url);
- ASSERT_LE(2u, q.urls().size());
- EXPECT_EQ(GURL(), q.urls()[0].url);
- EXPECT_EQ(prepopulate_urls[0].url, q.urls()[1].url);
- }
}
-// Makes sure prepopulated pages exist.
TEST_F(TopSitesTest, AddPrepopulatedPages) {
- TopSitesQuerier q;
- q.QueryTopSites(top_sites(), true);
- EXPECT_EQ(GetPrepopulatePages().size(), q.urls().size());
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
+ MostVisitedURLList pages;
+ top_sites().AddPrepopulatedPages(&pages);
+ ASSERT_EQ(2u, pages.size());
+ EXPECT_EQ(welcome_url(), pages[0].url);
+ EXPECT_EQ(themes_url(), pages[1].url);
+
+ pages.clear();
+
+ MostVisitedURL url(themes_url(), GURL(), string16());
+ pages.push_back(url);
- MostVisitedURLList pages = q.urls();
- EXPECT_FALSE(AddPrepopulatedPages(&pages));
+ top_sites().AddPrepopulatedPages(&pages);
- EXPECT_EQ(GetPrepopulatePages().size(), pages.size());
- q.set_urls(pages);
- ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
+ // Themes URL is already in pages; should not be added twice.
+ ASSERT_EQ(2u, pages.size());
+ EXPECT_EQ(themes_url(), pages[0].url);
+ EXPECT_EQ(welcome_url(), pages[1].url);
}
} // namespace history
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index e2574d7..8304c8d 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -513,7 +513,7 @@ ProfileImpl::~ProfileImpl() {
web_data_service_->Shutdown();
if (top_sites_.get())
- top_sites_->Shutdown();
+ top_sites_->ClearProfile();
if (history_service_.get())
history_service_->Cleanup();
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index c710191..c7e68ea 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2566,11 +2566,8 @@ void TabContents::UpdateThumbnail(const GURL& url,
const ThumbnailScore& score) {
// Tell History about this thumbnail
if (history::TopSites::IsEnabled()) {
- if (!profile()->IsOffTheRecord()) {
- history::TopSites* ts = profile()->GetTopSites();
- if (ts)
- ts->SetPageThumbnail(url, bitmap, score);
- }
+ if (!profile()->IsOffTheRecord())
+ profile()->GetTopSites()->SetPageThumbnail(url, bitmap, score);
} else {
HistoryService* hs;
if (!profile()->IsOffTheRecord() &&
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 498fb37..d9f8e78 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2013,13 +2013,7 @@
'browser/history/thumbnail_database.cc',
'browser/history/thumbnail_database.h',
'browser/history/top_sites.cc',
- 'browser/history/top_sites.h',
- 'browser/history/top_sites_backend.cc',
- 'browser/history/top_sites_backend.h',
- 'browser/history/top_sites_cache.cc',
- 'browser/history/top_sites_cache.h',
'browser/history/top_sites_database.cc',
- 'browser/history/top_sites_database.h',
'browser/history/url_database.cc',
'browser/history/url_database.h',
'browser/history/visit_database.cc',
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index c9300db..4fa44f2 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -649,12 +649,6 @@ class NotificationType {
// none and the source is a Profile*.
PROFILE_DESTROYED,
- // TopSites ----------------------------------------------------------------
-
- // Sent by TopSites when it finishes loading. The source is the profile the
- // details the TopSites.
- TOP_SITES_LOADED,
-
// Thumbnails---------------------------------------------------------------
// Sent by the ThumbnailGenerator whenever a render widget host
diff --git a/chrome/test/data/profiles/typical_history/Default/History b/chrome/test/data/profiles/typical_history/Default/History
index 6a6abd6..b1b3893 100644
--- a/chrome/test/data/profiles/typical_history/Default/History
+++ b/chrome/test/data/profiles/typical_history/Default/History
Binary files differ
diff --git a/chrome/test/data/top_sites/history.19.sql b/chrome/test/data/top_sites/history.19.sql
deleted file mode 100644
index 69aa0f7..0000000
--- a/chrome/test/data/top_sites/history.19.sql
+++ /dev/null
@@ -1,38 +0,0 @@
-BEGIN TRANSACTION;
-CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
-INSERT INTO "meta" VALUES('version','19');
-INSERT INTO "meta" VALUES('last_compatible_version','16');
-CREATE TABLE urls(id INTEGER PRIMARY KEY,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL,favicon_id INTEGER DEFAULT 0 NOT NULL);
-INSERT INTO "urls" VALUES(1,'http://google.com/','Google',1,1,12931898015280853,0,1);
-INSERT INTO "urls" VALUES(2,'http://www.google.com/','Google',1,0,12931898015280853,0,1);
-INSERT INTO "urls" VALUES(3,'http://www.google.com/blank.html','',1,0,12931898015572853,1,0);
-INSERT INTO "urls" VALUES(4,'http://yahoo.com/','Yahoo!',1,1,12931898025843853,0,2);
-INSERT INTO "urls" VALUES(5,'http://www.yahoo.com/','Yahoo!',1,0,12931898025843853,0,2);
-CREATE TABLE visits(id INTEGER PRIMARY KEY,url INTEGER NOT NULL,visit_time INTEGER NOT NULL,from_visit INTEGER,transition INTEGER DEFAULT 0 NOT NULL,segment_id INTEGER,is_indexed BOOLEAN);
-INSERT INTO "visits" VALUES(1,1,12931898015280853,0,268435457,1,0);
-INSERT INTO "visits" VALUES(2,2,12931898015280853,1,2684354561,0,1);
-INSERT INTO "visits" VALUES(3,3,12931898015572853,0,805306371,0,0);
-INSERT INTO "visits" VALUES(4,4,12931898025843853,0,268435457,2,0);
-INSERT INTO "visits" VALUES(5,5,12931898025843853,4,2684354561,0,1);
-CREATE TABLE visit_source(id INTEGER PRIMARY KEY,source INTEGER NOT NULL);
-CREATE TABLE keyword_search_terms (keyword_id INTEGER NOT NULL,url_id INTEGER NOT NULL,lower_term LONGVARCHAR NOT NULL,term LONGVARCHAR NOT NULL);
-CREATE TABLE downloads (id INTEGER PRIMARY KEY,full_path LONGVARCHAR NOT NULL,url LONGVARCHAR NOT NULL,start_time INTEGER NOT NULL,received_bytes INTEGER NOT NULL,total_bytes INTEGER NOT NULL,state INTEGER NOT NULL);
-CREATE TABLE segments (id INTEGER PRIMARY KEY,name VARCHAR,url_id INTEGER NON NULL,pres_index INTEGER DEFAULT -1 NOT NULL);
-INSERT INTO "segments" VALUES(1,'http://google.com/',1,-1);
-INSERT INTO "segments" VALUES(2,'http://yahoo.com/',4,-1);
-CREATE TABLE segment_usage (id INTEGER PRIMARY KEY,segment_id INTEGER NOT NULL,time_slot INTEGER NOT NULL,visit_count INTEGER DEFAULT 0 NOT NULL);
-INSERT INTO "segment_usage" VALUES(1,1,12931858800000000,1);
-INSERT INTO "segment_usage" VALUES(2,2,12931858800000000,1);
-CREATE TABLE presentation(url_id INTEGER PRIMARY KEY,pres_index INTEGER NOT NULL);
-CREATE INDEX visits_url_index ON visits (url);
-CREATE INDEX visits_from_index ON visits (from_visit);
-CREATE INDEX visits_time_index ON visits (visit_time);
-CREATE INDEX keyword_search_terms_index1 ON keyword_search_terms (keyword_id, lower_term);
-CREATE INDEX keyword_search_terms_index2 ON keyword_search_terms (url_id);
-CREATE INDEX segments_name ON segments(name);
-CREATE INDEX segments_url_id ON segments(url_id);
-CREATE INDEX segment_usage_time_slot_segment_id ON segment_usage(time_slot, segment_id);
-CREATE INDEX segments_usage_seg_id ON segment_usage(segment_id);
-CREATE INDEX urls_url_index ON urls (url);
-CREATE INDEX urls_favicon_id_INDEX ON urls (favicon_id);
-COMMIT;
diff --git a/chrome/test/data/top_sites/thumbnails.3.sql b/chrome/test/data/top_sites/thumbnails.3.sql
deleted file mode 100644
index 1e05945..0000000
--- a/chrome/test/data/top_sites/thumbnails.3.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-BEGIN TRANSACTION;
-CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
-INSERT INTO "meta" VALUES('version','3');
-INSERT INTO "meta" VALUES('last_compatible_version','3');
-CREATE TABLE thumbnails (url_id INTEGER PRIMARY KEY,boring_score DOUBLE DEFAULT 1.0,good_clipping INTEGER DEFAULT 0,at_top INTEGER DEFAULT 0,last_updated INTEGER DEFAULT 0,data BLOB);
-INSERT INTO "thumbnails" VALUES(2,0.826007718696398,1,1,1287424416,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080001000103012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-INSERT INTO "thumbnails" VALUES(5,0.223699256718125,1,1,1287424428,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080002000203012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-CREATE TABLE favicons(id INTEGER PRIMARY KEY,url LONGVARCHAR NOT NULL,last_updated INTEGER DEFAULT 0,image_data BLOB);
-INSERT INTO "favicons" VALUES(1,'http://www.google.com/favicon.ico',1287424416,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080002000203012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-INSERT INTO "favicons" VALUES(2,'http://www.yahoo.com/favicon.ico',1287424428,X'FFD8FFE000104A46494600010100000100010000FFDB0043000302020302020303030304030304050805050404050A070706080C0A0C0C0B0A0B0B0D0E12100D0E110E0B0B1016101113141515150C0F171816141812141514FFDB00430103040405040509050509140D0B0D1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414FFC00011080003000303012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F9D28A28AFC30FF54CFFD9');
-CREATE INDEX favicons_url ON favicons(url);
-COMMIT;
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 2b3624b..829fcc9 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -39,7 +39,6 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_pref_service.h"
-#include "chrome/test/ui_test_utils.h"
#include "net/base/cookie_monster.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_unittest.h"
@@ -195,19 +194,13 @@ TestingProfile::~TestingProfile() {
NotificationType::PROFILE_DESTROYED,
Source<Profile>(this),
NotificationService::NoDetails());
- if (top_sites_.get()) {
- top_sites_->Shutdown();
- top_sites_ = NULL;
- // TopSites::Shutdown schedules some tasks (from TopSitesBackend) that need
- // to be run to properly shutdown. Run all pending tasks now. This is
- // normally handled by browser_process shutdown.
- if (MessageLoop::current())
- MessageLoop::current()->RunAllPending();
- }
DestroyHistoryService();
// FaviconService depends on HistoryServce so destroying it later.
DestroyFaviconService();
DestroyWebDataService();
+ if (top_sites_.get())
+ top_sites_->ClearProfile();
+ history::TopSites::DeleteTopSites(top_sites_);
if (extensions_service_.get()) {
extensions_service_->DestroyingProfile();
extensions_service_ = NULL;
@@ -234,17 +227,6 @@ void TestingProfile::CreateHistoryService(bool delete_file, bool no_db) {
history_service_->Init(GetPath(), bookmark_bar_model_.get(), no_db);
}
-void TestingProfile::CreateTopSites() {
- if (top_sites_.get()) {
- top_sites_->Shutdown();
- top_sites_ = NULL;
- }
-
- top_sites_ = new history::TopSites(this);
- FilePath file_name = temp_dir_.path().Append(chrome::kTopSitesFilename);
- top_sites_->Init(file_name);
-}
-
void TestingProfile::DestroyFaviconService() {
if (!favicon_service_.get())
return;
@@ -321,12 +303,6 @@ void TestingProfile::BlockUntilBookmarkModelLoaded() {
DCHECK(bookmark_bar_model_->IsLoaded());
}
-void TestingProfile::BlockUntilTopSitesLoaded() {
- if (!GetHistoryService(Profile::EXPLICIT_ACCESS))
- GetTopSites()->HistoryLoaded();
- ui_test_utils::WaitForNotification(NotificationType::TOP_SITES_LOADED);
-}
-
void TestingProfile::CreateTemplateURLFetcher() {
template_url_fetcher_.reset(new TemplateURLFetcher(this));
}
@@ -416,7 +392,12 @@ PrefService* TestingProfile::GetPrefs() {
}
history::TopSites* TestingProfile::GetTopSites() {
- return top_sites_.get();
+ if (!top_sites_.get()) {
+ top_sites_ = new history::TopSites(this);
+ FilePath file_name = temp_dir_.path().AppendASCII("TopSites.db");
+ top_sites_->Init(file_name);
+ }
+ return top_sites_;
}
URLRequestContextGetter* TestingProfile::GetRequestContext() {
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index c36a5ec..b1395c0 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -56,8 +56,6 @@ class TestingProfile : public Profile {
// for testing error conditions.
void CreateHistoryService(bool delete_file, bool no_db);
- void CreateTopSites();
-
// Creates the BookmkarBarModel. If not invoked the bookmark bar model is
// NULL. If |delete_file| is true, the bookmarks file is deleted first, then
// the model is created. As TestingProfile deletes the directory containing
@@ -82,10 +80,6 @@ class TestingProfile : public Profile {
// CreateBookmarkModel.
void BlockUntilBookmarkModelLoaded();
- // Blocks until TopSites finishes loading.
- void BlockUntilTopSitesLoaded();
-
- // Creates a TemplateURLModel. If not invoked the TemplateURLModel is NULL.
// Creates a TemplateURLFetcher. If not invoked, the TemplateURLFetcher is
// NULL.
void CreateTemplateURLFetcher();