diff options
-rw-r--r-- | chrome/browser/history/history.cc | 8 | ||||
-rw-r--r-- | chrome/browser/history/history.h | 6 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.cc | 49 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.h | 14 | ||||
-rw-r--r-- | chrome/browser/history/history_notifications.h | 6 | ||||
-rw-r--r-- | chrome/browser/history/visit_database.cc | 27 | ||||
-rw-r--r-- | chrome/browser/history/visit_database.h | 6 |
7 files changed, 115 insertions, 1 deletions
diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc index 220f3cc..01d3e35 100644 --- a/chrome/browser/history/history.cc +++ b/chrome/browser/history/history.cc @@ -516,6 +516,14 @@ HistoryService::Handle HistoryService::QueryRedirectsFrom( new history::QueryRedirectsRequest(callback), from_url); } +HistoryService::Handle HistoryService::QueryRedirectsTo( + const GURL& to_url, + CancelableRequestConsumerBase* consumer, + QueryRedirectsCallback* callback) { + return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryRedirectsTo, consumer, + new history::QueryRedirectsRequest(callback), to_url); +} + HistoryService::Handle HistoryService::GetVisitCountToHost( const GURL& url, CancelableRequestConsumerBase* consumer, diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h index 2b480a7..8ca8878 100644 --- a/chrome/browser/history/history.h +++ b/chrome/browser/history/history.h @@ -280,6 +280,12 @@ class HistoryService : public CancelableRequestProvider, CancelableRequestConsumerBase* consumer, QueryRedirectsCallback* callback); + // Schedules a query to get the most recent redirects ending at the given + // URL. + Handle QueryRedirectsTo(const GURL& to_url, + CancelableRequestConsumerBase* consumer, + QueryRedirectsCallback* callback); + typedef Callback4<Handle, bool, // Were we able to determine the # of visits? int, // Number of visits. diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 691f24a..3200355 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -648,6 +648,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( URLVisitedDetails* details = new URLVisitedDetails; details->transition = transition; details->row = url_info; + GetMostRecentRedirectsTo(url, &details->redirects); BroadcastNotifications(NotificationType::HISTORY_URL_VISITED, details); } @@ -1127,6 +1128,16 @@ void HistoryBackend::QueryRedirectsFrom( request->handle(), url, success, &request->value)); } +void HistoryBackend::QueryRedirectsTo( + scoped_refptr<QueryRedirectsRequest> request, + const GURL& url) { + if (request->canceled()) + return; + bool success = GetMostRecentRedirectsTo(url, &request->value); + request->ForwardResult(QueryRedirectsRequest::TupleType( + request->handle(), url, success, &request->value)); +} + void HistoryBackend::GetVisitCountToHost( scoped_refptr<GetVisitCountToHostRequest> request, const GURL& url) { @@ -1158,6 +1169,28 @@ void HistoryBackend::GetRedirectsFromSpecificVisit( } } +void HistoryBackend::GetRedirectsToSpecificVisit( + VisitID cur_visit, + HistoryService::RedirectList* redirects) { + // Follow redirects going to cur_visit. These are added to |redirects| in + // the order they are found. If a redirect chain looks like A -> B -> C and + // |cur_visit| = C, redirects will be {B, A} in that order. + if (!db_.get()) + return; + + GURL cur_url; + std::set<VisitID> visit_set; + visit_set.insert(cur_visit); + while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { + if (visit_set.find(cur_visit) != visit_set.end()) { + NOTREACHED() << "Loop in visit chain, giving up"; + return; + } + visit_set.insert(cur_visit); + redirects->push_back(cur_url); + } +} + bool HistoryBackend::GetMostRecentRedirectsFrom( const GURL& from_url, HistoryService::RedirectList* redirects) { @@ -1174,6 +1207,22 @@ bool HistoryBackend::GetMostRecentRedirectsFrom( return true; } +bool HistoryBackend::GetMostRecentRedirectsTo( + const GURL& to_url, + HistoryService::RedirectList* redirects) { + redirects->clear(); + if (!db_.get()) + return false; + + URLID to_url_id = db_->GetRowForURL(to_url, NULL); + VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); + if (!cur_visit) + return false; // No visits for URL. + + GetRedirectsToSpecificVisit(cur_visit, redirects); + return true; +} + void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, HistoryURLProviderParams* params) { // ExecuteWithDB should handle the NULL database case. diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index 1e08bab..421e0a0 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h @@ -142,6 +142,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, const QueryOptions& options); void QueryRedirectsFrom(scoped_refptr<QueryRedirectsRequest> request, const GURL& url); + void QueryRedirectsTo(scoped_refptr<QueryRedirectsRequest> request, + const GURL& url); void GetVisitCountToHost(scoped_refptr<GetVisitCountToHostRequest> request, const GURL& url); @@ -155,6 +157,13 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, bool GetMostRecentRedirectsFrom(const GURL& url, HistoryService::RedirectList* redirects); + // Similar to above function except computes a chain of redirects to the + // given URL. Stores the most recent list of redirects ending at |url| in the + // given RedirectList. For example, if we have the redirect list A -> B -> C, + // then calling this function with url=C would fill redirects with {B, A}. + bool GetMostRecentRedirectsTo(const GURL& url, + HistoryService::RedirectList* redirects); + // Thumbnails ---------------------------------------------------------------- void SetPageThumbnail(const GURL& url, @@ -298,6 +307,11 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, void GetRedirectsFromSpecificVisit( VisitID cur_visit, HistoryService::RedirectList* redirects); + // Similar to the above function except returns a redirect list ending + // at |cur_visit|. + void GetRedirectsToSpecificVisit( + VisitID cur_visit, HistoryService::RedirectList* redirects); + // Thumbnail Helpers --------------------------------------------------------- // When a simple GetMostRecentRedirectsFrom() fails, this method is diff --git a/chrome/browser/history/history_notifications.h b/chrome/browser/history/history_notifications.h index 4eb9289..1281f2f4 100644 --- a/chrome/browser/history/history_notifications.h +++ b/chrome/browser/history/history_notifications.h @@ -27,6 +27,12 @@ struct HistoryDetails { struct URLVisitedDetails : public HistoryDetails { PageTransition::Type transition; URLRow row; + + // A list of redirects leading up to the URL represented by this struct. If + // we have the redirect chain A -> B -> C and this struct represents visiting + // C, then redirects[0]=B and redirects[1]=A. If there are no redirects, + // this will be an empty vector. + std::vector<GURL> redirects; }; // Details for NOTIFY_HISTORY_TYPED_URLS_MODIFIED. diff --git a/chrome/browser/history/visit_database.cc b/chrome/browser/history/visit_database.cc index c118bf2..7ce3e62 100644 --- a/chrome/browser/history/visit_database.cc +++ b/chrome/browser/history/visit_database.cc @@ -327,6 +327,31 @@ bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, return true; } +bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, + VisitID* from_visit, + GURL* from_url) { + VisitRow row; + if (!GetRowForVisit(to_visit, &row)) + return false; + + if (from_visit) + *from_visit = row.referring_visit; + + if (from_url) { + SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), + "SELECT u.url " + "FROM visits v JOIN urls u ON v.url = u.id " + "WHERE v.id = ?"); + statement->bind_int64(0, row.referring_visit); + + if (statement->step() != SQLITE_ROW) + return false; + + *from_url = GURL(statement->column_string(0)); + } + return true; +} + bool VisitDatabase::GetVisitCountToHost(const GURL& url, int* count, Time* first_visit) { @@ -373,7 +398,7 @@ bool VisitDatabase::GetVisitCountToHost(const GURL& url, bool VisitDatabase::GetStartDate(Time* first_visit) { SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0"); - if (!statement.is_valid() || statement->step() != SQLITE_ROW || + if (!statement.is_valid() || statement->step() != SQLITE_ROW || statement->column_int64(0) == 0) { *first_visit = Time::Now(); return false; diff --git a/chrome/browser/history/visit_database.h b/chrome/browser/history/visit_database.h index 0b2549e..2f73f90 100644 --- a/chrome/browser/history/visit_database.h +++ b/chrome/browser/history/visit_database.h @@ -111,6 +111,12 @@ class VisitDatabase { VisitID* to_visit, GURL* to_url); + // Similar to the above function except finds a redirect going to a given + // |to_visit|. + bool GetRedirectToVisit(VisitID to_visit, + VisitID* from_visit, + GURL* from_url); + // Returns the number of visits to all urls on the scheme/host/post // identified by url. This is only valid for http and https urls (all other // schemes are ignored and false is returned). |