diff options
-rw-r--r-- | chrome/browser/browser.vcproj | 12 | ||||
-rw-r--r-- | chrome/browser/browser.vsprops | 2 | ||||
-rw-r--r-- | chrome/browser/history/expire_history_backend_unittest.cc | 17 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.cc | 28 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.h | 5 | ||||
-rw-r--r-- | chrome/browser/history/history_backend_unittest.cc | 10 | ||||
-rw-r--r-- | chrome/browser/history/history_indexer.idl | 45 | ||||
-rw-r--r-- | chrome/browser/history/history_publisher.cc | 156 | ||||
-rw-r--r-- | chrome/browser/history/history_publisher.h | 81 | ||||
-rw-r--r-- | chrome/browser/history/text_database_manager.cc | 10 | ||||
-rw-r--r-- | chrome/browser/history/text_database_manager.h | 10 | ||||
-rw-r--r-- | chrome/browser/history/text_database_manager_unittest.cc | 22 | ||||
-rw-r--r-- | chrome/browser/history/thumbnail_database.cc | 18 | ||||
-rw-r--r-- | chrome/browser/history/thumbnail_database.h | 16 | ||||
-rw-r--r-- | chrome/browser/history/thumbnail_database_unittest.cc | 76 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_bar_view.cc | 2 |
16 files changed, 447 insertions, 63 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index f83558f..2b8bf3d 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -1326,6 +1326,10 @@ > </File> <File + RelativePath=".\history\history_indexer.idl" + > + </File> + <File RelativePath=".\history\history_marshaling.h" > </File> @@ -1334,6 +1338,14 @@ > </File> <File + RelativePath=".\history\history_publisher.cc" + > + </File> + <File + RelativePath=".\history\history_publisher.h" + > + </File> + <File RelativePath=".\history\history_types.cc" > </File> diff --git a/chrome/browser/browser.vsprops b/chrome/browser/browser.vsprops index a66aa02..b978e89 100644 --- a/chrome/browser/browser.vsprops +++ b/chrome/browser/browser.vsprops @@ -7,7 +7,7 @@ > <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(OutDir)\webkit";..\third_party\webkit\out" + AdditionalIncludeDirectories=""$(IntDir)\..\browser";"$(OutDir)\webkit";..\third_party\webkit\out" PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE" /> <Tool diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc index 7195cdb..f3e6a8b 100644 --- a/chrome/browser/history/expire_history_backend_unittest.cc +++ b/chrome/browser/history/expire_history_backend_unittest.cc @@ -115,12 +115,12 @@ class ExpireHistoryTest : public testing::Test, std::wstring thumb_name(dir_); file_util::AppendToPath(&thumb_name, L"Thumbnails"); thumb_db_.reset(new ThumbnailDatabase); - if (thumb_db_->Init(thumb_name) != INIT_OK) + if (thumb_db_->Init(thumb_name, NULL) != INIT_OK) thumb_db_.reset(); text_db_.reset(new TextDatabaseManager(dir_, main_db_.get(), main_db_.get())); - if (!text_db_->Init()) + if (!text_db_->Init(NULL)) text_db_.reset(); expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(), @@ -199,9 +199,12 @@ void ExpireHistoryTest::AddExampleData(URLID url_ids[3], Time visit_times[4]) { scoped_ptr<SkBitmap> thumbnail( JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail))); ThumbnailScore score(0.25, true, true, Time::Now()); - thumb_db_->SetPageThumbnail(url_ids[0], *thumbnail, score); - thumb_db_->SetPageThumbnail(url_ids[1], *thumbnail, score); - thumb_db_->SetPageThumbnail(url_ids[2], *thumbnail, score); + + Time time; + GURL gurl; + thumb_db_->SetPageThumbnail(gurl, url_ids[0], *thumbnail, score, time); + thumb_db_->SetPageThumbnail(gurl, url_ids[1], *thumbnail, score, time); + thumb_db_->SetPageThumbnail(gurl, url_ids[2], *thumbnail, score, time); // Four visits. VisitRow visit_row1; @@ -400,7 +403,7 @@ TEST_F(ExpireHistoryTest, DeleteURLAndFavicon) { text_db_.reset(); EXPECT_TRUE(IsStringInFile(fts_filename, "goats")); text_db_.reset(new TextDatabaseManager(dir_, main_db_.get(), main_db_.get())); - ASSERT_TRUE(text_db_->Init()); + ASSERT_TRUE(text_db_->Init(NULL)); expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(), text_db_.get()); @@ -412,7 +415,7 @@ TEST_F(ExpireHistoryTest, DeleteURLAndFavicon) { text_db_.reset(); EXPECT_FALSE(IsStringInFile(fts_filename, "goats")); text_db_.reset(new TextDatabaseManager(dir_, main_db_.get(), main_db_.get())); - ASSERT_TRUE(text_db_->Init()); + ASSERT_TRUE(text_db_->Init(NULL)); expirer_.SetDatabases(main_db_.get(), archived_db_.get(), thumb_db_.get(), text_db_.get()); diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index c3bdd4a..d904148 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -15,6 +15,7 @@ #include "chrome/browser/autocomplete/history_url_provider.h" #include "chrome/browser/bookmarks/bookmark_service.h" #include "chrome/browser/history/download_types.h" +#include "chrome/browser/history/history_publisher.h" #include "chrome/browser/history/in_memory_history_backend.h" #include "chrome/browser/history/page_usage_data.h" #include "chrome/common/chrome_constants.h" @@ -531,18 +532,28 @@ void HistoryBackend::InitImpl() { delete mem_backend; // Error case, run without the in-memory DB. db_->BeginExclusiveMode(); // Must be after the mem backend read the data. + // Create the history publisher which needs to be passed on to the text and + // thumbnail databases for publishing history. + history_publisher_.reset(new HistoryPublisher()); + if (!history_publisher_->Init()) { + // The init may fail when there are no indexers wanting our history. + // Hence no need to log the failure. + history_publisher_.reset(); + } + // Full-text database. This has to be first so we can pass it to the // HistoryDatabase for migration. text_database_.reset(new TextDatabaseManager(history_dir_, db_.get(), db_.get())); - if (!text_database_->Init()) { + if (!text_database_->Init(history_publisher_.get())) { LOG(WARNING) << "Text database initialization failed, running without it."; text_database_.reset(); } // Thumbnail database. thumbnail_db_.reset(new ThumbnailDatabase()); - if (thumbnail_db_->Init(thumbnail_name) != INIT_OK) { + if (thumbnail_db_->Init(thumbnail_name, + history_publisher_.get()) != INIT_OK) { // Unlike the main database, we don't error out when the database is too // new because this error is much less severe. Generally, this shouldn't // happen since the thumbnail and main datbase versions should be in sync. @@ -1185,9 +1196,13 @@ void HistoryBackend::SetPageThumbnail( if (!db_.get() || !thumbnail_db_.get()) return; - URLID url_id = db_->GetRowForURL(url, NULL); - if (url_id) - thumbnail_db_->SetPageThumbnail(url_id, thumbnail, score); + URLRow url_row; + URLID url_id = db_->GetRowForURL(url, &url_row); + if (url_id) { + thumbnail_db_->SetPageThumbnail(url, url_id, thumbnail, score, + url_row.last_visit()); + } + ScheduleCommit(); } @@ -1617,6 +1632,9 @@ void HistoryBackend::ExpireHistoryBetween( } request->ForwardResult(ExpireHistoryRequest::TupleType()); + + if (history_publisher_.get()) + history_publisher_->DeleteUserHistoryBetween(begin_time, end_time); } void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index b03a781..a7c9310 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h @@ -31,6 +31,7 @@ struct ThumbnailScore; namespace history { class CommitLaterTask; +class HistoryPublisher; // *See the .cc file for more information on the design.* // @@ -484,6 +485,10 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, // loaded. BookmarkService* bookmark_service_; + // Publishes the history to all indexers which are registered to receive + // history data from us. Can be NULL if there are no listeners. + scoped_ptr<HistoryPublisher> history_publisher_; + DISALLOW_EVIL_CONSTRUCTORS(HistoryBackend); }; diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index a762df4..2f9bcf4 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc @@ -12,6 +12,7 @@ #include "chrome/common/jpeg_codec.h" #include "chrome/common/thumbnail_score.h" #include "chrome/tools/profiles/thumbnail-inl.h" +#include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; @@ -195,10 +196,15 @@ TEST_F(HistoryBackendTest, DeleteAll) { ThumbnailScore score(0.25, true, true); scoped_ptr<SkBitmap> google_bitmap( JPEGCodec::Decode(kGoogleThumbnail, sizeof(kGoogleThumbnail))); - backend_->thumbnail_db_->SetPageThumbnail(row1_id, *google_bitmap, score); + + Time time; + GURL gurl; + backend_->thumbnail_db_->SetPageThumbnail(gurl, row1_id, *google_bitmap, + score, time); scoped_ptr<SkBitmap> weewar_bitmap( JPEGCodec::Decode(kWeewarThumbnail, sizeof(kWeewarThumbnail))); - backend_->thumbnail_db_->SetPageThumbnail(row2_id, *weewar_bitmap, score); + backend_->thumbnail_db_->SetPageThumbnail(gurl, row2_id, *weewar_bitmap, + score, time); // Star row1. bookmark_model_.AddURL( diff --git a/chrome/browser/history/history_indexer.idl b/chrome/browser/history/history_indexer.idl new file mode 100644 index 0000000..132c5f0 --- /dev/null +++ b/chrome/browser/history/history_indexer.idl @@ -0,0 +1,45 @@ +// Copyright (c) 2008 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. + +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(9C1100DD-51D4-4827-AE9F-3B8FAC4AED72), + oleautomation, + nonextensible, + pointer_default(unique) +] +interface IChromeHistoryIndexer : IUnknown { + // This is the method called by Chrome to send content and thumbnail of the + // page to be indexed. The html content and thumbnail for the same url + // are sent at different points in time. The thumbnail_format and + // thumbnail parameters will be NULL when sending only the content. + // |time| - The last time at which user visited the page. The time is in UTC. + // |url| - The url of the page being published for indexing. + // |html| - The html content of the page being published for indexing. + // |title| - The url of the page being published for indexing. + // |thumbnail_format| - The format of the thumbnail image. It is currently + // "image/jpeg", indicating that the thumbail is in jpeg + // format. + // |thumbnail| - This is an array of bytes that represents the thumbnail in + // the format specified by the "thumbnail_format" parameter. + HRESULT SendPageData([in] VARIANT time, + [in] BSTR url, + [in] BSTR html, + [in] BSTR title, + [in] BSTR thumbnail_format, + [in] VARIANT thumbnail); + + // This method is called by Chrome when the users delete their history. + // |begin_time| - Represents the start time from which the history needs to be + // deleted. It is given in UTC. + // |end_time| - Represents the end time until when the history needs to be + // deleted. It is given in UTC + // If both begin_time and end_time are '0', full user history needs to be + // deleted. + HRESULT DeleteUserHistoryBetween([in] VARIANT begin_time, + [in] VARIANT end_time); +}; diff --git a/chrome/browser/history/history_publisher.cc b/chrome/browser/history/history_publisher.cc new file mode 100644 index 0000000..5b4eead --- /dev/null +++ b/chrome/browser/history/history_publisher.cc @@ -0,0 +1,156 @@ +// Copyright (c) 008 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/history_publisher.h" + +#if defined(OS_WIN) +#include <atlsafe.h> +#include <objbase.h> +#include <oleauto.h> +#include <wtypes.h> +#endif + +#include "base/registry.h" + +namespace history { + +const wchar_t* HistoryPublisher::kRegKeyRegisteredIndexersInfo = + L"Software\\Google\\Google Chrome\\IndexerPlugins"; +const char* HistoryPublisher::kThumbnailImageFormat = "image/jpeg"; + +// static +double HistoryPublisher::TimeToUTCVariantTime(const base::Time& time) { + double var_time = 0; +#if defined(OS_WIN) + if (!time.is_null()) { + base::Time::Exploded exploded; + time.UTCExplode(&exploded); + + // Create the system time struct representing our exploded time. + SYSTEMTIME system_time; + system_time.wYear = exploded.year; + system_time.wMonth = exploded.month; + system_time.wDayOfWeek = exploded.day_of_week; + system_time.wDay = exploded.day_of_month; + system_time.wHour = exploded.hour; + system_time.wMinute = exploded.minute; + system_time.wSecond = exploded.second; + system_time.wMilliseconds = exploded.millisecond; + SystemTimeToVariantTime(&system_time, &var_time); + } +#endif + + return var_time; +} + +HistoryPublisher::HistoryPublisher() { +#if defined(OS_WIN) + CoInitialize(NULL); +#endif +} + +HistoryPublisher::~HistoryPublisher() { +#if defined(OS_WIN) + CoUninitialize(); +#endif +} + +bool HistoryPublisher::Init() { + return ReadRegisteredIndexersFromRegistry(); +} + +bool HistoryPublisher::ReadRegisteredIndexersFromRegistry() { +#if defined(OS_WIN) + RegistryKeyIterator iter(HKEY_CURRENT_USER, kRegKeyRegisteredIndexersInfo); + while (iter.Valid()) { + // The subkey name is the GUID of the Indexer COM object which implements + // the IChromeHistoryIndexer interface. We shall store that and use it to + // send historical data to the indexer. + CLSID clsid; + CLSIDFromString(static_cast<LPOLESTR>( + const_cast<TCHAR*>(iter.Name())), &clsid); + CComPtr<IChromeHistoryIndexer> indexer; + HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC, + __uuidof(IChromeHistoryIndexer), + reinterpret_cast<void**>(&indexer)); + if (SUCCEEDED(hr) && indexer != NULL) + indexers_.push_back(indexer); + ++iter; + } + return indexers_.size() > 0; +#else + // The indexing plublisher is implemented only for Windows platform as of + // now. Hence returning false for other platforms. + return false; +#endif +} + +void HistoryPublisher::PublishPageThumbnail( + const std::vector<unsigned char>& thumbnail, const GURL& url, + const base::Time& time) const { + PageData page_data = { + time, + url, + NULL, + NULL, + kThumbnailImageFormat, + &thumbnail, + }; + + PublishDataToIndexers(page_data); +} + +void HistoryPublisher::PublishPageContent(const base::Time& time, + const GURL& url, + const std::wstring& title, + const std::wstring& contents) const { + PageData page_data = { + time, + url, + contents.c_str(), + title.c_str(), + NULL, + NULL, + }; + + PublishDataToIndexers(page_data); +} + +void HistoryPublisher::PublishDataToIndexers(const PageData& page_data) + const { +#if defined(OS_WIN) + double var_time = TimeToUTCVariantTime(page_data.time); + + CComSafeArray<unsigned char> thumbnail_arr; + if (page_data.thumbnail) { + for(size_t i = 0; i < page_data.thumbnail->size(); ++i) + thumbnail_arr.Add((*page_data.thumbnail)[i]); + } + + // Send data to registered indexers. + for(size_t i = 0; i < indexers_.size(); ++i) { + indexers_[i]->SendPageData( + CComVariant(var_time, VT_DATE), + CComBSTR(page_data.url.spec().c_str()), + CComBSTR(page_data.html), + CComBSTR(page_data.title), + CComBSTR(page_data.thumbnail_format), + CComVariant(thumbnail_arr.m_psa)); + } +#endif +} + +void HistoryPublisher::DeleteUserHistoryBetween(const base::Time& begin_time, + const base::Time& end_time) const { +#if defined(OS_WIN) + double var_begin_time = TimeToUTCVariantTime(begin_time); + double var_end_time = TimeToUTCVariantTime(end_time); + for(size_t i = 0; i < indexers_.size(); ++i) { + indexers_[i]->DeleteUserHistoryBetween(CComVariant(var_begin_time, VT_DATE), + CComVariant(var_end_time, VT_DATE)); + } +#endif +} + +} // namespace history diff --git a/chrome/browser/history/history_publisher.h b/chrome/browser/history/history_publisher.h new file mode 100644 index 0000000..7c199ac --- /dev/null +++ b/chrome/browser/history/history_publisher.h @@ -0,0 +1,81 @@ +// Copyright (c) 2008 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_HISTORY_PUBLISHER_H_ +#define CHROME_BROWSER_HISTORY_HISTORY_PUBLISHER_H_ + +#include <vector> +#include <string> + +#include "base/basictypes.h" +#include "base/time.h" +#include "chrome/browser/history/history_types.h" +#include "googleurl/src/gurl.h" + +#if defined(OS_WIN) +#include <atlbase.h> +#include <atlcomcli.h> +#include "history_indexer.h" +#endif + +namespace history { + +class HistoryPublisher { + public: + HistoryPublisher(); + ~HistoryPublisher(); + + // Must call this function to complete initialization. Returns true if we + // need to publish data to any indexers registered with us. Returns false if + // there are none registered. On false, no other function should be called. + bool Init(); + + void PublishPageThumbnail(const std::vector<unsigned char>& thumbnail, + const GURL& url, const base::Time& time) const; + void PublishPageContent(const base::Time& time, const GURL& url, + const std::wstring& title, + const std::wstring& contents) const; + void DeleteUserHistoryBetween(const base::Time& begin_time, + const base::Time& end_time) const; + + private: + struct PageData { + const base::Time& time; + const GURL& url; + const wchar_t* html; + const wchar_t* title; + const char* thumbnail_format; + const std::vector<unsigned char>* thumbnail; + }; + void PublishDataToIndexers(const PageData& page_data) const; + + // Converts time represented by the Time class object to variant time in UTC. + // Returns '0' if the time object is NULL. + static double TimeToUTCVariantTime(const base::Time& time); + + // Initializes the indexer_list_ with the list of indexers that registered + // with us to index history. Returns true if there are any registered. + bool ReadRegisteredIndexersFromRegistry(); + + private: +#if defined(OS_WIN) + typedef std::vector<CComPtr<IChromeHistoryIndexer> > IndexerList; + + // The list of indexers registered to receive history data from us. + IndexerList indexers_; +#endif + + // The Registry key under HKCU where the indexers need to register their + // CLSID. + static const wchar_t* kRegKeyRegisteredIndexersInfo; + + // The format of the thumbnail we pass to indexers. + static const char* kThumbnailImageFormat; + + DISALLOW_COPY_AND_ASSIGN(HistoryPublisher); +}; + +} // namespace history + +#endif // CHROME_BROWSER_HISTORY_HISTORY_PUBLISHER_H_ diff --git a/chrome/browser/history/text_database_manager.cc b/chrome/browser/history/text_database_manager.cc index 483befa..8fcb8fc 100644 --- a/chrome/browser/history/text_database_manager.cc +++ b/chrome/browser/history/text_database_manager.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/string_util.h" +#include "chrome/browser/history/history_publisher.h" #include "chrome/common/mru_cache.h" using base::Time; @@ -77,6 +78,7 @@ TextDatabaseManager::TextDatabaseManager(const std::wstring& dir, transaction_nesting_(0), db_cache_(DBCache::NO_AUTO_EVICT), present_databases_loaded_(false), + history_publisher_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { } @@ -104,7 +106,9 @@ Time TextDatabaseManager::IDToTime(TextDatabase::DBIdent id) { return Time::FromUTCExploded(exploded); } -bool TextDatabaseManager::Init() { +bool TextDatabaseManager::Init(const HistoryPublisher* history_publisher) { + history_publisher_ = history_publisher; + // Start checking recent changes and committing them. ScheduleFlushOldChanges(); return true; @@ -306,6 +310,10 @@ bool TextDatabaseManager::AddPageData(const GURL& url, HISTOGRAM_TIMES(L"History.AddFTSData", TimeTicks::Now() - beginning_time); + + if (history_publisher_) + history_publisher_->PublishPageContent(visit_time, url, title, body); + return success; } diff --git a/chrome/browser/history/text_database_manager.h b/chrome/browser/history/text_database_manager.h index f1195ef..fcf9d5f 100644 --- a/chrome/browser/history/text_database_manager.h +++ b/chrome/browser/history/text_database_manager.h @@ -22,6 +22,8 @@ struct sqlite3; namespace history { +class HistoryPublisher; + // Manages a set of text databases representing different time periods. This // will page them in and out as necessary, and will manage queries for times // spanning multiple databases. @@ -77,7 +79,7 @@ class TextDatabaseManager { // Must call before using other functions. If it returns false, no other // functions should be called. - bool Init(); + bool Init(const HistoryPublisher* history_publisher); // Allows scoping updates. This also allows things to go faster since every // page add doesn't need to be committed to disk (slow). Note that files will @@ -293,6 +295,12 @@ class TextDatabaseManager { // Generates tasks for our periodic checking of expired "recent changes". ScopedRunnableMethodFactory<TextDatabaseManager> factory_; + // This object is created and managed by the history backend. We maintain an + // opaque pointer to the object for our use. + // This can be NULL if there are no indexers registered to receive indexing + // data from us. + const HistoryPublisher* history_publisher_; + DISALLOW_EVIL_CONSTRUCTORS(TextDatabaseManager); }; diff --git a/chrome/browser/history/text_database_manager_unittest.cc b/chrome/browser/history/text_database_manager_unittest.cc index 6781a76..b080def 100644 --- a/chrome/browser/history/text_database_manager_unittest.cc +++ b/chrome/browser/history/text_database_manager_unittest.cc @@ -169,7 +169,7 @@ TEST_F(TextDatabaseManagerTest, InsertQuery) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); std::vector<Time> times; AddAllPages(manager, &visit_db, ×); @@ -201,7 +201,7 @@ TEST_F(TextDatabaseManagerTest, InsertCompleteNoVisit) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); // First add one without a visit. const GURL url(kURL1); @@ -225,7 +225,7 @@ TEST_F(TextDatabaseManagerTest, InsertCompleteVisit) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); // First add a visit to a page. We can just make up a URL ID since there is // not actually any URL database around. @@ -264,7 +264,7 @@ TEST_F(TextDatabaseManagerTest, InsertPartial) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); // Add the first one with just a URL. GURL url1(kURL1); @@ -312,7 +312,7 @@ TEST_F(TextDatabaseManagerTest, PartialComplete) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); Time added_time = Time::Now(); GURL url(kURL1); @@ -370,7 +370,7 @@ TEST_F(TextDatabaseManagerTest, Writing) { // Create the manager and write some stuff to it. { TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); std::vector<Time> times; AddAllPages(manager, &visit_db, ×); @@ -384,7 +384,7 @@ TEST_F(TextDatabaseManagerTest, Writing) { // Recreate the manager and make sure it finds the written stuff. { TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); // We should have matched every page again. manager.GetTextMatches(L"FOO", options, &results, &first_time_searched); @@ -406,7 +406,7 @@ TEST_F(TextDatabaseManagerTest, WritingTransaction) { // Create the manager and write some stuff to it. { TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); std::vector<Time> times; manager.BeginTransaction(); @@ -422,7 +422,7 @@ TEST_F(TextDatabaseManagerTest, WritingTransaction) { // Recreate the manager and make sure it finds the written stuff. { TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); // We should have matched every page again. manager.GetTextMatches(L"FOO", options, &results, &first_time_searched); @@ -435,7 +435,7 @@ TEST_F(TextDatabaseManagerTest, QueryMax) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); std::vector<Time> times; AddAllPages(manager, &visit_db, ×); @@ -472,7 +472,7 @@ TEST_F(TextDatabaseManagerTest, QueryBackwards) { ASSERT_TRUE(Init()); InMemDB visit_db; TextDatabaseManager manager(dir_, &visit_db, &visit_db); - ASSERT_TRUE(manager.Init()); + ASSERT_TRUE(manager.Init(NULL)); std::vector<Time> times; AddAllPages(manager, &visit_db, ×); diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc index ca0a132..d493b56 100644 --- a/chrome/browser/history/thumbnail_database.cc +++ b/chrome/browser/history/thumbnail_database.cc @@ -7,6 +7,7 @@ #include "base/file_util.h" #include "base/time.h" #include "base/string_util.h" +#include "chrome/browser/history/history_publisher.h" #include "chrome/browser/history/url_database.h" #include "chrome/common/jpeg_codec.h" #include "chrome/common/sqlite_utils.h" @@ -24,14 +25,18 @@ static const int kCompatibleVersionNumber = 3; ThumbnailDatabase::ThumbnailDatabase() : db_(NULL), statement_cache_(NULL), - transaction_nesting_(0) { + transaction_nesting_(0), + history_publisher_(NULL) { } ThumbnailDatabase::~ThumbnailDatabase() { // The DBCloseScoper will delete the DB and the cache. } -InitStatus ThumbnailDatabase::Init(const std::wstring& db_name) { +InitStatus ThumbnailDatabase::Init(const std::wstring& db_name, + const HistoryPublisher* history_publisher) { + history_publisher_ = history_publisher; + // Open the thumbnail database, using the narrow version of open so that // the DB is in UTF-8. if (sqlite3_open(WideToUTF8(db_name).c_str(), &db_) != SQLITE_OK) @@ -222,9 +227,11 @@ void ThumbnailDatabase::Vacuum() { } void ThumbnailDatabase::SetPageThumbnail( + const GURL& url, URLID id, const SkBitmap& thumbnail, - const ThumbnailScore& score) { + const ThumbnailScore& score, + const Time& time) { if (!thumbnail.isNull()) { bool add_thumbnail = true; ThumbnailScore current_score; @@ -264,6 +271,11 @@ void ThumbnailDatabase::SetPageThumbnail( if (statement->step() != SQLITE_DONE) DLOG(WARNING) << "Unable to insert thumbnail"; } + + // Publish the thumbnail to any indexers listening to us. + // The tests may send an invalid url. Hence avoid publishing those. + if (url.is_valid() && history_publisher_ != NULL) + history_publisher_->PublishPageThumbnail(jpeg_data, url, time); } } else { if ( !DeleteThumbnail(id) ) diff --git a/chrome/browser/history/thumbnail_database.h b/chrome/browser/history/thumbnail_database.h index 0a15931..5452c77 100644 --- a/chrome/browser/history/thumbnail_database.h +++ b/chrome/browser/history/thumbnail_database.h @@ -22,6 +22,7 @@ namespace base { namespace history { class ExpireHistoryBackend; +class HistoryPublisher; // This database interface is owned by the history backend and runs on the // history thread. It is a totally separate component from history partially @@ -37,7 +38,8 @@ class ThumbnailDatabase { // Must be called after creation but before any other methods are called. // When not INIT_OK, no other functions should be called. - InitStatus Init(const std::wstring& db_name); + InitStatus Init(const std::wstring& db_name, + const HistoryPublisher* history_publisher); // Transactions on the database. void BeginTransaction(); @@ -55,9 +57,11 @@ class ThumbnailDatabase { // Sets the given data to be the thumbnail for the given URL, // overwriting any previous data. If the SkBitmap contains no pixel // data, the thumbnail will be deleted. - void SetPageThumbnail(URLID id, + void SetPageThumbnail(const GURL& url, + URLID id, const SkBitmap& thumbnail, - const ThumbnailScore& score); + const ThumbnailScore& score, + const base::Time& time); // Retrieves thumbnail data for the given URL, returning true on success, // false if there is no such thumbnail or there was some other error. @@ -160,6 +164,12 @@ class ThumbnailDatabase { int transaction_nesting_; MetaTableHelper meta_table_; + + // This object is created and managed by the history backend. We maintain an + // opaque pointer to the object for our use. + // This can be NULL if there are no indexers registered to receive indexing + // data from us. + const HistoryPublisher* history_publisher_; }; } // namespace history diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc index 318d385..7507536 100644 --- a/chrome/browser/history/thumbnail_database_unittest.cc +++ b/chrome/browser/history/thumbnail_database_unittest.cc @@ -12,6 +12,7 @@ #include "chrome/common/jpeg_codec.h" #include "chrome/common/thumbnail_score.h" #include "chrome/tools/profiles/thumbnail-inl.h" +#include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" #include "SkBitmap.h" @@ -80,11 +81,13 @@ static std::vector<unsigned char> StringToVector(const unsigned char* str) { TEST_F(ThumbnailDatabaseTest, AddDelete) { ThumbnailDatabase db; - ASSERT_TRUE(db.Init(file_name_) == INIT_OK); + ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); // Add one page & verify it got added. ThumbnailScore boring(kBoringness, true, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, boring); + Time time; + GURL gurl; + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring, time); ThumbnailScore score_output; ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_output)); ASSERT_TRUE(boring.Equals(score_output)); @@ -97,13 +100,14 @@ TEST_F(ThumbnailDatabaseTest, AddDelete) { // Add another page with a better boringness & verify it got added. ThumbnailScore better_boringness(kBetterBoringness, true, true); - db.SetPageThumbnail(page2, *google_bitmap_, better_boringness); + + db.SetPageThumbnail(gurl, page2, *google_bitmap_, better_boringness, time); ASSERT_TRUE(db.ThumbnailScoreForId(page2, &score_output)); ASSERT_TRUE(better_boringness.Equals(score_output)); // Delete the thumbnail for the second page. ThumbnailScore worse_boringness(kWorseBoringness, true, true); - db.SetPageThumbnail(page2, SkBitmap(), worse_boringness); + db.SetPageThumbnail(gurl, page2, SkBitmap(), worse_boringness, time); ASSERT_FALSE(db.GetPageThumbnail(page2, &jpeg_data)); ASSERT_FALSE(db.ThumbnailScoreForId(page2, &score_output)); @@ -120,11 +124,14 @@ TEST_F(ThumbnailDatabaseTest, AddDelete) { TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_) == INIT_OK); + ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); // Add one page & verify it got added. ThumbnailScore boring(kBoringness, true, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, boring); + + Time time; + GURL gurl; + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring, time); std::vector<unsigned char> jpeg_data; ThumbnailScore score_out; ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); @@ -134,7 +141,7 @@ TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { // Attempt to update the first page entry with a thumbnail that // is more boring and verify that it doesn't change. ThumbnailScore more_boring(kWorseBoringness, true, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, more_boring); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, more_boring, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring.Equals(score_out)); @@ -142,7 +149,7 @@ TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { // Attempt to update the first page entry with a thumbnail that // is less boring and verify that we update it. ThumbnailScore less_boring(kBetterBoringness, true, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, less_boring); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, less_boring, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(less_boring.Equals(score_out)); @@ -151,12 +158,15 @@ TEST_F(ThumbnailDatabaseTest, UseLessBoringThumbnails) { TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_) == INIT_OK); + ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); // Add one page & verify it got added. Note that it doesn't have // |good_clipping| and isn't |at_top|. ThumbnailScore boring_and_bad(kBoringness, false, false); - db.SetPageThumbnail(kPage1, *google_bitmap_, boring_and_bad); + + Time time; + GURL gurl; + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_and_bad, time); std::vector<unsigned char> jpeg_data; ThumbnailScore score_out; ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); @@ -166,7 +176,7 @@ TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { // A thumbnail that's at the top of the page should replace // thumbnails that are in the middle, for the same boringness. ThumbnailScore boring_but_better(kBoringness, false, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, boring_but_better); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_but_better, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring_but_better.Equals(score_out)); @@ -175,13 +185,15 @@ TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { // a thumbnail in the middle/bottom is when the current thumbnail is // weirdly stretched and the incoming thumbnail isn't. ThumbnailScore better_boring_bad_framing(kBetterBoringness, false, false); - db.SetPageThumbnail(kPage1, *google_bitmap_, better_boring_bad_framing); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, better_boring_bad_framing, + time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring_but_better.Equals(score_out)); ThumbnailScore boring_good_clipping(kBoringness, true, false); - db.SetPageThumbnail(kPage1, *google_bitmap_, boring_good_clipping); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, boring_good_clipping, + time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring_good_clipping.Equals(score_out)); @@ -190,15 +202,17 @@ TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { // we shouldn't be able to replace it with: // 1) A stretched thumbnail in the middle of the page - db.SetPageThumbnail(kPage1, *google_bitmap_, - ThumbnailScore(kBetterBoringness, false, false, now)); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, + ThumbnailScore(kBetterBoringness, false, false, now), + time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring_good_clipping.Equals(score_out)); // 2) A stretched thumbnail at the top of the page - db.SetPageThumbnail(kPage1, *google_bitmap_, - ThumbnailScore(kBetterBoringness, false, true, now)); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, + ThumbnailScore(kBetterBoringness, false, true, now), + time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(boring_good_clipping.Equals(score_out)); @@ -206,7 +220,7 @@ TEST_F(ThumbnailDatabaseTest, UseAtTopThumbnails) { // But it should be replaced by a thumbnail that's clipped properly // and is at the top ThumbnailScore best_score(kBetterBoringness, true, true); - db.SetPageThumbnail(kPage1, *google_bitmap_, best_score); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, best_score, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(best_score.Equals(score_out)); @@ -220,11 +234,14 @@ TEST_F(ThumbnailDatabaseTest, ThumbnailTimeDegradation) { const double kBaseBoringness = 0.305; const double kWorseBoringness = 0.345; - ASSERT_TRUE(db.Init(file_name_) == INIT_OK); + ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); // add one page & verify it got added. ThumbnailScore base_boringness(kBaseBoringness, true, true, kFiveHoursAgo); - db.SetPageThumbnail(kPage1, *google_bitmap_, base_boringness); + + Time time; + GURL gurl; + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base_boringness, time); std::vector<unsigned char> jpeg_data; ThumbnailScore score_out; ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); @@ -234,7 +251,7 @@ TEST_F(ThumbnailDatabaseTest, ThumbnailTimeDegradation) { // Try to add a different thumbnail with a worse score an hour later // (but not enough to trip the boringness degradation threshold). ThumbnailScore hour_later(kWorseBoringness, true, true, kThreeHoursAgo); - db.SetPageThumbnail(kPage1, *google_bitmap_, hour_later); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, hour_later, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(base_boringness.Equals(score_out)); @@ -243,7 +260,7 @@ TEST_F(ThumbnailDatabaseTest, ThumbnailTimeDegradation) { // that we'll allow the same thumbnail with the same (worse) // boringness that we previous rejected. ThumbnailScore five_hours_later(kWorseBoringness, true, true, kNow); - db.SetPageThumbnail(kPage1, *google_bitmap_, five_hours_later); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, five_hours_later, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(five_hours_later.Equals(score_out)); @@ -256,7 +273,7 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { // thumbnail is totally boring. ThumbnailDatabase db; Time now = Time::Now(); - ASSERT_TRUE(db.Init(file_name_) == INIT_OK); + ASSERT_TRUE(db.Init(file_name_, NULL) == INIT_OK); std::vector<unsigned char> jpeg_data; ThumbnailScore score_out; @@ -273,6 +290,9 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { {true, true} }; + Time time; + GURL gurl; + // Test that for each entry type, all entry types that are better // than it still will reject thumbnails which are totally boring. for (int i = 0; i < kSizeOfTable; ++i) { @@ -281,7 +301,7 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { heiarchy_table[i].at_top, kNow); - db.SetPageThumbnail(kPage1, *google_bitmap_, base); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(base.Equals(score_out)); @@ -291,7 +311,8 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { kTotallyBoring, heiarchy_table[j].good_scaling, heiarchy_table[j].at_top, kNow); - db.SetPageThumbnail(kPage1, *google_bitmap_, shouldnt_replace); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, shouldnt_replace, + time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(base.Equals(score_out)); @@ -306,14 +327,15 @@ TEST_F(ThumbnailDatabaseTest, NeverAcceptTotallyBoringThumbnail) { // We should never accept a totally boring thumbnail no matter how // much old the current thumbnail is. ThumbnailScore base_boring(kBaseBoringness, true, true, kNow); - db.SetPageThumbnail(kPage1, *google_bitmap_, base_boring); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, base_boring, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(base_boring.Equals(score_out)); ThumbnailScore totally_boring_in_the_future( kTotallyBoring, true, true, kNow + TimeDelta::FromDays(365)); - db.SetPageThumbnail(kPage1, *google_bitmap_, totally_boring_in_the_future); + db.SetPageThumbnail(gurl, kPage1, *google_bitmap_, + totally_boring_in_the_future, time); ASSERT_TRUE(db.GetPageThumbnail(kPage1, &jpeg_data)); ASSERT_TRUE(db.ThumbnailScoreForId(kPage1, &score_out)); ASSERT_TRUE(base_boring.Equals(score_out)); diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index 66d1ccd..a5f6fdf 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -17,8 +17,6 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/drag_utils.h" #include "chrome/browser/download/download_util.h" -#include "chrome/browser/history/history_backend.h" -#include "chrome/browser/history/history_database.h" #include "chrome/browser/history/history.h" #include "chrome/browser/page_navigator.h" #include "chrome/browser/profile.h" |