This source file includes following definitions.
- Init
- DeleteExpiredPrecacheHistory
- RecordURLPrecached
- RecordURLFetched
- IsDatabaseAccessible
- Flush
- PostedFlush
- MaybePostFlush
#include "components/precache/core/precache_database.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "sql/connection.h"
#include "sql/transaction.h"
#include "url/gurl.h"
namespace {
const int kPrecacheHistoryExpiryPeriodDays = 60;
}
namespace precache {
PrecacheDatabase::PrecacheDatabase() : is_flush_posted_(false) {
thread_checker_.DetachFromThread();
}
PrecacheDatabase::~PrecacheDatabase() {
thread_checker_.DetachFromThread();
}
bool PrecacheDatabase::Init(const base::FilePath& db_path) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!db_);
db_.reset(new sql::Connection());
db_->set_histogram_tag("Precache");
if (!db_->Open(db_path)) {
return false;
}
if (!precache_url_table_.Init(db_.get())) {
db_->RazeAndClose();
return false;
}
return true;
}
void PrecacheDatabase::DeleteExpiredPrecacheHistory(
const base::Time& current_time) {
if (!IsDatabaseAccessible()) {
return;
}
base::Time delete_end = current_time - base::TimeDelta::FromDays(
kPrecacheHistoryExpiryPeriodDays);
buffered_writes_.push_back(
base::Bind(&PrecacheURLTable::DeleteAllPrecachedBefore,
base::Unretained(&precache_url_table_), delete_end));
Flush();
}
void PrecacheDatabase::RecordURLPrecached(const GURL& url,
const base::Time& fetch_time,
int64 size, bool was_cached) {
if (!IsDatabaseAccessible()) {
return;
}
if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
Flush();
}
if (was_cached && !precache_url_table_.HasURL(url)) {
return;
}
if (!was_cached) {
UMA_HISTOGRAM_COUNTS("Precache.DownloadedPrecacheMotivated", size);
}
buffered_writes_.push_back(
base::Bind(&PrecacheURLTable::AddURL,
base::Unretained(&precache_url_table_), url, fetch_time));
buffered_urls_.insert(url.spec());
MaybePostFlush();
}
void PrecacheDatabase::RecordURLFetched(const GURL& url,
const base::Time& fetch_time,
int64 size, bool was_cached,
bool is_connection_cellular) {
if (!IsDatabaseAccessible()) {
return;
}
if (buffered_urls_.find(url.spec()) != buffered_urls_.end()) {
Flush();
}
if (was_cached && !precache_url_table_.HasURL(url)) {
return;
}
if (!was_cached) {
UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache", size);
if (is_connection_cellular) {
UMA_HISTOGRAM_COUNTS("Precache.DownloadedNonPrecache.Cellular", size);
}
} else {
UMA_HISTOGRAM_COUNTS("Precache.Saved", size);
if (is_connection_cellular) {
UMA_HISTOGRAM_COUNTS("Precache.Saved.Cellular", size);
}
}
buffered_writes_.push_back(
base::Bind(&PrecacheURLTable::DeleteURL,
base::Unretained(&precache_url_table_), url));
buffered_urls_.insert(url.spec());
MaybePostFlush();
}
bool PrecacheDatabase::IsDatabaseAccessible() const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(db_);
return db_->is_open();
}
void PrecacheDatabase::Flush() {
DCHECK(thread_checker_.CalledOnValidThread());
if (buffered_writes_.empty()) {
DCHECK(buffered_urls_.empty());
return;
}
if (IsDatabaseAccessible()) {
sql::Transaction transaction(db_.get());
if (transaction.Begin()) {
for (std::vector<base::Closure>::const_iterator it =
buffered_writes_.begin();
it != buffered_writes_.end(); ++it) {
it->Run();
}
transaction.Commit();
}
}
buffered_writes_.clear();
buffered_urls_.clear();
}
void PrecacheDatabase::PostedFlush() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(is_flush_posted_);
is_flush_posted_ = false;
Flush();
}
void PrecacheDatabase::MaybePostFlush() {
DCHECK(thread_checker_.CalledOnValidThread());
if (buffered_writes_.empty() || is_flush_posted_) {
return;
}
DCHECK(base::MessageLoop::current());
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(&PrecacheDatabase::PostedFlush,
scoped_refptr<PrecacheDatabase>(this)),
base::TimeDelta::FromSeconds(1));
is_flush_posted_ = true;
}
}