Commit 368e5eb0 authored by tburkard@chromium.org's avatar tburkard@chromium.org

Add PrerenderLocalPredictor, which will eventually perform

local prerender predictions.  At this point, the class itself
is just a dummy, and the focus for now is on the interface with
the history service.  I added everything I need added in history,
and PrerenderLocalPredictor performs the basic interface functionality
it needs with the History.  In a later CL, I will actually add the
prerender semantics.
R=brettw@chromium.org, cbentzel@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10067018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133548 0039d316-1c4b-4281-b951-d872f2087c98
parent 6ea8820f
......@@ -40,6 +40,7 @@
#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/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
......@@ -127,6 +128,13 @@ class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
history_service_.get(), backend_id));
}
virtual void NotifyVisitDBObserversOnAddVisit(
const history::BriefVisitInfo& info) OVERRIDE {
// Since the notification method can be run on any thread, we can
// call it right away.
history_service_->NotifyVisitDBObserversOnAddVisit(info);
}
private:
scoped_refptr<HistoryService> history_service_;
MessageLoop* message_loop_;
......@@ -143,7 +151,9 @@ HistoryService::HistoryService()
current_backend_id_(-1),
bookmark_service_(NULL),
no_db_(false),
needs_top_sites_migration_(false) {
needs_top_sites_migration_(false),
visit_database_observers_(
new ObserverListThreadSafe<history::VisitDatabaseObserver>()) {
}
HistoryService::HistoryService(Profile* profile)
......@@ -153,7 +163,9 @@ HistoryService::HistoryService(Profile* profile)
current_backend_id_(-1),
bookmark_service_(NULL),
no_db_(false),
needs_top_sites_migration_(false) {
needs_top_sites_migration_(false),
visit_database_observers_(
new ObserverListThreadSafe<history::VisitDatabaseObserver>()) {
DCHECK(profile_);
registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::Source<Profile>(profile_));
......@@ -892,3 +904,19 @@ void HistoryService::OnTopSitesReady() {
ScheduleAndForget(PRIORITY_NORMAL,
&HistoryBackend::MigrateThumbnailsDatabase);
}
void HistoryService::AddVisitDatabaseObserver(
history::VisitDatabaseObserver* observer) {
visit_database_observers_->AddObserver(observer);
}
void HistoryService::RemoveVisitDatabaseObserver(
history::VisitDatabaseObserver* observer) {
visit_database_observers_->RemoveObserver(observer);
}
void HistoryService::NotifyVisitDBObserversOnAddVisit(
const history::BriefVisitInfo& info) {
visit_database_observers_->Notify(
&history::VisitDatabaseObserver::OnAddVisit, info);
}
......@@ -14,6 +14,7 @@
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/string16.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/favicon/favicon_service.h"
......@@ -54,6 +55,7 @@ struct HistoryDetails;
class HistoryQueryTest;
class VisitFilter;
class URLDatabase;
class VisitDatabaseObserver;
} // namespace history
......@@ -546,6 +548,14 @@ class HistoryService : public CancelableRequestProvider,
// db.
bool needs_top_sites_migration() const { return needs_top_sites_migration_; }
// Adds or removes observers for the VisitDatabase. Should be run in the
// thread in which the observer would like to be notified.
void AddVisitDatabaseObserver(history::VisitDatabaseObserver* observer);
void RemoveVisitDatabaseObserver(history::VisitDatabaseObserver* observer);
// This notification method may be called on any thread.
void NotifyVisitDBObserversOnAddVisit(const history::BriefVisitInfo& info);
// Testing -------------------------------------------------------------------
// Designed for unit tests, this passes the given task on to the history
......@@ -898,6 +908,9 @@ class HistoryService : public CancelableRequestProvider,
// The index used for quick history lookups.
scoped_ptr<history::InMemoryURLIndex> in_memory_url_index_;
scoped_refptr<ObserverListThreadSafe<history::VisitDatabaseObserver> >
visit_database_observers_;
DISALLOW_COPY_AND_ASSIGN(HistoryService);
};
......
......@@ -770,6 +770,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
// Add the visit with the time to the database.
VisitRow visit_info(url_id, time, referring_visit, transition, 0);
VisitID visit_id = db_->AddVisit(&visit_info, visit_source);
NotifyVisitObservers(visit_info);
if (visit_info.visit_time < first_recorded_time_)
first_recorded_time_ = visit_info.visit_time;
......@@ -863,6 +864,7 @@ void HistoryBackend::AddPagesWithDetails(const URLRows& urls,
NOTREACHED() << "Adding visit failed.";
return;
}
NotifyVisitObservers(visit_info);
if (visit_info.visit_time < first_recorded_time_)
first_recorded_time_ = visit_info.visit_time;
......@@ -2477,4 +2479,15 @@ bool HistoryBackend::GetFaviconFromDB(FaviconID favicon_id,
return true;
}
void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) {
BriefVisitInfo info;
info.url_id = visit.url_id;
info.time = visit.visit_time;
info.transition = visit.transition;
// If we don't have a delegate yet during setup or shutdown, we will drop
// these notifications.
if (delegate_.get())
delegate_->NotifyVisitDBObserversOnAddVisit(info);
}
} // namespace history
......@@ -91,6 +91,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Tell TopSites to start reading thumbnails from the ThumbnailsDB.
virtual void StartTopSitesMigration(int backend_id) = 0;
virtual void NotifyVisitDBObserversOnAddVisit(
const history::BriefVisitInfo& info) = 0;
};
// Init must be called to complete object creation. This object can be
......@@ -588,6 +591,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// and true if returned on success, otherwise false is returned.
bool GetFaviconFromDB(FaviconID favicon_id, FaviconData* favicon);
// Notify any observers of an addition to the visit database.
void NotifyVisitObservers(const VisitRow& visit);
// Data ----------------------------------------------------------------------
// Delegate. See the class definition above for more information. This will
......
......@@ -64,6 +64,8 @@ class HistoryBackendTestDelegate : public HistoryBackend::Delegate {
HistoryDetails* details) OVERRIDE;
virtual void DBLoaded(int backend_id) OVERRIDE;
virtual void StartTopSitesMigration(int backend_id) OVERRIDE;
virtual void NotifyVisitDBObserversOnAddVisit(
const BriefVisitInfo& info) OVERRIDE {}
private:
// Not owned by us.
......
......@@ -764,6 +764,20 @@ struct FaviconData {
history::IconType icon_type;
};
// Abbreviated information about a visit.
struct BriefVisitInfo {
URLID url_id;
base::Time time;
content::PageTransition transition;
};
// An observer of VisitDatabase.
class VisitDatabaseObserver {
public:
virtual ~VisitDatabaseObserver() {}
virtual void OnAddVisit(const BriefVisitInfo& info) = 0;
};
} // namespace history
#endif // CHROME_BROWSER_HISTORY_HISTORY_TYPES_H_
......@@ -94,6 +94,8 @@ class BackendDelegate : public HistoryBackend::Delegate {
HistoryDetails* details) OVERRIDE;
virtual void DBLoaded(int backend_id) OVERRIDE {}
virtual void StartTopSitesMigration(int backend_id) OVERRIDE {}
virtual void NotifyVisitDBObserversOnAddVisit(
const BriefVisitInfo& info) OVERRIDE {}
private:
HistoryTest* history_test_;
};
......
......@@ -558,4 +558,27 @@ bool VisitDatabase::MigrateVisitsWithoutDuration() {
return true;
}
void VisitDatabase::GetBriefVisitInfoOfMostRecentVisits(
int max_visits,
std::vector<BriefVisitInfo>* result_vector) {
result_vector->clear();
sql::Statement statement(GetDB().GetUniqueStatement(
"SELECT url,visit_time,transition FROM visits "
"ORDER BY id DESC LIMIT ?"));
statement.BindInt64(0, max_visits);
if (!statement.is_valid())
return;
while (statement.Step()) {
BriefVisitInfo info;
info.url_id = statement.ColumnInt64(0);
info.time = base::Time::FromInternalValue(statement.ColumnInt64(1));
info.transition = content::PageTransitionFromInt(statement.ColumnInt(2));
result_vector->push_back(info);
}
}
} // namespace history
......@@ -172,6 +172,12 @@ class VisitDatabase {
void GetVisitsSource(const VisitVector& visits,
VisitSourceMap* sources);
// Obtains BriefVisitInfo for the specified number of most recent visits
// from the visit database.
void GetBriefVisitInfoOfMostRecentVisits(
int max_visits,
std::vector<BriefVisitInfo>* result_vector);
protected:
// Returns the database for the functions in this interface.
virtual sql::Connection& GetDB() = 0;
......
// 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/prerender/prerender_local_predictor.h"
#include "base/timer.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_database.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace prerender {
namespace {
// Task to lookup the URL for a given URLID.
class GetURLForURLIDTask : public HistoryDBTask {
public:
GetURLForURLIDTask(PrerenderLocalPredictor* local_predictor,
history::URLID url_id)
: local_predictor_(local_predictor),
url_id_(url_id),
success_(false) {
}
virtual bool RunOnDBThread(history::HistoryBackend* backend,
history::HistoryDatabase* db) {
history::URLRow url_row;
success_ = db->GetURLRow(url_id_, &url_row);
if (success_)
url_ = url_row.url();
return true;
}
virtual void DoneRunOnMainThread() {
if (success_)
local_predictor_->OnLookupURL(url_id_, url_);
}
private:
PrerenderLocalPredictor* local_predictor_;
history::URLID url_id_;
bool success_;
GURL url_;
DISALLOW_COPY_AND_ASSIGN(GetURLForURLIDTask);
};
// Task to load history from the visit database on startup.
class GetVisitHistoryTask : public HistoryDBTask {
public:
GetVisitHistoryTask(PrerenderLocalPredictor* local_predictor,
int max_visits)
: local_predictor_(local_predictor),
max_visits_(max_visits),
visit_history_(new std::vector<history::BriefVisitInfo>) {
}
virtual bool RunOnDBThread(history::HistoryBackend* backend,
history::HistoryDatabase* db) {
db->GetBriefVisitInfoOfMostRecentVisits(max_visits_, visit_history_.get());
return true;
}
virtual void DoneRunOnMainThread() {
local_predictor_->OnGetInitialVisitHistory(visit_history_.Pass());
}
private:
PrerenderLocalPredictor* local_predictor_;
int max_visits_;
scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history_;
DISALLOW_COPY_AND_ASSIGN(GetVisitHistoryTask);
};
// Maximum visit history to retrieve from the visit database.
const int kMaxVisitHistory = 100 * 1000;
} // namespace
PrerenderLocalPredictor::PrerenderLocalPredictor(
PrerenderManager* prerender_manager)
: prerender_manager_(prerender_manager),
visit_history_initialized_(false) {
if (MessageLoop::current()) {
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kInitDelayMs),
this,
&PrerenderLocalPredictor::Init);
}
}
PrerenderLocalPredictor::~PrerenderLocalPredictor() {
HistoryService* history = GetHistoryIfExists();
if (history)
history->RemoveVisitDatabaseObserver(this);
}
void PrerenderLocalPredictor::OnAddVisit(const history::BriefVisitInfo& info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
HistoryService* history = GetHistoryIfExists();
if (history) {
history->ScheduleDBTask(
new GetURLForURLIDTask(this, info.url_id),
&history_db_consumer_);
}
}
void PrerenderLocalPredictor::OnLookupURL(history::URLID url_id,
const GURL& url) {
}
void PrerenderLocalPredictor::OnGetInitialVisitHistory(
scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!visit_history_initialized_);
visit_history_.reset(visit_history.release());
visit_history_initialized_ = true;
}
HistoryService* PrerenderLocalPredictor::GetHistoryIfExists() const {
Profile* profile = prerender_manager_->profile();
if (!profile)
return NULL;
return profile->GetHistoryServiceWithoutCreating();
}
void PrerenderLocalPredictor::Init() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
HistoryService* history = GetHistoryIfExists();
if (!history) {
// TODO(tburkard): Record this somewhere (eg histogram) and/or try again
// later.
return;
}
history->ScheduleDBTask(
new GetVisitHistoryTask(this, kMaxVisitHistory),
&history_db_consumer_);
history->AddVisitDatabaseObserver(this);
}
} // namespace prerender
// 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_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
#pragma once
#include <vector>
#include "base/timer.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/history/visit_database.h"
#include "googleurl/src/gurl.h"
class HistoryService;
namespace prerender {
class PrerenderManager;
// PrerenderLocalPredictor maintains local browsing history to make prerender
// predictions.
// At this point, the class is just illustrating the interface with the
// Chrome History.
// TODO(tburkard): Fill in actual prerender prediction logic.
class PrerenderLocalPredictor : history::VisitDatabaseObserver {
public:
// A PrerenderLocalPredictor is owned by the PrerenderManager specified
// in the constructor. It will be destoryed at the time its owning
// PrerenderManager is destroyed.
explicit PrerenderLocalPredictor(PrerenderManager* prerender_manager);
virtual ~PrerenderLocalPredictor();
// history::VisitDatabaseObserver implementation
virtual void OnAddVisit(const history::BriefVisitInfo& info) OVERRIDE;
void OnLookupURL(history::URLID url_id, const GURL& url);
void OnGetInitialVisitHistory(
scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history);
private:
HistoryService* GetHistoryIfExists() const;
void Init();
PrerenderManager* prerender_manager_;
base::OneShotTimer<PrerenderLocalPredictor> timer_;
// Delay after which to initialize, to avoid putting to much load on the
// database thread early on when Chrome is starting up.
static const int kInitDelayMs = 5 * 1000;
CancelableRequestConsumer history_db_consumer_;
scoped_ptr<std::vector<history::BriefVisitInfo> > visit_history_;
bool visit_history_initialized_;
DISALLOW_COPY_AND_ASSIGN(PrerenderLocalPredictor);
};
} // namespace prerender
#endif // CHROME_BROWSER_PRERENDER_PRERENDER_LOCAL_PREDICTOR_H_
......@@ -25,6 +25,7 @@
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_histograms.h"
#include "chrome/browser/prerender/prerender_history.h"
#include "chrome/browser/prerender/prerender_local_predictor.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/prerender/prerender_tab_helper.h"
#include "chrome/browser/prerender/prerender_tracker.h"
......@@ -254,7 +255,8 @@ PrerenderManager::PrerenderManager(Profile* profile,
base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)),
weak_factory_(this),
prerender_history_(new PrerenderHistory(kHistoryLength)),
histograms_(new PrerenderHistograms()) {
histograms_(new PrerenderHistograms()),
local_predictor_(new PrerenderLocalPredictor(this)) {
// There are some assumptions that the PrerenderManager is on the UI thread.
// Any other checks simply make sure that the PrerenderManager is accessed on
// the same thread that it was created on.
......
......@@ -52,6 +52,7 @@ namespace prerender {
class PrerenderCondition;
class PrerenderHistograms;
class PrerenderHistory;
class PrerenderLocalPredictor;
class PrerenderTracker;
// PrerenderManager is responsible for initiating and keeping prerendered
......@@ -234,6 +235,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
// provided URL.
void RecordNavigation(const GURL& url);
Profile* profile() const { return profile_; }
protected:
void SetPrerenderContentsFactory(
PrerenderContents::Factory* prerender_contents_factory);
......@@ -453,6 +456,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
scoped_ptr<PrerenderHistograms> histograms_;
scoped_ptr<PrerenderLocalPredictor> local_predictor_;
scoped_ptr<MostVisitedSites> most_visited_;
DISALLOW_COPY_AND_ASSIGN(PrerenderManager);
......
......@@ -1656,6 +1656,8 @@
'browser/prerender/prerender_histograms.h',
'browser/prerender/prerender_history.cc',
'browser/prerender/prerender_history.h',
'browser/prerender/prerender_local_predictor.cc',
'browser/prerender/prerender_local_predictor.h',
'browser/prerender/prerender_manager.cc',
'browser/prerender/prerender_manager.h',
'browser/prerender/prerender_manager_factory.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