Commit 4c3d9d6a authored by boliu@chromium.org's avatar boliu@chromium.org

Remove VisitedLink dependency on rest of chrome

This is in preparation of componentizing VisitedLink implementation and
be shared with Android WebView.

* Added VisitedLinkDelegate which HistoryService implements.
* Removed VisitedLinkMasterFactory and have HistoryService directly own
  VisitedLinkMaster.
* Introduce URLIterator interface for DeleteURLs.

Last committed in https://src.chromium.org/viewvc/chrome?view=rev&revision=175186

Reverted in https://src.chromium.org/viewvc/chrome?view=rev&revision=175217
due to memory leaks.

Before this patch, VisitedLink was a ProfileKeyedService and some using
HistoryService did not create VisitedLink at all. After this patch,
VisitedLink is created and owned directly by HistoryService, so they are
now created for some tests depending on which HistoryService constructor
is used.

First version was leaking URLEnumerator in HistoryService::RebuildTable
which was doing manual ref counting (AddRef/Release) calls. Some tests do
not start the background thread at all, so URLEnumerator::OnComplete is
never called to delete itself.

Fixed by properly ref-counting URLEnumerator with scoped_refptr in this
path.

BUG=168716

Review URL: https://chromiumcodereview.appspot.com/11573060

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175906 0039d316-1c4b-4281-b951-d872f2087c98
parent 43f8b0a6
...@@ -51,6 +51,8 @@ include_rules = [ ...@@ -51,6 +51,8 @@ include_rules = [
"!chrome/browser/ui/profile_error_dialog.h", "!chrome/browser/ui/profile_error_dialog.h",
"!chrome/browser/ui/webui/ntp/most_visited_handler.h", "!chrome/browser/ui/webui/ntp/most_visited_handler.h",
"!chrome/browser/ui/webui/ntp/new_tab_ui.h", "!chrome/browser/ui/webui/ntp/new_tab_ui.h",
# TODO(boliu): Allow visitedlink after they are componentized.
"!chrome/browser/visitedlink/visitedlink_delegate.h",
"!chrome/browser/visitedlink/visitedlink_master.h", "!chrome/browser/visitedlink/visitedlink_master.h",
] ]
......
...@@ -111,6 +111,29 @@ void RunWithFaviconResults( ...@@ -111,6 +111,29 @@ void RunWithFaviconResults(
callback.Run(results->bitmap_results, results->size_map); callback.Run(results->bitmap_results, results->size_map);
} }
// Extract history::URLRows into GURLs for VisitedLinkMaster.
class URLIteratorFromURLRows : public 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);
};
} // namespace } // namespace
// Sends messages from the backend to us on the main thread. This must be a // Sends messages from the backend to us on the main thread. This must be a
...@@ -208,6 +231,8 @@ HistoryService::HistoryService(Profile* profile) ...@@ -208,6 +231,8 @@ HistoryService::HistoryService(Profile* profile)
: weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
thread_(new base::Thread(kHistoryThreadName)), thread_(new base::Thread(kHistoryThreadName)),
profile_(profile), profile_(profile),
visitedlink_master_(new VisitedLinkMaster(
profile, ALLOW_THIS_IN_INITIALIZER_LIST(this))),
backend_loaded_(false), backend_loaded_(false),
current_backend_id_(-1), current_backend_id_(-1),
bookmark_service_(NULL), bookmark_service_(NULL),
...@@ -472,10 +497,8 @@ void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) { ...@@ -472,10 +497,8 @@ void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) {
return; return;
// Add link & all redirects to visited link list. // Add link & all redirects to visited link list.
VisitedLinkMaster* visited_links; if (visitedlink_master_) {
if (profile_ && visitedlink_master_->AddURL(add_page_args.url);
(visited_links = VisitedLinkMaster::FromProfile(profile_))) {
visited_links->AddURL(add_page_args.url);
if (!add_page_args.redirects.empty()) { if (!add_page_args.redirects.empty()) {
// We should not be asked to add a page in the middle of a redirect chain. // We should not be asked to add a page in the middle of a redirect chain.
...@@ -485,7 +508,7 @@ void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) { ...@@ -485,7 +508,7 @@ void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) {
// We need the !redirects.empty() condition above since size_t is unsigned // We need the !redirects.empty() condition above since size_t is unsigned
// and will wrap around when we subtract one from a 0 size. // and will wrap around when we subtract one from a 0 size.
for (size_t i = 0; i < add_page_args.redirects.size() - 1; i++) for (size_t i = 0; i < add_page_args.redirects.size() - 1; i++)
visited_links->AddURL(add_page_args.redirects[i]); visitedlink_master_->AddURL(add_page_args.redirects[i]);
} }
} }
...@@ -530,11 +553,8 @@ void HistoryService::AddPageWithDetails(const GURL& url, ...@@ -530,11 +553,8 @@ void HistoryService::AddPageWithDetails(const GURL& url,
return; return;
// Add to the visited links system. // Add to the visited links system.
VisitedLinkMaster* visited_links; if (visitedlink_master_)
if (profile_ && visitedlink_master_->AddURL(url);
(visited_links = VisitedLinkMaster::FromProfile(profile_))) {
visited_links->AddURL(url);
}
history::URLRow row(url); history::URLRow row(url);
row.set_title(title); row.set_title(title);
...@@ -554,16 +574,14 @@ void HistoryService::AddPagesWithDetails(const history::URLRows& info, ...@@ -554,16 +574,14 @@ void HistoryService::AddPagesWithDetails(const history::URLRows& info,
history::VisitSource visit_source) { history::VisitSource visit_source) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
// Add to the visited links system. // Add to the visited links system.
VisitedLinkMaster* visited_links; if (visitedlink_master_) {
if (profile_ &&
(visited_links = VisitedLinkMaster::FromProfile(profile_))) {
std::vector<GURL> urls; std::vector<GURL> urls;
urls.reserve(info.size()); urls.reserve(info.size());
for (history::URLRows::const_iterator i = info.begin(); i != info.end(); for (history::URLRows::const_iterator i = info.begin(); i != info.end();
++i) ++i)
urls.push_back(i->url()); urls.push_back(i->url());
visited_links->AddURLs(urls); visitedlink_master_->AddURLs(urls);
} }
ScheduleAndForget(PRIORITY_NORMAL, ScheduleAndForget(PRIORITY_NORMAL,
...@@ -720,11 +738,6 @@ void HistoryService::SetImportedFavicons( ...@@ -720,11 +738,6 @@ void HistoryService::SetImportedFavicons(
&HistoryBackend::SetImportedFavicons, favicon_usage); &HistoryBackend::SetImportedFavicons, favicon_usage);
} }
void HistoryService::IterateURLs(URLEnumerator* enumerator) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::IterateURLs, enumerator);
}
HistoryService::Handle HistoryService::QueryURL( HistoryService::Handle HistoryService::QueryURL(
const GURL& url, const GURL& url,
bool want_visits, bool want_visits,
...@@ -902,17 +915,16 @@ void HistoryService::Observe(int type, ...@@ -902,17 +915,16 @@ void HistoryService::Observe(int type,
// delete notifications are by time. We would also like to be more // delete notifications are by time. We would also like to be more
// respectful of privacy and never tell the user something is gone when it // respectful of privacy and never tell the user something is gone when it
// isn't. Therefore, we update the delete URLs after the fact. // isn't. Therefore, we update the delete URLs after the fact.
if (!profile_) if (visitedlink_master_) {
return; // No profile, probably unit testing. content::Details<history::URLsDeletedDetails> deleted_details(details);
content::Details<history::URLsDeletedDetails> deleted_details(details);
VisitedLinkMaster* visited_links = if (deleted_details->all_history) {
VisitedLinkMaster::FromProfile(profile_); visitedlink_master_->DeleteAllURLs();
if (!visited_links) } else {
return; // Nobody to update. URLIteratorFromURLRows iterator(deleted_details->rows);
if (deleted_details->all_history) visitedlink_master_->DeleteURLs(&iterator);
visited_links->DeleteAllURLs(); }
else // Delete individual ones. }
visited_links->DeleteURLs(deleted_details->rows);
break; break;
} }
...@@ -926,6 +938,23 @@ void HistoryService::Observe(int type, ...@@ -926,6 +938,23 @@ void HistoryService::Observe(int type,
} }
} }
bool HistoryService::AreEquivalentContexts(content::BrowserContext* context1,
content::BrowserContext* context2) {
DCHECK(context1);
DCHECK(context2);
Profile* profile1 = Profile::FromBrowserContext(context1);
Profile* profile2 = Profile::FromBrowserContext(context2);
return profile1->IsSameProfile(profile2);
}
void HistoryService::RebuildTable(
const scoped_refptr<URLEnumerator>& enumerator) {
DCHECK(thread_checker_.CalledOnValidThread());
ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::IterateURLs, enumerator);
}
bool HistoryService::Init(const FilePath& history_dir, bool HistoryService::Init(const FilePath& history_dir,
BookmarkService* bookmark_service, BookmarkService* bookmark_service,
bool no_db) { bool no_db) {
...@@ -949,6 +978,12 @@ bool HistoryService::Init(const FilePath& history_dir, ...@@ -949,6 +978,12 @@ bool HistoryService::Init(const FilePath& history_dir,
// Create the history backend. // Create the history backend.
LoadBackendIfNecessary(); LoadBackendIfNecessary();
if (visitedlink_master_) {
bool result = visitedlink_master_->Init();
DCHECK(result);
}
return true; return true;
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "chrome/browser/history/history_types.h" #include "chrome/browser/history/history_types.h"
#include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/search_engines/template_url_id.h" #include "chrome/browser/search_engines/template_url_id.h"
#include "chrome/browser/visitedlink/visitedlink_delegate.h"
#include "chrome/common/cancelable_task_tracker.h" #include "chrome/common/cancelable_task_tracker.h"
#include "chrome/common/ref_counted_util.h" #include "chrome/common/ref_counted_util.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
...@@ -45,6 +46,7 @@ class HistoryURLProvider; ...@@ -45,6 +46,7 @@ class HistoryURLProvider;
class PageUsageData; class PageUsageData;
class PageUsageRequest; class PageUsageRequest;
class Profile; class Profile;
class VisitedLinkMaster;
struct HistoryURLProviderParams; struct HistoryURLProviderParams;
namespace base { namespace base {
...@@ -107,7 +109,8 @@ class HistoryDBTask : public base::RefCountedThreadSafe<HistoryDBTask> { ...@@ -107,7 +109,8 @@ class HistoryDBTask : public base::RefCountedThreadSafe<HistoryDBTask> {
class HistoryService : public CancelableRequestProvider, class HistoryService : public CancelableRequestProvider,
public content::NotificationObserver, public content::NotificationObserver,
public syncer::SyncableService, public syncer::SyncableService,
public ProfileKeyedService { public ProfileKeyedService,
public VisitedLinkDelegate {
public: public:
// Miscellaneous commonly-used types. // Miscellaneous commonly-used types.
typedef std::vector<PageUsageData*> PageUsageDataList; typedef std::vector<PageUsageData*> PageUsageDataList;
...@@ -261,31 +264,6 @@ class HistoryService : public CancelableRequestProvider, ...@@ -261,31 +264,6 @@ class HistoryService : public CancelableRequestProvider,
// Querying ------------------------------------------------------------------ // Querying ------------------------------------------------------------------
// Callback class that a client can implement to iterate over URLs. The
// callbacks WILL BE CALLED ON THE BACKGROUND THREAD! Your implementation
// should handle this appropriately.
class URLEnumerator {
public:
// Indicates that a URL is available. There will be exactly one call for
// every URL in history.
virtual void OnURL(const history::URLRow& url_row) = 0;
// Indicates we are done iterating over URLs. Once called, there will be no
// more callbacks made. This call is guaranteed to occur, even if there are
// no URLs. If all URLs were iterated, success will be true.
virtual void OnComplete(bool success) = 0;
protected:
virtual ~URLEnumerator() {}
};
// Enumerate all URLs in history. The given iterator will be owned by the
// caller, so the caller should ensure it exists until OnComplete is called.
// You should not generally use this since it will be slow to slurp all URLs
// in from the database. It is designed for rebuilding the visited link
// database from history.
void IterateURLs(URLEnumerator* iterator);
// Returns the information about the requested URL. If the URL is found, // Returns the information about the requested URL. If the URL is found,
// success will be true and the information will be in the URLRow parameter. // success will be true and the information will be in the URLRow parameter.
// On success, the visits, if requested, will be sorted by date. If they have // On success, the visits, if requested, will be sorted by date. If they have
...@@ -679,6 +657,13 @@ class HistoryService : public CancelableRequestProvider, ...@@ -679,6 +657,13 @@ class HistoryService : public CancelableRequestProvider,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE; const content::NotificationDetails& details) OVERRIDE;
// Implementation of VisitedLinkDelegate.
virtual bool AreEquivalentContexts(
content::BrowserContext* context1,
content::BrowserContext* context2) OVERRIDE;
virtual void RebuildTable(
const scoped_refptr<URLEnumerator>& enumerator) OVERRIDE;
// Low-level Init(). Same as the public version, but adds a |no_db| parameter // Low-level Init(). Same as the public version, but adds a |no_db| parameter
// that is only set by unittests which causes the backend to not init its DB. // that is only set by unittests which causes the backend to not init its DB.
bool Init(const FilePath& history_dir, bool Init(const FilePath& history_dir,
...@@ -1103,6 +1088,10 @@ class HistoryService : public CancelableRequestProvider, ...@@ -1103,6 +1088,10 @@ class HistoryService : public CancelableRequestProvider,
// The profile, may be null when testing. // The profile, may be null when testing.
Profile* profile_; Profile* profile_;
// Used for propagating link highlighting data across renderers. May be null
// in tests.
scoped_ptr<VisitedLinkMaster> visitedlink_master_;
// Has the backend finished loading? The backend is loaded once Init has // Has the backend finished loading? The backend is loaded once Init has
// completed. // completed.
bool backend_loaded_; bool backend_loaded_;
......
...@@ -1058,13 +1058,14 @@ void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, ...@@ -1058,13 +1058,14 @@ void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url,
db_->AddURL(url_info); db_->AddURL(url_info);
} }
void HistoryBackend::IterateURLs(HistoryService::URLEnumerator* iterator) { void HistoryBackend::IterateURLs(
const scoped_refptr<VisitedLinkDelegate::URLEnumerator>& iterator) {
if (db_.get()) { if (db_.get()) {
HistoryDatabase::URLEnumerator e; HistoryDatabase::URLEnumerator e;
if (db_->InitURLEnumeratorForEverything(&e)) { if (db_->InitURLEnumeratorForEverything(&e)) {
URLRow info; URLRow info;
while (e.GetNextURL(&info)) { while (e.GetNextURL(&info)) {
iterator->OnURL(info); iterator->OnURL(info.url());
} }
iterator->OnComplete(true); // Success. iterator->OnComplete(true); // Success.
return; return;
......
...@@ -173,7 +173,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, ...@@ -173,7 +173,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
void ScheduleAutocomplete(HistoryURLProvider* provider, void ScheduleAutocomplete(HistoryURLProvider* provider,
HistoryURLProviderParams* params); HistoryURLProviderParams* params);
void IterateURLs(HistoryService::URLEnumerator* enumerator); void IterateURLs(
const scoped_refptr<VisitedLinkDelegate::URLEnumerator>& enumerator);
void QueryURL(scoped_refptr<QueryURLRequest> request, void QueryURL(scoped_refptr<QueryURLRequest> request,
const GURL& url, const GURL& url,
bool want_visits); bool want_visits);
......
...@@ -74,7 +74,6 @@ ...@@ -74,7 +74,6 @@
#include "chrome/browser/ui/webui/chrome_url_data_manager_factory.h" #include "chrome/browser/ui/webui/chrome_url_data_manager_factory.h"
#include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h" #include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
#include "chrome/browser/user_style_sheet_watcher_factory.h" #include "chrome/browser/user_style_sheet_watcher_factory.h"
#include "chrome/browser/visitedlink/visitedlink_master_factory.h"
#include "chrome/browser/webdata/web_data_service_factory.h" #include "chrome/browser/webdata/web_data_service_factory.h"
#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
...@@ -323,7 +322,6 @@ void ProfileDependencyManager::AssertFactoriesBuilt() { ...@@ -323,7 +322,6 @@ void ProfileDependencyManager::AssertFactoriesBuilt() {
#endif #endif
TokenServiceFactory::GetInstance(); TokenServiceFactory::GetInstance();
UserStyleSheetWatcherFactory::GetInstance(); UserStyleSheetWatcherFactory::GetInstance();
VisitedLinkMasterFactory::GetInstance();
WebDataServiceFactory::GetInstance(); WebDataServiceFactory::GetInstance();
#if defined(ENABLE_WEB_INTENTS) #if defined(ENABLE_WEB_INTENTS)
WebIntentsRegistryFactory::GetInstance(); WebIntentsRegistryFactory::GetInstance();
......
// Copyright (c) 2012 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_VISITEDLINK_VISITEDLINK_DELEGATE_H_
#define CHROME_BROWSER_VISITEDLINK_VISITEDLINK_DELEGATE_H_
#include "base/memory/ref_counted.h"
class GURL;
namespace content {
class BrowserContext;
} // namespace content
// Delegate class that clients of VisitedLinkMaster must implement.
class VisitedLinkDelegate {
public:
// Returns true when the two BrowserContexts are equivalent.
virtual bool AreEquivalentContexts(content::BrowserContext* context1,
content::BrowserContext* context2) = 0;
// See RebuildTable.
class URLEnumerator : public base::RefCountedThreadSafe<URLEnumerator> {
public:
// Call this with each URL to rebuild the table.
virtual void OnURL(const GURL& url) = 0;
// This must be called by Delegate after RebuildTable is called. |success|
// indicates all URLs have been returned successfully. The URLEnumerator
// object cannot be used by the delegate after this call.
virtual void OnComplete(bool success) = 0;
protected:
virtual ~URLEnumerator() {}
private:
friend class base::RefCountedThreadSafe<URLEnumerator>;
};
// Delegate class is responsible for persisting the list of visited URLs
// across browser runs. This is called by VisitedLinkMaster to repopulate
// its internal table. Note that methods on enumerator can be called on any
// thread but the delegate is responsible for synchronizating the calls.
virtual void RebuildTable(const scoped_refptr<URLEnumerator>& enumerator) = 0;
protected:
virtual ~VisitedLinkDelegate() {}
};
#endif // CHROME_BROWSER_VISITEDLINK_VISITEDLINK_DELEGATE_H_
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
#include "chrome/browser/visitedlink/visitedlink_event_listener.h" #include "chrome/browser/visitedlink/visitedlink_event_listener.h"
#include "base/shared_memory.h" #include "base/shared_memory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/visitedlink/visitedlink_delegate.h"
#include "chrome/browser/visitedlink/visitedlink_master_factory.h"
#include "chrome/common/render_messages.h" #include "chrome/common/render_messages.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h" #include "content/public/browser/notification_types.h"
...@@ -108,8 +107,11 @@ class VisitedLinkUpdater { ...@@ -108,8 +107,11 @@ class VisitedLinkUpdater {
VisitedLinkCommon::Fingerprints pending_; VisitedLinkCommon::Fingerprints pending_;
}; };
VisitedLinkEventListener::VisitedLinkEventListener(Profile* profile) VisitedLinkEventListener::VisitedLinkEventListener(
: profile_(profile) { VisitedLinkMaster* master,
content::BrowserContext* browser_context)
: master_(master),
browser_context_(browser_context) {
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
content::NotificationService::AllBrowserContextsAndSources()); content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
...@@ -134,12 +136,8 @@ void VisitedLinkEventListener::NewTable(base::SharedMemory* table_memory) { ...@@ -134,12 +136,8 @@ void VisitedLinkEventListener::NewTable(base::SharedMemory* table_memory) {
content::RenderProcessHost::FromID(i->first); content::RenderProcessHost::FromID(i->first);
if (!process) if (!process)
continue; continue;
Profile* profile = Profile::FromBrowserContext(
process->GetBrowserContext()); i->second->SendVisitedLinkTable(table_memory);
VisitedLinkMaster* master =
VisitedLinkMasterFactory::GetForProfile(profile);
if (master && master->shared_memory() == table_memory)
i->second->SendVisitedLinkTable(table_memory);
} }
} }
...@@ -181,22 +179,18 @@ void VisitedLinkEventListener::Observe( ...@@ -181,22 +179,18 @@ void VisitedLinkEventListener::Observe(
case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
content::RenderProcessHost* process = content::RenderProcessHost* process =
content::Source<content::RenderProcessHost>(source).ptr(); content::Source<content::RenderProcessHost>(source).ptr();
Profile* profile = if (!master_->GetDelegate()->AreEquivalentContexts(
Profile::FromBrowserContext(process->GetBrowserContext()); browser_context_, process->GetBrowserContext()))
if (!profile_->IsSameProfile(profile))
return; return;
updaters_[process->GetID()] =
make_linked_ptr(new VisitedLinkUpdater(process->GetID()));
// Initialize support for visited links. Send the renderer process its // Happens on browser start up.
// initial set of visited links. if (!master_->shared_memory())
VisitedLinkMaster* master =
VisitedLinkMasterFactory::GetForProfile(profile);
if (!master)
return; return;
updaters_[process->GetID()] =
make_linked_ptr(new VisitedLinkUpdater(process->GetID()));
updaters_[process->GetID()]->SendVisitedLinkTable( updaters_[process->GetID()]->SendVisitedLinkTable(
master->shared_memory()); master_->shared_memory());
break; break;
} }
case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
......
...@@ -17,17 +17,21 @@ ...@@ -17,17 +17,21 @@
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
class Profile;
class VisitedLinkUpdater; class VisitedLinkUpdater;
namespace base { namespace base {
class SharedMemory; class SharedMemory;
} }
namespace content {
class BrowserContext;
} // namespace content
class VisitedLinkEventListener : public VisitedLinkMaster::Listener, class VisitedLinkEventListener : public VisitedLinkMaster::Listener,
public content::NotificationObserver { public content::NotificationObserver {
public: public:
explicit VisitedLinkEventListener(Profile* profile); VisitedLinkEventListener(VisitedLinkMaster* master,
content::BrowserContext* browser_context);
virtual ~VisitedLinkEventListener(); virtual ~VisitedLinkEventListener();
virtual void NewTable(base::SharedMemory* table_memory) OVERRIDE; virtual void NewTable(base::SharedMemory* table_memory) OVERRIDE;
...@@ -51,7 +55,11 @@ class VisitedLinkEventListener : public VisitedLinkMaster::Listener, ...@@ -51,7 +55,11 @@ class VisitedLinkEventListener : public VisitedLinkMaster::Listener,
typedef std::map<int, linked_ptr<VisitedLinkUpdater> > Updaters; typedef std::map<int, linked_ptr<VisitedLinkUpdater> > Updaters;
Updaters updaters_; Updaters updaters_;
Profile* profile_; VisitedLinkMaster* master_;
// Used to filter RENDERER_PROCESS_CREATED notifications to renderers that
// belong to this BrowserContext.
content::BrowserContext* browser_context_;
DISALLOW_COPY_AND_ASSIGN(VisitedLinkEventListener); DISALLOW_COPY_AND_ASSIGN(VisitedLinkEventListener);
}; };
......
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
#include "base/rand_util.h" #include "base/rand_util.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "chrome/browser/history/history.h" #include "chrome/browser/visitedlink/visitedlink_delegate.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/visitedlink/visitedlink_event_listener.h" #include "chrome/browser/visitedlink/visitedlink_event_listener.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "googleurl/src/gurl.h"
using content::BrowserThread; using content::BrowserThread;
using file_util::ScopedFILE; using file_util::ScopedFILE;
...@@ -138,8 +138,7 @@ void AsyncClose(FILE** file) { ...@@ -138,8 +138,7 @@ void AsyncClose(FILE** file) {
// which case it notifies the builder via DisownMaster(). The builder will // which case it notifies the builder via DisownMaster(). The builder will
// delete itself once rebuilding is complete, and not execute any callback. // delete itself once rebuilding is complete, and not execute any callback.
class VisitedLinkMaster::TableBuilder class VisitedLinkMaster::TableBuilder
: public HistoryService::URLEnumerator, : public VisitedLinkDelegate::URLEnumerator {
public base::RefCountedThreadSafe<TableBuilder> {
public: public:
TableBuilder(VisitedLinkMaster* master, TableBuilder(VisitedLinkMaster* master,
const uint8 salt[LINK_SALT_LENGTH]); const uint8 salt[LINK_SALT_LENGTH]);
...@@ -150,14 +149,12 @@ class VisitedLinkMaster::TableBuilder ...@@ -150,14 +149,12 @@ class VisitedLinkMaster::TableBuilder
// table will be being rebuilt simultaneously on the other thread. // table will be being rebuilt simultaneously on the other thread.
void DisownMaster(); void DisownMaster();
// HistoryService::URLEnumerator // VisitedLinkDelegate::URLEnumerator
virtual void OnURL(const history::URLRow& url_row); virtual void OnURL(const GURL& url);
virtual void OnComplete(bool succeed); virtual void OnComplete(bool succeed);
private: private:
friend class base::RefCountedThreadSafe<TableBuilder>; virtual ~TableBuilder() {}
~TableBuilder() {}
// OnComplete mashals to this function on the main thread to do the // OnComplete mashals to this function on the main thread to do the
// notification. // notification.
...@@ -174,30 +171,34 @@ class VisitedLinkMaster::TableBuilder ...@@ -174,30 +171,34 @@ class VisitedLinkMaster::TableBuilder
// Stores the fingerprints we computed on the background thread. // Stores the fingerprints we computed on the background thread.
VisitedLinkCommon::Fingerprints fingerprints_; VisitedLinkCommon::Fingerprints fingerprints_;
DISALLOW_COPY_AND_ASSIGN(TableBuilder);
}; };
// VisitedLinkMaster ---------------------------------------------------------- // VisitedLinkMaster ----------------------------------------------------------
VisitedLinkMaster::VisitedLinkMaster(Profile* profile) VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context,
: profile_(profile) { VisitedLinkDelegate* delegate)
listener_.reset(new VisitedLinkEventListener(profile)); : browser_context_(browser_context),
DCHECK(listener_.get()); delegate_(delegate),
listener_(new VisitedLinkEventListener(
ALLOW_THIS_IN_INITIALIZER_LIST(this), browser_context)) {
InitMembers(); InitMembers();
} }
VisitedLinkMaster::VisitedLinkMaster(Listener* listener, VisitedLinkMaster::VisitedLinkMaster(Listener* listener,
HistoryService* history_service, VisitedLinkDelegate* delegate,
bool suppress_rebuild, bool suppress_rebuild,
const FilePath& filename, const FilePath& filename,
int32 default_table_size) int32 default_table_size)
: profile_(NULL) { : browser_context_(NULL),
delegate_(delegate) {
listener_.reset(listener); listener_.reset(listener);
DCHECK(listener_.get()); DCHECK(listener_.get());
InitMembers(); InitMembers();
database_name_override_ = filename; database_name_override_ = filename;
table_size_override_ = default_table_size; table_size_override_ = default_table_size;
history_service_override_ = history_service;
suppress_rebuild_ = suppress_rebuild; suppress_rebuild_ = suppress_rebuild;
} }
...@@ -220,7 +221,6 @@ void VisitedLinkMaster::InitMembers() { ...@@ -220,7 +221,6 @@ void VisitedLinkMaster::InitMembers() {
shared_memory_serial_ = 0; shared_memory_serial_ = 0;
used_items_ = 0; used_items_ = 0;
table_size_override_ = 0; table_size_override_ = 0;
history_service_override_ = NULL;
suppress_rebuild_ = false; suppress_rebuild_ = false;
sequence_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); sequence_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
...@@ -241,7 +241,9 @@ bool VisitedLinkMaster::Init() { ...@@ -241,7 +241,9 @@ bool VisitedLinkMaster::Init() {
VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) { VisitedLinkMaster::Hash VisitedLinkMaster::TryToAddURL(const GURL& url) {
// Extra check that we are not incognito. This should not happen. // Extra check that we are not incognito. This should not happen.
if (profile_ && profile_->IsOffTheRecord()) { // TODO(boliu): Move this check to HistoryService when IsOffTheRecord is
// removed from BrowserContext.
if (browser_context_ && browser_context_->IsOffTheRecord()) {
NOTREACHED(); NOTREACHED();
return null_hash_; return null_hash_;
} }
...@@ -320,10 +322,12 @@ void VisitedLinkMaster::DeleteAllURLs() { ...@@ -320,10 +322,12 @@ void VisitedLinkMaster::DeleteAllURLs() {
listener_->Reset(); listener_->Reset();
} }
void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) { VisitedLinkDelegate* VisitedLinkMaster::GetDelegate() {
typedef std::set<GURL>::const_iterator SetIterator; return delegate_;
}
if (rows.empty()) void VisitedLinkMaster::DeleteURLs(URLIterator* urls) {
if (!urls->HasNextURL())
return; return;
listener_->Reset(); listener_->Reset();
...@@ -331,9 +335,8 @@ void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) { ...@@ -331,9 +335,8 @@ void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) {
if (table_builder_) { if (table_builder_) {
// A rebuild is in progress, save this deletion in the temporary list so // A rebuild is in progress, save this deletion in the temporary list so
// it can be added once rebuild is complete. // it can be added once rebuild is complete.
for (history::URLRows::const_iterator i = rows.begin(); i != rows.end(); while (urls->HasNextURL()) {
++i) { const GURL& url(urls->NextURL());
const GURL& url(i->url());
if (!url.is_valid()) if (!url.is_valid())
continue; continue;
...@@ -357,9 +360,8 @@ void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) { ...@@ -357,9 +360,8 @@ void VisitedLinkMaster::DeleteURLs(const history::URLRows& rows) {
// Compute the deleted URLs' fingerprints and delete them // Compute the deleted URLs' fingerprints and delete them
std::set<Fingerprint> deleted_fingerprints; std::set<Fingerprint> deleted_fingerprints;
for (history::URLRows::const_iterator i = rows.begin(); i != rows.end(); while (urls->HasNextURL()) {
++i) { const GURL& url(urls->NextURL());
const GURL& url(i->url());
if (!url.is_valid()) if (!url.is_valid())
continue; continue;
deleted_fingerprints.insert( deleted_fingerprints.insert(
...@@ -581,7 +583,7 @@ bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) { ...@@ -581,7 +583,7 @@ bool VisitedLinkMaster::InitFromScratch(bool suppress_rebuild) {
// to disk. We don't want to save explicitly here, since the rebuild may // to disk. We don't want to save explicitly here, since the rebuild may
// not complete, leaving us with an empty but valid visited link database. // not complete, leaving us with an empty but valid visited link database.
// In the future, we won't know we need to try rebuilding again. // In the future, we won't know we need to try rebuilding again.
return RebuildTableFromHistory(); return RebuildTableFromDelegate();
} }
bool VisitedLinkMaster::ReadFileHeader(FILE* file, bool VisitedLinkMaster::ReadFileHeader(FILE* file,
...@@ -641,10 +643,10 @@ bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) { ...@@ -641,10 +643,10 @@ bool VisitedLinkMaster::GetDatabaseFileName(FilePath* filename) {
return true; return true;
} }
if (!profile_ || profile_->GetPath().empty()) if (!browser_context_ || browser_context_->GetPath().empty())
return false; return false;
FilePath profile_dir = profile_->GetPath(); FilePath profile_dir = browser_context_->GetPath();
*filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links")); *filename = profile_dir.Append(FILE_PATH_LITERAL("Visited Links"));
return true; return true;
} }
...@@ -810,31 +812,12 @@ uint32 VisitedLinkMaster::NewTableSizeForCount(int32 item_count) const { ...@@ -810,31 +812,12 @@ uint32 VisitedLinkMaster::NewTableSizeForCount(int32 item_count) const {
} }
// See the TableBuilder definition in the header file for how this works. // See the TableBuilder definition in the header file for how this works.
bool VisitedLinkMaster::RebuildTableFromHistory() { bool VisitedLinkMaster::RebuildTableFromDelegate() {
DCHECK(!table_builder_); DCHECK(!table_builder_);
if (table_builder_)
return false;
HistoryService* history_service = history_service_override_;
if (!history_service && profile_) {
history_service =
HistoryServiceFactory::GetForProfile(profile_,
Profile::EXPLICIT_ACCESS);
}
if (!history_service) {
DLOG(WARNING) << "Attempted to rebuild visited link table, but couldn't "
"obtain a HistoryService.";
return false;
}
// TODO(brettw) make sure we have reasonable salt! // TODO(brettw) make sure we have reasonable salt!
table_builder_ = new TableBuilder(this, salt_); table_builder_ = new TableBuilder(this, salt_);
delegate_->RebuildTable(table_builder_);
// Make sure the table builder stays live during the call, even if the
// master is deleted. This is balanced in TableBuilder::OnCompleteMainThread.
table_builder_->AddRef();
history_service->IterateURLs(table_builder_);
return true; return true;
} }
...@@ -958,8 +941,7 @@ void VisitedLinkMaster::TableBuilder::DisownMaster() { ...@@ -958,8 +941,7 @@ void VisitedLinkMaster::TableBuilder::DisownMaster() {
master_ = NULL; master_ = NULL;
} }
void VisitedLinkMaster::TableBuilder::OnURL(const history::URLRow& url_row) { void VisitedLinkMaster::TableBuilder::OnURL(const GURL& url) {
const GURL& url(url_row.url());
if (!url.is_empty()) { if (!url.is_empty()) {
fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint( fingerprints_.push_back(VisitedLinkMaster::ComputeURLFingerprint(
url.spec().data(), url.spec().length(), salt_)); url.spec().data(), url.spec().length(), salt_));
...@@ -980,8 +962,4 @@ void VisitedLinkMaster::TableBuilder::OnComplete(bool success) { ...@@ -980,8 +962,4 @@ void VisitedLinkMaster::TableBuilder::OnComplete(bool success) {
void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() { void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() {
if (master_) if (master_)
master_->OnTableRebuildComplete(success_, fingerprints_); master_->OnTableRebuildComplete(success_, fingerprints_);
// WILL (generally) DELETE THIS! This balances the AddRef in
// VisitedLinkMaster::RebuildTableFromHistory.
Release();
} }
...@@ -11,19 +11,25 @@ ...@@ -11,19 +11,25 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include "base/callback.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/file_path.h" #include "base/file_path.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/shared_memory.h" #include "base/shared_memory.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/common/visitedlink_common.h" #include "chrome/common/visitedlink_common.h"
#if defined(UNIT_TEST) || defined(PERF_TEST) || !defined(NDEBUG)
#include "base/logging.h"
#endif
class GURL; class GURL;
class Profile; class VisitedLinkDelegate;
namespace content {
class BrowserContext;
} // namespace content
// Controls the link coloring database. The master controls all writing to the // Controls the link coloring database. The master controls all writing to the
// database as well as disk I/O. There should be only one master. // database as well as disk I/O. There should be only one master.
...@@ -31,8 +37,7 @@ class Profile; ...@@ -31,8 +37,7 @@ class Profile;
// This class will defer writing operations to the file thread. This means that // This class will defer writing operations to the file thread. This means that
// class destruction, the file may still be open since operations are pending on // class destruction, the file may still be open since operations are pending on
// another thread. // another thread.
class VisitedLinkMaster : public VisitedLinkCommon, class VisitedLinkMaster : public VisitedLinkCommon {
public ProfileKeyedService {
public: public:
// Listens to the link coloring database events. The master is given this // Listens to the link coloring database events. The master is given this
// event as a constructor argument and dispatches events using it. // event as a constructor argument and dispatches events using it.
...@@ -53,7 +58,8 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -53,7 +58,8 @@ class VisitedLinkMaster : public VisitedLinkCommon,
virtual void Reset() = 0; virtual void Reset() = 0;
}; };
explicit VisitedLinkMaster(Profile* profile); VisitedLinkMaster(content::BrowserContext* browser_context,
VisitedLinkDelegate* delegate);
// In unit test mode, we allow the caller to optionally specify the database // In unit test mode, we allow the caller to optionally specify the database
// filename so that it can be run from a unit test. The directory where this // filename so that it can be run from a unit test. The directory where this
...@@ -71,15 +77,12 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -71,15 +77,12 @@ class VisitedLinkMaster : public VisitedLinkCommon,
// history if the file can't be loaded. This should generally be set for // history if the file can't be loaded. This should generally be set for
// testing except when you want to test the rebuild process explicitly. // testing except when you want to test the rebuild process explicitly.
VisitedLinkMaster(Listener* listener, VisitedLinkMaster(Listener* listener,
HistoryService* history_service, VisitedLinkDelegate* delegate,
bool suppress_rebuild, bool suppress_rebuild,
const FilePath& filename, const FilePath& filename,
int32 default_table_size); int32 default_table_size);
virtual ~VisitedLinkMaster(); virtual ~VisitedLinkMaster();
// Return the VisitedLinkMaster instance for a profile.
static VisitedLinkMaster* FromProfile(Profile* profile);
// Must be called immediately after object creation. Nothing else will work // Must be called immediately after object creation. Nothing else will work
// until this is called. Returns true on success, false means that this // until this is called. Returns true on success, false means that this
// object won't work. // object won't work.
...@@ -93,13 +96,31 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -93,13 +96,31 @@ class VisitedLinkMaster : public VisitedLinkCommon,
// Adds a set of URLs to the table. // Adds a set of URLs to the table.
void AddURLs(const std::vector<GURL>& url); void AddURLs(const std::vector<GURL>& url);
// See DeleteURLs.
class URLIterator {
public:
// HasNextURL must return true when this is called. Returns the next URL
// then advances the iterator. Note that the returned reference is only
// valid until the next call of NextURL.
virtual const GURL& NextURL() = 0;
// Returns true if still has URLs to be iterated.
virtual bool HasNextURL() const = 0;
protected:
virtual ~URLIterator() {}
};
// Deletes the specified URLs from |rows| from the table. // Deletes the specified URLs from |rows| from the table.
void DeleteURLs(const history::URLRows& rows); void DeleteURLs(URLIterator* iterator);
// Clears the visited links table by deleting the file from disk. Used as // Clears the visited links table by deleting the file from disk. Used as
// part of history clearing. // part of history clearing.
void DeleteAllURLs(); void DeleteAllURLs();
// Returns the Delegate of this Master.
VisitedLinkDelegate* GetDelegate();
#if defined(UNIT_TEST) || !defined(NDEBUG) || defined(PERF_TEST) #if defined(UNIT_TEST) || !defined(NDEBUG) || defined(PERF_TEST)
// This is a debugging function that can be called to double-check internal // This is a debugging function that can be called to double-check internal
// data structures. It will assert if the check fails. // data structures. It will assert if the check fails.
...@@ -289,7 +310,7 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -289,7 +310,7 @@ class VisitedLinkMaster : public VisitedLinkCommon,
// //
// Returns true on success. Failure means we're not attempting to rebuild // Returns true on success. Failure means we're not attempting to rebuild
// the database because something failed. // the database because something failed.
bool RebuildTableFromHistory(); bool RebuildTableFromDelegate();
// Callback that the table rebuilder uses when the rebuild is complete. // Callback that the table rebuilder uses when the rebuild is complete.
// |success| is true if the fingerprint generation succeeded, in which case // |success| is true if the fingerprint generation succeeded, in which case
...@@ -320,9 +341,13 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -320,9 +341,13 @@ class VisitedLinkMaster : public VisitedLinkCommon,
bool posted_asynchronous_operation_; bool posted_asynchronous_operation_;
#endif #endif
// Reference to the user profile that this object belongs to // Reference to the browser context that this object belongs to
// (it knows the path to where the data is stored) // (it knows the path to where the data is stored)
Profile* profile_; content::BrowserContext* browser_context_;
// Client owns the delegate and is responsible for it being valid through
// the life time this VisitedLinkMaster.
VisitedLinkDelegate* delegate_;
// VisitedLinkEventListener to handle incoming events. // VisitedLinkEventListener to handle incoming events.
scoped_ptr<Listener> listener_; scoped_ptr<Listener> listener_;
...@@ -380,10 +405,6 @@ class VisitedLinkMaster : public VisitedLinkCommon, ...@@ -380,10 +405,6 @@ class VisitedLinkMaster : public VisitedLinkCommon,
// When nonzero, overrides the table size for new databases for testing // When nonzero, overrides the table size for new databases for testing
int32 table_size_override_; int32 table_size_override_;
// When non-NULL, overrides the history service to use rather than as the
// BrowserProcess. This is provided for unit tests.
HistoryService* history_service_override_;
// When set, indicates the task that should be run after the next rebuild from // When set, indicates the task that should be run after the next rebuild from
// history is complete. // history is complete.
base::Closure rebuild_complete_task_; base::Closure rebuild_complete_task_;
......
// Copyright (c) 2012 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/visitedlink/visitedlink_master_factory.h"
#include "base/memory/singleton.h"
#include "chrome/browser/profiles/profile_dependency_manager.h"
#include "chrome/browser/visitedlink/visitedlink_master.h"
// static
VisitedLinkMaster* VisitedLinkMaster::FromProfile(Profile* profile) {
return VisitedLinkMasterFactory::GetForProfile(profile);
}
// static
VisitedLinkMaster* VisitedLinkMasterFactory::GetForProfile(Profile* profile) {
return static_cast<VisitedLinkMaster*>(
GetInstance()->GetServiceForProfile(profile, true));
}
// static
VisitedLinkMasterFactory* VisitedLinkMasterFactory::GetInstance() {
return Singleton<VisitedLinkMasterFactory>::get();
}
VisitedLinkMasterFactory::VisitedLinkMasterFactory()
: ProfileKeyedServiceFactory(
"VisitedLinkMaster", ProfileDependencyManager::GetInstance()) {
}
VisitedLinkMasterFactory::~VisitedLinkMasterFactory() {
}
ProfileKeyedService*
VisitedLinkMasterFactory::BuildServiceInstanceFor(Profile* profile) const {
VisitedLinkMaster* visitedlink_master(new VisitedLinkMaster(profile));
if (visitedlink_master->Init())
return visitedlink_master;
return NULL;
}
bool VisitedLinkMasterFactory::ServiceIsNULLWhileTesting() const {
return true;
}
// Copyright (c) 2012 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_VISITEDLINK_VISITEDLINK_MASTER_FACTORY_H_
#define CHROME_BROWSER_VISITEDLINK_VISITEDLINK_MASTER_FACTORY_H_
#include "base/memory/singleton.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
template <typename T> struct DefaultSingletonTraits;
class VisitedLinkMaster;
// Singleton that owns all VisitedLinkMaster and associates them with
// Profiles.
class VisitedLinkMasterFactory : public ProfileKeyedServiceFactory {
public:
static VisitedLinkMaster* GetForProfile(Profile* profile);
static VisitedLinkMasterFactory* GetInstance();
private:
friend struct DefaultSingletonTraits<VisitedLinkMasterFactory>;
VisitedLinkMasterFactory();
virtual ~VisitedLinkMasterFactory();
// ProfileKeyedServiceFactory:
virtual ProfileKeyedService* BuildServiceInstanceFor(
Profile* profile) const OVERRIDE;
virtual bool ServiceIsNULLWhileTesting() const OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(VisitedLinkMasterFactory);
};
#endif // CHROME_BROWSER_VISITEDLINK_VISITEDLINK_MASTER_FACTORY_H_
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/stringprintf.h" #include "base/stringprintf.h"
#include "base/test/test_file_util.h" #include "base/test/test_file_util.h"
#include "chrome/browser/visitedlink/visitedlink_master.h" #include "chrome/browser/visitedlink/visitedlink_master.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta; using base::TimeDelta;
......
...@@ -2165,12 +2165,11 @@ ...@@ -2165,12 +2165,11 @@
'browser/value_store/value_store.h', 'browser/value_store/value_store.h',
'browser/view_type_utils.cc', 'browser/view_type_utils.cc',
'browser/view_type_utils.h', 'browser/view_type_utils.h',
'browser/visitedlink/visitedlink_delegate.h',
'browser/visitedlink/visitedlink_event_listener.cc', 'browser/visitedlink/visitedlink_event_listener.cc',
'browser/visitedlink/visitedlink_event_listener.h', 'browser/visitedlink/visitedlink_event_listener.h',
'browser/visitedlink/visitedlink_master.cc', 'browser/visitedlink/visitedlink_master.cc',
'browser/visitedlink/visitedlink_master.h', 'browser/visitedlink/visitedlink_master.h',
'browser/visitedlink/visitedlink_master_factory.cc',
'browser/visitedlink/visitedlink_master_factory.h',
'browser/web_applications/web_app.cc', 'browser/web_applications/web_app.cc',
'browser/web_applications/web_app.h', 'browser/web_applications/web_app.h',
'browser/web_applications/web_app_android.cc', 'browser/web_applications/web_app_android.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment