#include "chrome/browser/history/in_memory_url_index.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/bookmarks/bookmark_service.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/history/url_database.h"
#include "chrome/browser/history/url_index_private_data.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/history/core/browser/url_database.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
DCHECK(whitelist);
if (!whitelist->empty())
return; // Nothing to do, already initialized.
- whitelist->insert(std::string(chrome::kAboutScheme));
+ whitelist->insert(std::string(url::kAboutScheme));
whitelist->insert(std::string(content::kChromeUIScheme));
- whitelist->insert(std::string(content::kFileScheme));
- whitelist->insert(std::string(content::kFtpScheme));
- whitelist->insert(std::string(content::kHttpScheme));
- whitelist->insert(std::string(content::kHttpsScheme));
- whitelist->insert(std::string(content::kMailToScheme));
+ whitelist->insert(std::string(url::kFileScheme));
+ whitelist->insert(std::string(url::kFtpScheme));
+ whitelist->insert(std::string(url::kHttpScheme));
+ whitelist->insert(std::string(url::kHttpsScheme));
+ whitelist->insert(std::string(url::kMailToScheme));
}
// Restore/SaveCacheObserver ---------------------------------------------------
// InMemoryURLIndex ------------------------------------------------------------
InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
+ HistoryService* history_service,
const base::FilePath& history_dir,
- const std::string& languages)
+ const std::string& languages,
+ HistoryClient* history_client)
: profile_(profile),
+ history_service_(history_service),
+ history_client_(history_client),
history_dir_(history_dir),
languages_(languages),
private_data_(new URLIndexPrivateData),
if (profile) {
// TODO(mrossetti): Register for language change notifications.
content::Source<Profile> source(profile);
- registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
source);
registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
}
+ if (history_service_)
+ history_service_->AddObserver(this);
}
// Called only by unit tests.
InMemoryURLIndex::InMemoryURLIndex()
: profile_(NULL),
+ history_service_(nullptr),
+ history_client_(NULL),
private_data_(new URLIndexPrivateData),
restore_cache_observer_(NULL),
save_cache_observer_(NULL),
}
void InMemoryURLIndex::ShutDown() {
+ if (history_service_)
+ history_service_->RemoveObserver(this);
registrar_.RemoveAll();
- cache_reader_consumer_.CancelAllRequests();
+ cache_reader_tracker_.TryCancelAll();
shutdown_ = true;
base::FilePath path;
if (!GetCacheFilePath(&path))
return;
- private_data_->CancelPendingUpdates();
+ private_data_tracker_.TryCancelAll();
URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path);
needs_to_be_cached_ = false;
}
ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
const base::string16& term_string,
- size_t cursor_position) {
+ size_t cursor_position,
+ size_t max_matches) {
return private_data_->HistoryItemsForTerms(
term_string,
cursor_position,
+ max_matches,
languages_,
- BookmarkModelFactory::GetForProfile(profile_));
+ history_client_);
}
// Updating --------------------------------------------------------------------
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (notification_type) {
- case chrome::NOTIFICATION_HISTORY_URL_VISITED:
- OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
- break;
case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
OnURLsModified(
content::Details<history::URLsModifiedDetails>(details).ptr());
}
}
-void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
- HistoryService* service =
- HistoryServiceFactory::GetForProfile(profile_,
- Profile::EXPLICIT_ACCESS);
- needs_to_be_cached_ |= private_data_->UpdateURL(
- service, details->row, languages_, scheme_whitelist_);
+void InMemoryURLIndex::OnURLVisited(HistoryService* history_service,
+ ui::PageTransition transition,
+ const URLRow& row,
+ const RedirectList& redirects,
+ base::Time visit_time) {
+ DCHECK_EQ(history_service_, history_service);
+ needs_to_be_cached_ |= private_data_->UpdateURL(history_service_,
+ row,
+ languages_,
+ scheme_whitelist_,
+ &private_data_tracker_);
}
void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) {
HistoryServiceFactory::GetForProfile(profile_,
Profile::EXPLICIT_ACCESS);
for (URLRows::const_iterator row = details->changed_urls.begin();
- row != details->changed_urls.end(); ++row)
- needs_to_be_cached_ |=
- private_data_->UpdateURL(service, *row, languages_, scheme_whitelist_);
+ row != details->changed_urls.end();
+ ++row) {
+ needs_to_be_cached_ |= private_data_->UpdateURL(
+ service, *row, languages_, scheme_whitelist_, &private_data_tracker_);
+ }
}
void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
row != details->rows.end(); ++row)
needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
}
+ // If we made changes, destroy the previous cache. Otherwise, if we go
+ // through an unclean shutdown (and therefore fail to write a new cache file),
+ // when Chrome restarts and we restore from the previous cache, we'll end up
+ // searching over URLs that may be deleted. This would be wrong, and
+ // surprising to the user who bothered to delete some URLs from his/her
+ // history. In this situation, deleting the cache is a better solution than
+ // writing a new cache (after deleting the URLs from the in-memory structure)
+ // because deleting the cache forces it to be rebuilt from history upon
+ // startup. If we instead write a new, updated cache then at the time of next
+ // startup (after an unclean shutdown) we will not rebuild the in-memory data
+ // structures from history but rather use the cache. This solution is
+ // mediocre because this cache may not have the most-recently-visited URLs
+ // in it (URLs visited after user deleted some URLs from history), which
+ // would be odd and confusing. It's better to force a rebuild.
+ base::FilePath path;
+ if (needs_to_be_cached_ && GetCacheFilePath(&path)) {
+ content::BrowserThread::PostBlockingPoolTask(
+ FROM_HERE, base::Bind(DeleteCacheFile, path));
+ }
}
// Restoring from Cache --------------------------------------------------------
void InMemoryURLIndex::OnCacheLoadDone(
scoped_refptr<URLIndexPrivateData> private_data) {
if (private_data.get() && !private_data->Empty()) {
+ private_data_tracker_.TryCancelAll();
private_data_ = private_data;
restored_ = true;
if (restore_cache_observer_)
HistoryServiceFactory::GetForProfile(profile_,
Profile::EXPLICIT_ACCESS);
service->ScheduleDBTask(
- new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
- this, languages_, scheme_whitelist_),
- &cache_reader_consumer_);
+ scoped_ptr<history::HistoryDBTask>(
+ new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
+ this, languages_, scheme_whitelist_)),
+ &cache_reader_tracker_);
}
void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
scoped_refptr<URLIndexPrivateData> private_data) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (succeeded) {
+ private_data_tracker_.TryCancelAll();
private_data_ = private_data;
PostSaveToCacheFileTask(); // Cache the newly rebuilt index.
} else {
}
void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
+ private_data_tracker_.TryCancelAll();
private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
languages_,
scheme_whitelist_);