blob: 44afd45ff91210d678eeee75fd17fcbeb9b09724 [file] [log] [blame]
// Copyright 2015 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 "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include <utility>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
#include "components/data_reduction_proxy/core/browser/data_store.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/proto/data_store.pb.h"
#include "components/prefs/pref_service.h"
namespace data_reduction_proxy {
DataReductionProxyService::DataReductionProxyService(
DataReductionProxySettings* settings,
PrefService* prefs,
net::URLRequestContextGetter* request_context_getter,
std::unique_ptr<DataStore> store,
std::unique_ptr<DataReductionProxyPingbackClient> pingback_client,
network::NetworkQualityTracker* network_quality_tracker,
const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
const base::TimeDelta& commit_delay)
: url_request_context_getter_(request_context_getter),
pingback_client_(std::move(pingback_client)),
settings_(settings),
prefs_(prefs),
db_data_owner_(new DBDataOwner(std::move(store))),
io_task_runner_(io_task_runner),
db_task_runner_(db_task_runner),
initialized_(false),
network_quality_tracker_(network_quality_tracker),
effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
weak_factory_(this) {
DCHECK(settings);
DCHECK(network_quality_tracker_);
db_task_runner_->PostTask(FROM_HERE,
base::BindOnce(&DBDataOwner::InitializeOnDBThread,
db_data_owner_->GetWeakPtr()));
if (prefs_) {
compression_stats_.reset(
new DataReductionProxyCompressionStats(this, prefs_, commit_delay));
}
event_store_.reset(new DataReductionProxyEventStore());
network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
network_quality_tracker_->AddRTTAndThroughputEstimatesObserver(this);
}
DataReductionProxyService::~DataReductionProxyService() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
network_quality_tracker_->RemoveEffectiveConnectionTypeObserver(this);
network_quality_tracker_->RemoveRTTAndThroughputEstimatesObserver(this);
compression_stats_.reset();
db_task_runner_->DeleteSoon(FROM_HERE, db_data_owner_.release());
}
void DataReductionProxyService::SetIOData(
base::WeakPtr<DataReductionProxyIOData> io_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
io_data_ = io_data;
initialized_ = true;
// Notify IO data of the current network quality estimates.
OnEffectiveConnectionTypeChanged(effective_connection_type_);
if (http_rtt_) {
OnRTTOrThroughputEstimatesComputed(http_rtt_.value(), base::TimeDelta(),
INT32_MAX);
}
for (DataReductionProxyServiceObserver& observer : observer_list_)
observer.OnServiceInitialized();
ReadPersistedClientConfig();
}
void DataReductionProxyService::ReadPersistedClientConfig() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!prefs_)
return;
base::Time last_config_retrieval_time =
base::Time() + base::TimeDelta::FromMicroseconds(prefs_->GetInt64(
prefs::kDataReductionProxyLastConfigRetrievalTime));
base::TimeDelta time_since_last_config_retrieval =
base::Time::Now() - last_config_retrieval_time;
// A config older than 24 hours should not be used.
bool persisted_config_is_expired =
GetFieldTrialParamByFeatureAsBool(
features::kDataReductionProxyRobustConnection,
"use_24h_config_expiration_time", true) &&
!last_config_retrieval_time.is_null() &&
time_since_last_config_retrieval > base::TimeDelta::FromHours(24);
if (persisted_config_is_expired)
return;
const std::string config_value =
prefs_->GetString(prefs::kDataReductionProxyConfig);
if (config_value.empty())
return;
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DataReductionProxyIOData::SetDataReductionProxyConfiguration,
io_data_, config_value));
}
void DataReductionProxyService::OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
effective_connection_type_ = type;
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DataReductionProxyIOData::OnEffectiveConnectionTypeChanged, io_data_,
type));
}
void DataReductionProxyService::OnRTTOrThroughputEstimatesComputed(
base::TimeDelta http_rtt,
base::TimeDelta transport_rtt,
int32_t downstream_throughput_kbps) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
http_rtt_ = http_rtt;
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DataReductionProxyIOData::OnRTTOrThroughputEstimatesComputed,
io_data_, http_rtt));
}
void DataReductionProxyService::Shutdown() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
weak_factory_.InvalidateWeakPtrs();
}
void DataReductionProxyService::UpdateDataUseForHost(int64_t network_bytes,
int64_t original_bytes,
const std::string& host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (compression_stats_) {
compression_stats_->RecordDataUseByHost(host, network_bytes, original_bytes,
base::Time::Now());
}
}
void DataReductionProxyService::UpdateContentLengths(
int64_t data_used,
int64_t original_size,
bool data_reduction_proxy_enabled,
DataReductionProxyRequestType request_type,
const std::string& mime_type,
bool is_user_traffic,
data_use_measurement::DataUseUserData::DataUseContentType content_type,
int32_t service_hash_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (compression_stats_) {
compression_stats_->RecordDataUseWithMimeType(
data_used, original_size, data_reduction_proxy_enabled, request_type,
mime_type, is_user_traffic, content_type, service_hash_code);
}
}
void DataReductionProxyService::AddEvent(std::unique_ptr<base::Value> event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
event_store_->AddEvent(std::move(event));
}
void DataReductionProxyService::AddEnabledEvent(
std::unique_ptr<base::Value> event,
bool enabled) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
event_store_->AddEnabledEvent(std::move(event), enabled);
}
void DataReductionProxyService::AddEventAndSecureProxyCheckState(
std::unique_ptr<base::Value> event,
SecureProxyCheckState state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
event_store_->AddEventAndSecureProxyCheckState(std::move(event), state);
}
void DataReductionProxyService::AddAndSetLastBypassEvent(
std::unique_ptr<base::Value> event,
int64_t expiration_ticks) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
event_store_->AddAndSetLastBypassEvent(std::move(event), expiration_ticks);
}
void DataReductionProxyService::SetUnreachable(bool unreachable) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
settings_->SetUnreachable(unreachable);
}
void DataReductionProxyService::SetInt64Pref(const std::string& pref_path,
int64_t value) {
if (prefs_)
prefs_->SetInt64(pref_path, value);
}
void DataReductionProxyService::SetStringPref(const std::string& pref_path,
const std::string& value) {
if (prefs_)
prefs_->SetString(pref_path, value);
}
void DataReductionProxyService::SetProxyPrefs(bool enabled, bool at_startup) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (io_task_runner_->BelongsToCurrentThread()) {
io_data_->SetProxyPrefs(enabled, at_startup);
return;
}
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&DataReductionProxyIOData::SetProxyPrefs,
io_data_, enabled, at_startup));
}
void DataReductionProxyService::SetPingbackReportingFraction(
float pingback_reporting_fraction) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pingback_client_->SetPingbackReportingFraction(pingback_reporting_fraction);
}
void DataReductionProxyService::OnCacheCleared(const base::Time start,
const base::Time end) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
io_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&DataReductionProxyIOData::OnCacheCleared,
io_data_, start, end));
}
net::EffectiveConnectionType
DataReductionProxyService::GetEffectiveConnectionType() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return effective_connection_type_;
}
base::Optional<base::TimeDelta> DataReductionProxyService::GetHttpRttEstimate()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return http_rtt_;
}
void DataReductionProxyService::LoadHistoricalDataUsage(
const HistoricalDataUsageCallback& load_data_usage_callback) {
std::unique_ptr<std::vector<DataUsageBucket>> data_usage(
new std::vector<DataUsageBucket>());
std::vector<DataUsageBucket>* data_usage_ptr = data_usage.get();
db_task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&DBDataOwner::LoadHistoricalDataUsage,
db_data_owner_->GetWeakPtr(),
base::Unretained(data_usage_ptr)),
base::BindOnce(load_data_usage_callback, std::move(data_usage)));
}
void DataReductionProxyService::LoadCurrentDataUsageBucket(
const LoadCurrentDataUsageCallback& load_current_data_usage_callback) {
std::unique_ptr<DataUsageBucket> bucket(new DataUsageBucket());
DataUsageBucket* bucket_ptr = bucket.get();
db_task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&DBDataOwner::LoadCurrentDataUsageBucket,
db_data_owner_->GetWeakPtr(),
base::Unretained(bucket_ptr)),
base::BindOnce(load_current_data_usage_callback, std::move(bucket)));
}
void DataReductionProxyService::StoreCurrentDataUsageBucket(
std::unique_ptr<DataUsageBucket> current) {
db_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&DBDataOwner::StoreCurrentDataUsageBucket,
db_data_owner_->GetWeakPtr(), std::move(current)));
}
void DataReductionProxyService::DeleteHistoricalDataUsage() {
db_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&DBDataOwner::DeleteHistoricalDataUsage,
db_data_owner_->GetWeakPtr()));
}
void DataReductionProxyService::DeleteBrowsingHistory(const base::Time& start,
const base::Time& end) {
DCHECK_LE(start, end);
db_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&DBDataOwner::DeleteBrowsingHistory,
db_data_owner_->GetWeakPtr(), start, end));
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&DataReductionProxyIOData::DeleteBrowsingHistory, io_data_,
start, end));
}
void DataReductionProxyService::AddObserver(
DataReductionProxyServiceObserver* observer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observer_list_.AddObserver(observer);
}
void DataReductionProxyService::RemoveObserver(
DataReductionProxyServiceObserver* observer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observer_list_.RemoveObserver(observer);
}
bool DataReductionProxyService::Initialized() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return initialized_;
}
base::WeakPtr<DataReductionProxyService>
DataReductionProxyService::GetWeakPtr() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return weak_factory_.GetWeakPtr();
}
} // namespace data_reduction_proxy