| Index: components/precache/core/precache_database.cc
|
| diff --git a/components/precache/core/precache_database.cc b/components/precache/core/precache_database.cc
|
| index e6853fa2eea9d6731033f953b5c4f770f260ed2b..ab6d727b4d4a946923224a70b09c6776d8987246 100644
|
| --- a/components/precache/core/precache_database.cc
|
| +++ b/components/precache/core/precache_database.cc
|
| @@ -58,6 +58,7 @@ bool PrecacheDatabase::Init(const base::FilePath& db_path) {
|
| }
|
|
|
| if (!precache_url_table_.Init(db_.get()) ||
|
| + !precache_referrer_host_table_.Init(db_.get()) ||
|
| !precache_session_table_.Init(db_.get())) {
|
| // Raze and close the database connection to indicate that it's not usable,
|
| // and so that the database will be created anew next time, in case it's
|
| @@ -81,6 +82,9 @@ void PrecacheDatabase::DeleteExpiredPrecacheHistory(
|
| buffered_writes_.push_back(
|
| base::Bind(&PrecacheURLTable::DeleteAllPrecachedBefore,
|
| base::Unretained(&precache_url_table_), delete_end));
|
| + buffered_writes_.push_back(
|
| + base::Bind(&PrecacheReferrerHostTable::DeleteAllEntriesBefore,
|
| + base::Unretained(&precache_referrer_host_table_), delete_end));
|
| Flush();
|
| }
|
|
|
| @@ -92,6 +96,9 @@ void PrecacheDatabase::ClearHistory() {
|
|
|
| buffered_writes_.push_back(base::Bind(
|
| &PrecacheURLTable::DeleteAll, base::Unretained(&precache_url_table_)));
|
| + buffered_writes_.push_back(
|
| + base::Bind(&PrecacheReferrerHostTable::DeleteAll,
|
| + base::Unretained(&precache_referrer_host_table_)));
|
| Flush();
|
| }
|
|
|
| @@ -117,23 +124,27 @@ base::Time PrecacheDatabase::GetLastPrecacheTimestamp() {
|
| return last_precache_timestamp_;
|
| }
|
|
|
| -void PrecacheDatabase::RecordURLPrefetch(const GURL& url,
|
| - const base::TimeDelta& latency,
|
| - const base::Time& fetch_time,
|
| - const net::HttpResponseInfo& info,
|
| - int64_t size) {
|
| - UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency);
|
| +PrecacheReferrerHostEntry PrecacheDatabase::GetReferrerHost(
|
| + const std::string& referrer_host) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return precache_referrer_host_table_.GetReferrerHost(referrer_host);
|
| +}
|
|
|
| - if (!IsDatabaseAccessible()) {
|
| - // Don't track anything if unable to access the database.
|
| - return;
|
| - }
|
| +void PrecacheDatabase::GetURLListForReferrerHost(
|
| + int64_t referrer_host_id,
|
| + std::deque<GURL>& used_urls,
|
| + std::deque<GURL>& unused_urls) {
|
| + DCHECK_NE(PrecacheReferrerHostEntry::INVALID_ID, referrer_host_id);
|
| + precache_url_table_.GetURLListForReferrerHost(referrer_host_id, used_urls,
|
| + unused_urls);
|
| +}
|
|
|
| - if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
|
| - // If the URL for this fetch is in the write buffer, then flush the write
|
| - // buffer.
|
| - Flush();
|
| - }
|
| +void PrecacheDatabase::RecordURLPrefetchMetrics(
|
| + const net::HttpResponseInfo& info,
|
| + const base::TimeDelta& latency) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + UMA_HISTOGRAM_TIMES("Precache.Latency.Prefetch", latency);
|
|
|
| DCHECK(info.headers) << "The headers are required to get the freshness.";
|
| if (info.headers) {
|
| @@ -145,33 +156,64 @@ void PrecacheDatabase::RecordURLPrefetch(const GURL& url,
|
| base::TimeDelta::FromDays(356).InSeconds() /* max */,
|
| 100 /* bucket_count */);
|
| }
|
| +}
|
|
|
| - if (info.was_cached && !precache_url_table_.HasURL(url)) {
|
| - // Since the precache came from the cache, and there's no entry in the URL
|
| - // table for the URL, this means that the resource was already in the cache
|
| - // because of user browsing. Therefore, this precache won't be considered as
|
| - // precache-motivated since it had no significant effect (besides a possible
|
| - // revalidation and a change in the cache LRU priority).
|
| +void PrecacheDatabase::RecordURLPrefetch(const GURL& url,
|
| + const std::string& referrer_host,
|
| + const base::Time& fetch_time,
|
| + bool was_cached,
|
| + int64_t size) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!IsDatabaseAccessible()) {
|
| + // Don't track anything if unable to access the database.
|
| return;
|
| }
|
|
|
| - if (!info.was_cached) {
|
| + if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
|
| + // If the URL for this fetch is in the write buffer, then flush the write
|
| + // buffer.
|
| + Flush();
|
| + }
|
| +
|
| + if (!was_cached) {
|
| // The precache only counts as overhead if it was downloaded over the
|
| // network.
|
| UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated",
|
| static_cast<base::HistogramBase::Sample>(size));
|
| }
|
|
|
| - // Use the URL table to keep track of URLs that are in the cache thanks to
|
| - // precaching. If a row for the URL already exists, than update the timestamp
|
| - // to |fetch_time|.
|
| - buffered_writes_.push_back(
|
| - base::Bind(&PrecacheURLTable::AddURL,
|
| - base::Unretained(&precache_url_table_), url, fetch_time));
|
| + // Use the URL table to keep track of URLs. URLs that are fetched via network
|
| + // or already in the cache due to prior precaching are recorded as
|
| + // precache-motivated. URLs that came from the cache and not recorded as
|
| + // precached previously, were already in the cache because of user browsing.
|
| + // Therefore, this precache will not be considered as precache-motivated,
|
| + // since it had no significant effect (besides a possible revalidation and a
|
| + // change in the cache LRU priority). If a row for the URL already exists,
|
| + // then the timestamp is updated.
|
| + buffered_writes_.push_back(base::Bind(
|
| + &PrecacheDatabase::RecordURLPrefetchInternal, GetWeakPtr(), url,
|
| + referrer_host, !was_cached || precache_url_table_.IsURLPrecached(url),
|
| + fetch_time));
|
| buffered_urls_.insert(url.spec());
|
| MaybePostFlush();
|
| }
|
|
|
| +void PrecacheDatabase::RecordURLPrefetchInternal(
|
| + const GURL& url,
|
| + const std::string& referrer_host,
|
| + bool is_precached,
|
| + const base::Time& fetch_time) {
|
| + auto referrer_host_id =
|
| + precache_referrer_host_table_.GetReferrerHost(referrer_host).id;
|
| + if (referrer_host_id == PrecacheReferrerHostEntry::INVALID_ID) {
|
| + referrer_host_id = precache_referrer_host_table_.UpdateReferrerHost(
|
| + referrer_host, 0, fetch_time);
|
| + DCHECK_NE(referrer_host_id, PrecacheReferrerHostEntry::INVALID_ID);
|
| + }
|
| + precache_url_table_.AddURL(url, referrer_host_id, is_precached, fetch_time);
|
| +}
|
| +
|
| void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url,
|
| const base::TimeDelta& latency,
|
| const base::Time& fetch_time,
|
| @@ -207,7 +249,8 @@ void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url,
|
| Flush();
|
| }
|
|
|
| - if (info.was_cached && !precache_url_table_.HasURL(url)) {
|
| + bool is_precached = precache_url_table_.IsURLPrecachedAndUnused(url);
|
| + if (info.was_cached && !is_precached) {
|
| // Ignore cache hits that precache can't take credit for.
|
| return;
|
| }
|
| @@ -245,18 +288,44 @@ void PrecacheDatabase::RecordURLNonPrefetch(const GURL& url,
|
| }
|
| }
|
|
|
| - // Since the resource has been fetched during user browsing, remove any record
|
| - // of that URL having been precached from the URL table, if any exists.
|
| - // The current fetch would have put this resource in the cache regardless of
|
| - // whether or not it was previously precached, so delete any record of that
|
| - // URL having been precached from the URL table.
|
| + if (is_precached) {
|
| + // Since the resource has been fetched during user browsing, mark the URL as
|
| + // used in the precache URL table, if any exists. The current fetch would
|
| + // have put this resource in the cache regardless of whether or not it was
|
| + // previously precached, so mark the URL as used.
|
| + buffered_writes_.push_back(
|
| + base::Bind(&PrecacheURLTable::SetPrecachedURLAsUsed,
|
| + base::Unretained(&precache_url_table_), url));
|
| + buffered_urls_.insert(url.spec());
|
| + MaybePostFlush();
|
| + }
|
| +}
|
| +
|
| +void PrecacheDatabase::UpdatePrecacheReferrerHost(
|
| + const std::string& hostname,
|
| + int64_t manifest_id,
|
| + const base::Time& fetch_time) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!IsDatabaseAccessible()) {
|
| + // Don't track anything if unable to access the database.
|
| + return;
|
| + }
|
| +
|
| buffered_writes_.push_back(
|
| - base::Bind(&PrecacheURLTable::DeleteURL,
|
| - base::Unretained(&precache_url_table_), url));
|
| - buffered_urls_.insert(url.spec());
|
| + base::Bind(&PrecacheDatabase::UpdatePrecacheReferrerHostInternal,
|
| + GetWeakPtr(), hostname, manifest_id, fetch_time));
|
| MaybePostFlush();
|
| }
|
|
|
| +void PrecacheDatabase::UpdatePrecacheReferrerHostInternal(
|
| + const std::string& hostname,
|
| + int64_t manifest_id,
|
| + const base::Time& fetch_time) {
|
| + precache_referrer_host_table_.UpdateReferrerHost(hostname, manifest_id,
|
| + fetch_time);
|
| +}
|
| +
|
| void PrecacheDatabase::RecordTimeSinceLastPrecache(
|
| const base::Time& fetch_time) {
|
| const base::Time& last_precache_timestamp = GetLastPrecacheTimestamp();
|
|
|