This source file includes following definitions.
- DeleteCacheFile
- InitializeSchemeWhitelist
- succeeded_
- RunOnDBThread
- DoneRunOnMainThread
- RebuildPrivateDataFromHistoryDBTask
- needs_to_be_cached_
- needs_to_be_cached_
- Init
- ShutDown
- ClearPrivateData
- GetCacheFilePath
- HistoryItemsForTerms
- DeleteURL
- Observe
- OnURLVisited
- OnURLsModified
- OnURLsDeleted
- PostRestoreFromCacheFileTask
- OnCacheLoadDone
- ScheduleRebuildFromHistory
- DoneRebuidingPrivateDataFromHistoryDB
- RebuildFromHistory
- PostSaveToCacheFileTask
- OnCacheSaveDone
#include "chrome/browser/history/in_memory_url_index.h"
#include "base/debug/trace_event.h"
#include "base/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 "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
using in_memory_url_index::InMemoryURLIndexCacheItem;
namespace history {
void DeleteCacheFile(const base::FilePath& path) {
DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::DeleteFile(path, false);
}
void InitializeSchemeWhitelist(std::set<std::string>* whitelist) {
DCHECK(whitelist);
if (!whitelist->empty())
return;
whitelist->insert(std::string(content::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));
}
InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
RebuildPrivateDataFromHistoryDBTask(
InMemoryURLIndex* index,
const std::string& languages,
const std::set<std::string>& scheme_whitelist)
: index_(index),
languages_(languages),
scheme_whitelist_(scheme_whitelist),
succeeded_(false) {
}
bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
HistoryBackend* backend,
HistoryDatabase* db) {
data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
scheme_whitelist_);
succeeded_ = data_.get() && !data_->Empty();
if (!succeeded_ && data_.get())
data_->Clear();
return true;
}
void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
DoneRunOnMainThread() {
index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
}
InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
~RebuildPrivateDataFromHistoryDBTask() {
}
InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
const base::FilePath& history_dir,
const std::string& languages)
: profile_(profile),
history_dir_(history_dir),
languages_(languages),
private_data_(new URLIndexPrivateData),
restore_cache_observer_(NULL),
save_cache_observer_(NULL),
shutdown_(false),
restored_(false),
needs_to_be_cached_(false) {
InitializeSchemeWhitelist(&scheme_whitelist_);
if (profile) {
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);
}
}
InMemoryURLIndex::InMemoryURLIndex()
: profile_(NULL),
private_data_(new URLIndexPrivateData),
restore_cache_observer_(NULL),
save_cache_observer_(NULL),
shutdown_(false),
restored_(false),
needs_to_be_cached_(false) {
InitializeSchemeWhitelist(&scheme_whitelist_);
}
InMemoryURLIndex::~InMemoryURLIndex() {
DCHECK(history_dir_.empty() || !needs_to_be_cached_);
}
void InMemoryURLIndex::Init() {
PostRestoreFromCacheFileTask();
}
void InMemoryURLIndex::ShutDown() {
registrar_.RemoveAll();
cache_reader_consumer_.CancelAllRequests();
shutdown_ = true;
base::FilePath path;
if (!GetCacheFilePath(&path))
return;
private_data_->CancelPendingUpdates();
URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path);
needs_to_be_cached_ = false;
}
void InMemoryURLIndex::ClearPrivateData() {
private_data_->Clear();
}
bool InMemoryURLIndex::GetCacheFilePath(base::FilePath* file_path) {
if (history_dir_.empty())
return false;
*file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
return true;
}
ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
const base::string16& term_string,
size_t cursor_position) {
return private_data_->HistoryItemsForTerms(
term_string,
cursor_position,
languages_,
BookmarkModelFactory::GetForProfile(profile_));
}
void InMemoryURLIndex::DeleteURL(const GURL& url) {
private_data_->DeleteURL(url);
}
void InMemoryURLIndex::Observe(int notification_type,
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());
break;
case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
OnURLsDeleted(
content::Details<history::URLsDeletedDetails>(details).ptr());
break;
case chrome::NOTIFICATION_HISTORY_LOADED:
registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
content::Source<Profile>(profile_));
ScheduleRebuildFromHistory();
break;
default:
break;
}
}
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::OnURLsModified(const URLsModifiedDetails* details) {
HistoryService* service =
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_);
}
void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
if (details->all_history) {
ClearPrivateData();
needs_to_be_cached_ = true;
} else {
for (URLRows::const_iterator row = details->rows.begin();
row != details->rows.end(); ++row)
needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
}
}
void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask");
base::FilePath path;
if (!GetCacheFilePath(&path) || shutdown_) {
restored_ = true;
if (restore_cache_observer_)
restore_cache_observer_->OnCacheRestoreFinished(false);
return;
}
content::BrowserThread::PostTaskAndReplyWithResult
<scoped_refptr<URLIndexPrivateData> >(
content::BrowserThread::FILE, FROM_HERE,
base::Bind(&URLIndexPrivateData::RestoreFromFile, path, languages_),
base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr()));
}
void InMemoryURLIndex::OnCacheLoadDone(
scoped_refptr<URLIndexPrivateData> private_data) {
if (private_data.get() && !private_data->Empty()) {
private_data_ = private_data;
restored_ = true;
if (restore_cache_observer_)
restore_cache_observer_->OnCacheRestoreFinished(true);
} else if (profile_) {
base::FilePath path;
if (!GetCacheFilePath(&path) || shutdown_)
return;
content::BrowserThread::PostBlockingPoolTask(
FROM_HERE, base::Bind(DeleteCacheFile, path));
HistoryService* service =
HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
if (service && service->backend_loaded()) {
ScheduleRebuildFromHistory();
} else {
registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
content::Source<Profile>(profile_));
}
}
}
void InMemoryURLIndex::ScheduleRebuildFromHistory() {
HistoryService* service =
HistoryServiceFactory::GetForProfile(profile_,
Profile::EXPLICIT_ACCESS);
service->ScheduleDBTask(
new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
this, languages_, scheme_whitelist_),
&cache_reader_consumer_);
}
void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
bool succeeded,
scoped_refptr<URLIndexPrivateData> private_data) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (succeeded) {
private_data_ = private_data;
PostSaveToCacheFileTask();
} else {
private_data_->Clear();
}
restored_ = true;
if (restore_cache_observer_)
restore_cache_observer_->OnCacheRestoreFinished(succeeded);
}
void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
languages_,
scheme_whitelist_);
}
void InMemoryURLIndex::PostSaveToCacheFileTask() {
base::FilePath path;
if (!GetCacheFilePath(&path))
return;
if (private_data_.get() && !private_data_->Empty()) {
scoped_refptr<URLIndexPrivateData> private_data_copy =
private_data_->Duplicate();
content::BrowserThread::PostTaskAndReplyWithResult<bool>(
content::BrowserThread::FILE, FROM_HERE,
base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
private_data_copy, path),
base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr()));
} else {
content::BrowserThread::PostBlockingPoolTask(
FROM_HERE,
base::Bind(DeleteCacheFile, path));
}
}
void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) {
if (save_cache_observer_)
save_cache_observer_->OnCacheSaveFinished(succeeded);
}
}