This source file includes following definitions.
- RunWithFaviconResults
- RunWithFaviconResult
- end_
- NextURL
- HasNextURL
- ExpireWebHistoryComplete
- profile_
- NotifyProfileError
- SetInMemoryBackend
- BroadcastNotifications
- DBLoaded
- NotifyVisitDBObserversOnAddVisit
- no_db_
- no_db_
- BackendLoaded
- Cleanup
- NotifyRenderProcessHostDestruction
- InMemoryDatabase
- GetTypedCountForURL
- GetLastVisitTimeForURL
- GetVisitCountForURL
- GetTypedUrlSyncableService
- Shutdown
- SetKeywordSearchTermsForURL
- DeleteAllSearchTermsForKeyword
- GetMostRecentKeywordSearchTerms
- DeleteKeywordSearchTermForURL
- DeleteMatchingURLsForKeyword
- URLsNoLongerBookmarked
- ScheduleDBTask
- QuerySegmentUsageSince
- FlushForTest
- SetOnBackendDestroyTask
- AddPage
- AddPage
- AddPage
- AddPageNoVisitForBookmark
- SetPageTitle
- UpdateWithPageEndTime
- AddPageWithDetails
- AddPagesWithDetails
- GetFavicons
- GetFaviconsForURL
- GetLargestFaviconForURL
- GetFaviconForID
- UpdateFaviconMappingsAndFetch
- MergeFavicon
- SetFavicons
- SetFaviconsOutOfDateForPage
- CloneFavicons
- SetImportedFavicons
- QueryURL
- CreateDownload
- GetNextDownloadId
- QueryDownloads
- UpdateDownload
- RemoveDownloads
- QueryHistory
- QueryRedirectsFrom
- QueryRedirectsTo
- GetVisibleVisitCountToHost
- QueryTopURLsAndRedirects
- QueryMostVisitedURLs
- QueryFilteredURLs
- Observe
- RebuildTable
- Init
- ScheduleAutocomplete
- ScheduleTask
- CanAddURL
- AsWeakPtr
- MergeDataAndStartSyncing
- StopSyncing
- GetAllSyncData
- ProcessSyncChanges
- ProcessLocalDeleteDirective
- SetInMemoryBackend
- NotifyProfileError
- DeleteURL
- DeleteURLsForTest
- ExpireHistoryBetween
- ExpireHistory
- ExpireLocalAndRemoteHistoryBetween
- BroadcastNotificationsHelper
- OnDBLoaded
- GetRowForURL
- AddVisitDatabaseObserver
- RemoveVisitDatabaseObserver
- NotifyVisitDBObserversOnAddVisit
#include "chrome/browser/history/history_service.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chrome/browser/autocomplete/history_url_provider.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/download_row.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/history/in_memory_database.h"
#include "chrome/browser/history/in_memory_history_backend.h"
#include "chrome/browser/history/in_memory_url_index.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/history/visit_database.h"
#include "chrome/browser/history/visit_filter.h"
#include "chrome/browser/history/web_history_service.h"
#include "chrome/browser/history/web_history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/profile_error_dialog.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/importer/imported_favicon_usage.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/thumbnail_score.h"
#include "chrome/common/url_constants.h"
#include "components/visitedlink/browser/visitedlink_master.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/notification_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "sync/api/sync_error_factory.h"
#include "third_party/skia/include/core/SkBitmap.h"
using base::Time;
using history::HistoryBackend;
namespace {
static const char* kHistoryThreadName = "Chrome_HistoryThread";
void RunWithFaviconResults(
const FaviconService::FaviconResultsCallback& callback,
std::vector<chrome::FaviconBitmapResult>* bitmap_results) {
callback.Run(*bitmap_results);
}
void RunWithFaviconResult(
const FaviconService::FaviconRawCallback& callback,
chrome::FaviconBitmapResult* bitmap_result) {
callback.Run(*bitmap_result);
}
class URLIteratorFromURLRows
: public visitedlink::VisitedLinkMaster::URLIterator {
public:
explicit URLIteratorFromURLRows(const history::URLRows& url_rows)
: itr_(url_rows.begin()),
end_(url_rows.end()) {
}
virtual const GURL& NextURL() OVERRIDE {
return (itr_++)->url();
}
virtual bool HasNextURL() const OVERRIDE {
return itr_ != end_;
}
private:
history::URLRows::const_iterator itr_;
history::URLRows::const_iterator end_;
DISALLOW_COPY_AND_ASSIGN(URLIteratorFromURLRows);
};
void ExpireWebHistoryComplete(bool success) {
}
}
class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
public:
BackendDelegate(
const base::WeakPtr<HistoryService>& history_service,
const scoped_refptr<base::SequencedTaskRunner>& service_task_runner,
Profile* profile)
: history_service_(history_service),
service_task_runner_(service_task_runner),
profile_(profile) {
}
virtual void NotifyProfileError(sql::InitStatus init_status) OVERRIDE {
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::NotifyProfileError, history_service_,
init_status));
}
virtual void SetInMemoryBackend(
scoped_ptr<history::InMemoryHistoryBackend> backend) OVERRIDE {
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::SetInMemoryBackend, history_service_,
base::Passed(&backend)));
}
virtual void BroadcastNotifications(
int type,
scoped_ptr<history::HistoryDetails> details) OVERRIDE {
if (content::NotificationService::current()) {
content::Details<history::HistoryDetails> det(details.get());
content::NotificationService::current()->Notify(
type, content::Source<Profile>(profile_), det);
}
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::BroadcastNotificationsHelper,
history_service_, type, base::Passed(&details)));
}
virtual void DBLoaded() OVERRIDE {
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::OnDBLoaded, history_service_));
}
virtual void NotifyVisitDBObserversOnAddVisit(
const history::BriefVisitInfo& info) OVERRIDE {
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::NotifyVisitDBObserversOnAddVisit,
history_service_, info));
}
private:
const base::WeakPtr<HistoryService> history_service_;
const scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
Profile* const profile_;
};
HistoryService::HistoryService()
: weak_ptr_factory_(this),
thread_(new base::Thread(kHistoryThreadName)),
profile_(NULL),
backend_loaded_(false),
bookmark_service_(NULL),
no_db_(false) {
}
HistoryService::HistoryService(Profile* profile)
: weak_ptr_factory_(this),
thread_(new base::Thread(kHistoryThreadName)),
profile_(profile),
visitedlink_master_(new visitedlink::VisitedLinkMaster(
profile, this, true)),
backend_loaded_(false),
bookmark_service_(NULL),
no_db_(false) {
DCHECK(profile_);
registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::Source<Profile>(profile_));
registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
content::Source<Profile>(profile_));
}
HistoryService::~HistoryService() {
DCHECK(thread_checker_.CalledOnValidThread());
Cleanup();
}
bool HistoryService::BackendLoaded() {
DCHECK(thread_checker_.CalledOnValidThread());
return backend_loaded_;
}
void HistoryService::Cleanup() {
DCHECK(thread_checker_.CalledOnValidThread());
if (!thread_) {
return;
}
weak_ptr_factory_.InvalidateWeakPtrs();
if (history_backend_) {
in_memory_backend_.reset();
if (in_memory_url_index_)
in_memory_url_index_->ShutDown();
history_backend_->AddRef();
base::Closure closing_task =
base::Bind(&HistoryBackend::Closing, history_backend_.get());
ScheduleTask(PRIORITY_NORMAL, closing_task);
closing_task.Reset();
HistoryBackend* raw_ptr = history_backend_.get();
history_backend_ = NULL;
thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
}
base::Thread* thread = thread_;
thread_ = NULL;
delete thread;
}
void HistoryService::NotifyRenderProcessHostDestruction(const void* host) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::NotifyRenderProcessHostDestruction, host);
}
history::URLDatabase* HistoryService::InMemoryDatabase() {
DCHECK(thread_checker_.CalledOnValidThread());
return in_memory_backend_ ? in_memory_backend_->db() : NULL;
}
bool HistoryService::GetTypedCountForURL(const GURL& url, int* typed_count) {
DCHECK(thread_checker_.CalledOnValidThread());
history::URLRow url_row;
if (!GetRowForURL(url, &url_row))
return false;
*typed_count = url_row.typed_count();
return true;
}
bool HistoryService::GetLastVisitTimeForURL(const GURL& url,
base::Time* last_visit) {
DCHECK(thread_checker_.CalledOnValidThread());
history::URLRow url_row;
if (!GetRowForURL(url, &url_row))
return false;
*last_visit = url_row.last_visit();
return true;
}
bool HistoryService::GetVisitCountForURL(const GURL& url, int* visit_count) {
DCHECK(thread_checker_.CalledOnValidThread());
history::URLRow url_row;
if (!GetRowForURL(url, &url_row))
return false;
*visit_count = url_row.visit_count();
return true;
}
history::TypedUrlSyncableService* HistoryService::GetTypedUrlSyncableService()
const {
return history_backend_->GetTypedUrlSyncableService();
}
void HistoryService::Shutdown() {
DCHECK(thread_checker_.CalledOnValidThread());
BookmarkModel* bookmark_model = static_cast<BookmarkModel*>(
BookmarkModelFactory::GetForProfileIfExists(profile_));
if (bookmark_model)
bookmark_model->Shutdown();
Cleanup();
}
void HistoryService::SetKeywordSearchTermsForURL(const GURL& url,
TemplateURLID keyword_id,
const base::string16& term) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_UI,
&HistoryBackend::SetKeywordSearchTermsForURL,
url, keyword_id, term);
}
void HistoryService::DeleteAllSearchTermsForKeyword(
TemplateURLID keyword_id) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_UI,
&HistoryBackend::DeleteAllSearchTermsForKeyword,
keyword_id);
}
HistoryService::Handle HistoryService::GetMostRecentKeywordSearchTerms(
TemplateURLID keyword_id,
const base::string16& prefix,
int max_count,
CancelableRequestConsumerBase* consumer,
const GetMostRecentKeywordSearchTermsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::GetMostRecentKeywordSearchTerms,
consumer,
new history::GetMostRecentKeywordSearchTermsRequest(callback),
keyword_id, prefix, max_count);
}
void HistoryService::DeleteKeywordSearchTermForURL(const GURL& url) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteKeywordSearchTermForURL,
url);
}
void HistoryService::DeleteMatchingURLsForKeyword(TemplateURLID keyword_id,
const base::string16& term) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteMatchingURLsForKeyword,
keyword_id, term);
}
void HistoryService::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::URLsNoLongerBookmarked,
urls);
}
void HistoryService::ScheduleDBTask(history::HistoryDBTask* task,
CancelableRequestConsumerBase* consumer) {
DCHECK(thread_checker_.CalledOnValidThread());
history::HistoryDBTaskRequest* request = new history::HistoryDBTaskRequest(
base::Bind(&history::HistoryDBTask::DoneRunOnMainThread, task));
request->value = task;
Schedule(PRIORITY_UI, &HistoryBackend::ProcessDBTask, consumer, request);
}
HistoryService::Handle HistoryService::QuerySegmentUsageSince(
CancelableRequestConsumerBase* consumer,
const Time from_time,
int max_result_count,
const SegmentQueryCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::QuerySegmentUsage,
consumer, new history::QuerySegmentUsageRequest(callback),
from_time, max_result_count);
}
void HistoryService::FlushForTest(const base::Closure& flushed) {
thread_->message_loop_proxy()->PostTaskAndReply(
FROM_HERE, base::Bind(&base::DoNothing), flushed);
}
void HistoryService::SetOnBackendDestroyTask(const base::Closure& task) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetOnBackendDestroyTask,
base::MessageLoop::current(), task);
}
void HistoryService::AddPage(const GURL& url,
Time time,
const void* id_scope,
int32 page_id,
const GURL& referrer,
const history::RedirectList& redirects,
content::PageTransition transition,
history::VisitSource visit_source,
bool did_replace_entry) {
DCHECK(thread_checker_.CalledOnValidThread());
AddPage(
history::HistoryAddPageArgs(url, time, id_scope, page_id, referrer,
redirects, transition, visit_source,
did_replace_entry));
}
void HistoryService::AddPage(const GURL& url,
base::Time time,
history::VisitSource visit_source) {
DCHECK(thread_checker_.CalledOnValidThread());
AddPage(
history::HistoryAddPageArgs(url, time, NULL, 0, GURL(),
history::RedirectList(),
content::PAGE_TRANSITION_LINK,
visit_source, false));
}
void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(thread_) << "History service being called after cleanup";
if (!CanAddURL(add_page_args.url))
return;
if (visitedlink_master_) {
visitedlink_master_->AddURL(add_page_args.url);
if (!add_page_args.redirects.empty()) {
DCHECK_EQ(add_page_args.url,
add_page_args.redirects[add_page_args.redirects.size() - 1]);
for (size_t i = 0; i < add_page_args.redirects.size() - 1; i++)
visitedlink_master_->AddURL(add_page_args.redirects[i]);
}
}
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::AddPage, add_page_args);
}
void HistoryService::AddPageNoVisitForBookmark(const GURL& url,
const base::string16& title) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!CanAddURL(url))
return;
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::AddPageNoVisitForBookmark, url, title);
}
void HistoryService::SetPageTitle(const GURL& url,
const base::string16& title) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetPageTitle, url, title);
}
void HistoryService::UpdateWithPageEndTime(const void* host,
int32 page_id,
const GURL& url,
Time end_ts) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateWithPageEndTime,
host, page_id, url, end_ts);
}
void HistoryService::AddPageWithDetails(const GURL& url,
const base::string16& title,
int visit_count,
int typed_count,
Time last_visit,
bool hidden,
history::VisitSource visit_source) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!CanAddURL(url))
return;
if (visitedlink_master_)
visitedlink_master_->AddURL(url);
history::URLRow row(url);
row.set_title(title);
row.set_visit_count(visit_count);
row.set_typed_count(typed_count);
row.set_last_visit(last_visit);
row.set_hidden(hidden);
history::URLRows rows;
rows.push_back(row);
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::AddPagesWithDetails, rows, visit_source);
}
void HistoryService::AddPagesWithDetails(const history::URLRows& info,
history::VisitSource visit_source) {
DCHECK(thread_checker_.CalledOnValidThread());
if (visitedlink_master_) {
std::vector<GURL> urls;
urls.reserve(info.size());
for (history::URLRows::const_iterator i = info.begin(); i != info.end();
++i)
urls.push_back(i->url());
visitedlink_master_->AddURLs(urls);
}
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::AddPagesWithDetails, info, visit_source);
}
base::CancelableTaskTracker::TaskId HistoryService::GetFavicons(
const std::vector<GURL>& icon_urls,
int icon_types,
int desired_size_in_dip,
const std::vector<ui::ScaleFactor>& desired_scale_factors,
const FaviconService::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<chrome::FaviconBitmapResult>* results =
new std::vector<chrome::FaviconBitmapResult>();
return tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::GetFavicons,
history_backend_.get(),
icon_urls,
icon_types,
desired_size_in_dip,
desired_scale_factors,
results),
base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}
base::CancelableTaskTracker::TaskId HistoryService::GetFaviconsForURL(
const GURL& page_url,
int icon_types,
int desired_size_in_dip,
const std::vector<ui::ScaleFactor>& desired_scale_factors,
const FaviconService::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<chrome::FaviconBitmapResult>* results =
new std::vector<chrome::FaviconBitmapResult>();
return tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::GetFaviconsForURL,
history_backend_.get(),
page_url,
icon_types,
desired_size_in_dip,
desired_scale_factors,
results),
base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}
base::CancelableTaskTracker::TaskId HistoryService::GetLargestFaviconForURL(
const GURL& page_url,
const std::vector<int>& icon_types,
int minimum_size_in_pixels,
const FaviconService::FaviconRawCallback& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_checker_.CalledOnValidThread());
chrome::FaviconBitmapResult* result = new chrome::FaviconBitmapResult();
return tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::GetLargestFaviconForURL,
history_backend_.get(),
page_url,
icon_types,
minimum_size_in_pixels,
result),
base::Bind(&RunWithFaviconResult, callback, base::Owned(result)));
}
base::CancelableTaskTracker::TaskId HistoryService::GetFaviconForID(
chrome::FaviconID favicon_id,
int desired_size_in_dip,
ui::ScaleFactor desired_scale_factor,
const FaviconService::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<chrome::FaviconBitmapResult>* results =
new std::vector<chrome::FaviconBitmapResult>();
return tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::GetFaviconForID,
history_backend_.get(),
favicon_id,
desired_size_in_dip,
desired_scale_factor,
results),
base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}
base::CancelableTaskTracker::TaskId
HistoryService::UpdateFaviconMappingsAndFetch(
const GURL& page_url,
const std::vector<GURL>& icon_urls,
int icon_types,
int desired_size_in_dip,
const std::vector<ui::ScaleFactor>& desired_scale_factors,
const FaviconService::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<chrome::FaviconBitmapResult>* results =
new std::vector<chrome::FaviconBitmapResult>();
return tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::UpdateFaviconMappingsAndFetch,
history_backend_.get(),
page_url,
icon_urls,
icon_types,
desired_size_in_dip,
desired_scale_factors,
results),
base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}
void HistoryService::MergeFavicon(
const GURL& page_url,
const GURL& icon_url,
chrome::IconType icon_type,
scoped_refptr<base::RefCountedMemory> bitmap_data,
const gfx::Size& pixel_size) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!CanAddURL(page_url))
return;
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::MergeFavicon, page_url,
icon_url, icon_type, bitmap_data, pixel_size);
}
void HistoryService::SetFavicons(
const GURL& page_url,
chrome::IconType icon_type,
const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!CanAddURL(page_url))
return;
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetFavicons, page_url,
icon_type, favicon_bitmap_data);
}
void HistoryService::SetFaviconsOutOfDateForPage(const GURL& page_url) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::SetFaviconsOutOfDateForPage, page_url);
}
void HistoryService::CloneFavicons(const GURL& old_page_url,
const GURL& new_page_url) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::CloneFavicons,
old_page_url, new_page_url);
}
void HistoryService::SetImportedFavicons(
const std::vector<ImportedFaviconUsage>& favicon_usage) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::SetImportedFavicons, favicon_usage);
}
HistoryService::Handle HistoryService::QueryURL(
const GURL& url,
bool want_visits,
CancelableRequestConsumerBase* consumer,
const QueryURLCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::QueryURL, consumer,
new history::QueryURLRequest(callback), url, want_visits);
}
void HistoryService::CreateDownload(
const history::DownloadRow& create_info,
const HistoryService::DownloadCreateCallback& callback) {
DCHECK(thread_) << "History service being called after cleanup";
DCHECK(thread_checker_.CalledOnValidThread());
PostTaskAndReplyWithResult(
thread_->message_loop_proxy(), FROM_HERE,
base::Bind(&HistoryBackend::CreateDownload, history_backend_.get(),
create_info),
callback);
}
void HistoryService::GetNextDownloadId(
const content::DownloadIdCallback& callback) {
DCHECK(thread_) << "History service being called after cleanup";
DCHECK(thread_checker_.CalledOnValidThread());
PostTaskAndReplyWithResult(
thread_->message_loop_proxy(), FROM_HERE,
base::Bind(&HistoryBackend::GetNextDownloadId, history_backend_.get()),
callback);
}
void HistoryService::QueryDownloads(
const DownloadQueryCallback& callback) {
DCHECK(thread_) << "History service being called after cleanup";
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<history::DownloadRow>* rows =
new std::vector<history::DownloadRow>();
scoped_ptr<std::vector<history::DownloadRow> > scoped_rows(rows);
thread_->message_loop_proxy()->PostTaskAndReply(
FROM_HERE,
base::Bind(&HistoryBackend::QueryDownloads, history_backend_.get(), rows),
base::Bind(callback, base::Passed(&scoped_rows)));
}
void HistoryService::UpdateDownload(const history::DownloadRow& data) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateDownload, data);
}
void HistoryService::RemoveDownloads(const std::set<uint32>& ids) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::RemoveDownloads, ids);
}
HistoryService::Handle HistoryService::QueryHistory(
const base::string16& text_query,
const history::QueryOptions& options,
CancelableRequestConsumerBase* consumer,
const QueryHistoryCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::QueryHistory, consumer,
new history::QueryHistoryRequest(callback),
text_query, options);
}
HistoryService::Handle HistoryService::QueryRedirectsFrom(
const GURL& from_url,
CancelableRequestConsumerBase* consumer,
const QueryRedirectsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::QueryRedirectsFrom, consumer,
new history::QueryRedirectsRequest(callback), from_url);
}
HistoryService::Handle HistoryService::QueryRedirectsTo(
const GURL& to_url,
CancelableRequestConsumerBase* consumer,
const QueryRedirectsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryRedirectsTo, consumer,
new history::QueryRedirectsRequest(callback), to_url);
}
HistoryService::Handle HistoryService::GetVisibleVisitCountToHost(
const GURL& url,
CancelableRequestConsumerBase* consumer,
const GetVisibleVisitCountToHostCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_UI, &HistoryBackend::GetVisibleVisitCountToHost,
consumer, new history::GetVisibleVisitCountToHostRequest(callback), url);
}
HistoryService::Handle HistoryService::QueryTopURLsAndRedirects(
int result_count,
CancelableRequestConsumerBase* consumer,
const QueryTopURLsAndRedirectsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryTopURLsAndRedirects,
consumer, new history::QueryTopURLsAndRedirectsRequest(callback),
result_count);
}
HistoryService::Handle HistoryService::QueryMostVisitedURLs(
int result_count,
int days_back,
CancelableRequestConsumerBase* consumer,
const QueryMostVisitedURLsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryMostVisitedURLs,
consumer,
new history::QueryMostVisitedURLsRequest(callback),
result_count, days_back);
}
HistoryService::Handle HistoryService::QueryFilteredURLs(
int result_count,
const history::VisitFilter& filter,
bool extended_info,
CancelableRequestConsumerBase* consumer,
const QueryFilteredURLsCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
return Schedule(PRIORITY_NORMAL,
&HistoryBackend::QueryFilteredURLs,
consumer,
new history::QueryFilteredURLsRequest(callback),
result_count, filter, extended_info);
}
void HistoryService::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!thread_)
return;
switch (type) {
case chrome::NOTIFICATION_HISTORY_URLS_DELETED: {
if (visitedlink_master_) {
content::Details<history::URLsDeletedDetails> deleted_details(details);
if (deleted_details->all_history) {
visitedlink_master_->DeleteAllURLs();
} else {
URLIteratorFromURLRows iterator(deleted_details->rows);
visitedlink_master_->DeleteURLs(&iterator);
}
}
break;
}
case chrome::NOTIFICATION_TEMPLATE_URL_REMOVED:
DeleteAllSearchTermsForKeyword(
*(content::Details<TemplateURLID>(details).ptr()));
break;
default:
NOTREACHED();
}
}
void HistoryService::RebuildTable(
const scoped_refptr<URLEnumerator>& enumerator) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::IterateURLs, enumerator);
}
bool HistoryService::Init(const base::FilePath& history_dir,
BookmarkService* bookmark_service,
bool no_db) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!thread_->Start()) {
Cleanup();
return false;
}
history_dir_ = history_dir;
bookmark_service_ = bookmark_service;
no_db_ = no_db;
if (profile_) {
std::string languages =
profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
in_memory_url_index_.reset(
new history::InMemoryURLIndex(profile_, history_dir_, languages));
in_memory_url_index_->Init();
}
scoped_refptr<HistoryBackend> backend(
new HistoryBackend(history_dir_,
new BackendDelegate(
weak_ptr_factory_.GetWeakPtr(),
base::ThreadTaskRunnerHandle::Get(),
profile_),
bookmark_service_));
history_backend_.swap(backend);
std::string languages;
if (profile_) {
PrefService* prefs = profile_->GetPrefs();
languages = prefs->GetString(prefs::kAcceptLanguages);
}
ScheduleAndForget(PRIORITY_UI, &HistoryBackend::Init, languages, no_db_);
if (visitedlink_master_) {
bool result = visitedlink_master_->Init();
DCHECK(result);
}
return true;
}
void HistoryService::ScheduleAutocomplete(HistoryURLProvider* provider,
HistoryURLProviderParams* params) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_UI, &HistoryBackend::ScheduleAutocomplete,
scoped_refptr<HistoryURLProvider>(provider), params);
}
void HistoryService::ScheduleTask(SchedulePriority priority,
const base::Closure& task) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK(thread_);
CHECK(thread_->message_loop());
thread_->message_loop()->PostTask(FROM_HERE, task);
}
bool HistoryService::CanAddURL(const GURL& url) {
if (!url.is_valid())
return false;
if (url.SchemeIs(content::kJavaScriptScheme) ||
url.SchemeIs(content::kChromeDevToolsScheme) ||
url.SchemeIs(content::kChromeUIScheme) ||
url.SchemeIs(content::kViewSourceScheme) ||
url.SchemeIs(chrome::kChromeNativeScheme) ||
url.SchemeIs(chrome::kChromeSearchScheme) ||
url.SchemeIs(chrome::kDomDistillerScheme))
return false;
if (url == GURL(content::kAboutBlankURL))
return false;
return true;
}
base::WeakPtr<HistoryService> HistoryService::AsWeakPtr() {
DCHECK(thread_checker_.CalledOnValidThread());
return weak_ptr_factory_.GetWeakPtr();
}
syncer::SyncMergeResult HistoryService::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
scoped_ptr<syncer::SyncErrorFactory> error_handler) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
delete_directive_handler_.Start(this, initial_sync_data,
sync_processor.Pass());
return syncer::SyncMergeResult(type);
}
void HistoryService::StopSyncing(syncer::ModelType type) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
delete_directive_handler_.Stop();
}
syncer::SyncDataList HistoryService::GetAllSyncData(
syncer::ModelType type) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
return syncer::SyncDataList();
}
syncer::SyncError HistoryService::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) {
delete_directive_handler_.ProcessSyncChanges(this, change_list);
return syncer::SyncError();
}
syncer::SyncError HistoryService::ProcessLocalDeleteDirective(
const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive) {
DCHECK(thread_checker_.CalledOnValidThread());
return delete_directive_handler_.ProcessLocalDeleteDirective(
delete_directive);
}
void HistoryService::SetInMemoryBackend(
scoped_ptr<history::InMemoryHistoryBackend> mem_backend) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!in_memory_backend_) << "Setting mem DB twice";
in_memory_backend_.reset(mem_backend.release());
in_memory_backend_->AttachToHistoryService(profile_);
}
void HistoryService::NotifyProfileError(sql::InitStatus init_status) {
DCHECK(thread_checker_.CalledOnValidThread());
ShowProfileErrorDialog(
PROFILE_ERROR_HISTORY,
(init_status == sql::INIT_FAILURE) ?
IDS_COULDNT_OPEN_PROFILE_ERROR : IDS_PROFILE_TOO_NEW_ERROR);
}
void HistoryService::DeleteURL(const GURL& url) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURL, url);
}
void HistoryService::DeleteURLsForTest(const std::vector<GURL>& urls) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURLs, urls);
}
void HistoryService::ExpireHistoryBetween(
const std::set<GURL>& restrict_urls,
Time begin_time,
Time end_time,
const base::Closure& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_);
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(history_backend_.get());
tracker->PostTaskAndReply(thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::ExpireHistoryBetween,
history_backend_,
restrict_urls,
begin_time,
end_time),
callback);
}
void HistoryService::ExpireHistory(
const std::vector<history::ExpireHistoryArgs>& expire_list,
const base::Closure& callback,
base::CancelableTaskTracker* tracker) {
DCHECK(thread_);
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(history_backend_.get());
tracker->PostTaskAndReply(
thread_->message_loop_proxy().get(),
FROM_HERE,
base::Bind(&HistoryBackend::ExpireHistory, history_backend_, expire_list),
callback);
}
void HistoryService::ExpireLocalAndRemoteHistoryBetween(
const std::set<GURL>& restrict_urls,
Time begin_time,
Time end_time,
const base::Closure& callback,
base::CancelableTaskTracker* tracker) {
history::WebHistoryService* web_history =
WebHistoryServiceFactory::GetForProfile(profile_);
if (web_history) {
DCHECK(restrict_urls.empty());
delete_directive_handler_.CreateDeleteDirectives(
std::set<int64>(), begin_time, end_time);
web_history->ExpireHistoryBetween(
restrict_urls, begin_time, end_time,
base::Bind(&ExpireWebHistoryComplete));
}
ExpireHistoryBetween(restrict_urls, begin_time, end_time, callback, tracker);
}
void HistoryService::BroadcastNotificationsHelper(
int type,
scoped_ptr<history::HistoryDetails> details) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!g_browser_process)
return;
if (!thread_)
return;
content::Source<Profile> source(profile_);
content::Details<history::HistoryDetails> det(details.get());
content::NotificationService::current()->Notify(type, source, det);
}
void HistoryService::OnDBLoaded() {
DCHECK(thread_checker_.CalledOnValidThread());
backend_loaded_ = true;
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_HISTORY_LOADED,
content::Source<Profile>(profile_),
content::Details<HistoryService>(this));
}
bool HistoryService::GetRowForURL(const GURL& url, history::URLRow* url_row) {
DCHECK(thread_checker_.CalledOnValidThread());
history::URLDatabase* db = InMemoryDatabase();
return db && (db->GetRowForURL(url, url_row) != 0);
}
void HistoryService::AddVisitDatabaseObserver(
history::VisitDatabaseObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
visit_database_observers_.AddObserver(observer);
}
void HistoryService::RemoveVisitDatabaseObserver(
history::VisitDatabaseObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread());
visit_database_observers_.RemoveObserver(observer);
}
void HistoryService::NotifyVisitDBObserversOnAddVisit(
const history::BriefVisitInfo& info) {
DCHECK(thread_checker_.CalledOnValidThread());
FOR_EACH_OBSERVER(history::VisitDatabaseObserver, visit_database_observers_,
OnAddVisit(info));
}