| Index: components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
|
| diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0fbd744faeea3d609014ad8e2274aa32618e2758
|
| --- /dev/null
|
| +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
|
| @@ -0,0 +1,292 @@
|
| +// 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_config.h"
|
| +
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/metrics/sparse_histogram.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
|
| +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h"
|
| +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
|
| +#include "net/base/load_flags.h"
|
| +#include "net/url_request/url_fetcher.h"
|
| +#include "net/url_request/url_request_context_getter.h"
|
| +#include "net/url_request/url_request_status.h"
|
| +
|
| +namespace {
|
| +
|
| +// Values of the UMA DataReductionProxy.NetworkChangeEvents histograms.
|
| +// This enum must remain synchronized with the enum of the same
|
| +// name in metrics/histograms/histograms.xml.
|
| +enum DataReductionProxyNetworkChangeEvent {
|
| + IP_CHANGED = 0, // The client IP address changed.
|
| + DISABLED_ON_VPN = 1, // The proxy is disabled because a VPN is running.
|
| + CHANGE_EVENT_COUNT = 2 // This must always be last.
|
| +};
|
| +
|
| +// Key of the UMA DataReductionProxy.ProbeURL histogram.
|
| +const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL";
|
| +
|
| +// Key of the UMA DataReductionProxy.ProbeURLNetError histogram.
|
| +const char kUMAProxyProbeURLNetError[] = "DataReductionProxy.ProbeURLNetError";
|
| +
|
| +// Record a network change event.
|
| +void RecordNetworkChangeEvent(DataReductionProxyNetworkChangeEvent event) {
|
| + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.NetworkChangeEvents", event,
|
| + CHANGE_EVENT_COUNT);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace data_reduction_proxy {
|
| +
|
| +DataReductionProxyConfig::DataReductionProxyConfig(
|
| + scoped_ptr<DataReductionProxyParams> params)
|
| + : restricted_by_carrier_(false),
|
| + disabled_on_vpn_(false),
|
| + unreachable_(false),
|
| + enabled_by_user_(false),
|
| + alternative_enabled_by_user_(false),
|
| + net_log_(nullptr),
|
| + url_request_context_getter_(nullptr),
|
| + configurator_(nullptr),
|
| + event_store_(nullptr) {
|
| + params_.reset(params.release());
|
| +}
|
| +
|
| +DataReductionProxyConfig::~DataReductionProxyConfig() {
|
| + net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
|
| +}
|
| +
|
| +void DataReductionProxyConfig::InitDataReductionProxyConfig(
|
| + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
|
| + net::NetLog* net_log,
|
| + net::URLRequestContextGetter* url_request_context_getter,
|
| + DataReductionProxyConfigurator* configurator,
|
| + DataReductionProxyEventStore* event_store) {
|
| + DCHECK(io_task_runner);
|
| + DCHECK(configurator);
|
| + DCHECK(event_store);
|
| + DCHECK(io_task_runner->BelongsToCurrentThread());
|
| + io_task_runner_ = io_task_runner;
|
| + net_log_ = net_log;
|
| + url_request_context_getter_ = url_request_context_getter;
|
| + configurator_ = configurator;
|
| + event_store_ = event_store;
|
| + net::NetworkChangeNotifier::AddIPAddressObserver(this);
|
| +}
|
| +
|
| +void DataReductionProxyConfig::SetProxyConfigs(bool enabled,
|
| + bool alternative_enabled,
|
| + bool restricted,
|
| + bool at_startup) {
|
| + DCHECK(configurator_);
|
| +
|
| + LogProxyState(enabled, restricted, at_startup);
|
| + // The alternative is only configured if the standard configuration is
|
| + // is enabled.
|
| + if (enabled & !params()->holdback()) {
|
| + if (alternative_enabled) {
|
| + configurator_->Enable(restricted,
|
| + !params()->alternative_fallback_allowed(),
|
| + params()->alt_origin().spec(), std::string(),
|
| + params()->ssl_origin().spec());
|
| + } else {
|
| + configurator_->Enable(restricted, !params()->fallback_allowed(),
|
| + params()->origin().spec(),
|
| + params()->fallback_origin().spec(), std::string());
|
| + }
|
| + } else {
|
| + configurator_->Disable();
|
| + }
|
| +}
|
| +
|
| +void DataReductionProxyConfig::LogProxyState(bool enabled,
|
| + bool restricted,
|
| + bool at_startup) {
|
| + // This must stay a LOG(WARNING); the output is used in processing customer
|
| + // feedback.
|
| + const char kAtStartup[] = "at startup";
|
| + const char kByUser[] = "by user action";
|
| + const char kOn[] = "ON";
|
| + const char kOff[] = "OFF";
|
| + const char kRestricted[] = "(Restricted)";
|
| + const char kUnrestricted[] = "(Unrestricted)";
|
| +
|
| + std::string annotated_on =
|
| + kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);
|
| +
|
| + LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff) << " "
|
| + << (at_startup ? kAtStartup : kByUser);
|
| +}
|
| +
|
| +void DataReductionProxyConfig::OnURLFetchComplete(
|
| + const net::URLFetcher* source) {
|
| + DCHECK(source == fetcher_.get());
|
| + net::URLRequestStatus status = source->GetStatus();
|
| +
|
| + if (event_store_) {
|
| + event_store_->EndCanaryRequest(bound_net_log_, status.error());
|
| + }
|
| +
|
| + if (status.status() == net::URLRequestStatus::FAILED) {
|
| + if (status.error() == net::ERR_INTERNET_DISCONNECTED) {
|
| + RecordProbeURLFetchResult(INTERNET_DISCONNECTED);
|
| + return;
|
| + }
|
| + // TODO(bengr): Remove once we understand the reasons probes are failing.
|
| + // Probe errors are either due to fetcher-level errors or modified
|
| + // responses. This only tracks the former.
|
| + UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAProxyProbeURLNetError,
|
| + std::abs(status.error()));
|
| + }
|
| +
|
| + std::string response;
|
| + source->GetResponseAsString(&response);
|
| +
|
| + if ("OK" == response.substr(0, 2)) {
|
| + DVLOG(1) << "The data reduction proxy is unrestricted.";
|
| +
|
| + if (enabled_by_user_) {
|
| + if (restricted_by_carrier_) {
|
| + // The user enabled the proxy, but sometime previously in the session,
|
| + // the network operator had blocked the canary and restricted the user.
|
| + // The current network doesn't block the canary, so don't restrict the
|
| + // proxy configurations.
|
| + SetProxyConfigs(true /* enabled */, false /* alternative_enabled */,
|
| + false /* restricted */, false /* at_startup */);
|
| + RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED);
|
| + } else {
|
| + RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED);
|
| + }
|
| + }
|
| + restricted_by_carrier_ = false;
|
| + return;
|
| + }
|
| + DVLOG(1) << "The data reduction proxy is restricted to the configured "
|
| + << "fallback proxy.";
|
| + if (enabled_by_user_) {
|
| + if (!restricted_by_carrier_) {
|
| + // Restrict the proxy.
|
| + SetProxyConfigs(true /* enabled */, false /* alternative_enabled */,
|
| + true /* restricted */, false /* at_startup */);
|
| + RecordProbeURLFetchResult(FAILED_PROXY_DISABLED);
|
| + } else {
|
| + RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED);
|
| + }
|
| + }
|
| + restricted_by_carrier_ = true;
|
| +}
|
| +
|
| +void DataReductionProxyConfig::OnIPAddressChanged() {
|
| + if (enabled_by_user_) {
|
| + DCHECK(params()->allowed());
|
| + RecordNetworkChangeEvent(IP_CHANGED);
|
| + if (DisableIfVPN())
|
| + return;
|
| + if (alternative_enabled_by_user_ &&
|
| + !params()->alternative_fallback_allowed()) {
|
| + return;
|
| + }
|
| + ProbeWhetherDataReductionProxyIsAvailable();
|
| + }
|
| +}
|
| +
|
| +void DataReductionProxyConfig::AddDefaultProxyBypassRules() {
|
| + // localhost
|
| + DCHECK(configurator_);
|
| + configurator_->AddHostPatternToBypass("<local>");
|
| + // RFC6890 loopback addresses.
|
| + // TODO(tbansal): Remove this once crbug/446705 is fixed.
|
| + configurator_->AddHostPatternToBypass("127.0.0.0/8");
|
| +
|
| + // RFC6890 current network (only valid as source address).
|
| + configurator_->AddHostPatternToBypass("0.0.0.0/8");
|
| +
|
| + // RFC1918 private addresses.
|
| + configurator_->AddHostPatternToBypass("10.0.0.0/8");
|
| + configurator_->AddHostPatternToBypass("172.16.0.0/12");
|
| + configurator_->AddHostPatternToBypass("192.168.0.0/16");
|
| +
|
| + // RFC3513 unspecified address.
|
| + configurator_->AddHostPatternToBypass("::/128");
|
| +
|
| + // RFC4193 private addresses.
|
| + configurator_->AddHostPatternToBypass("fc00::/7");
|
| + // IPV6 probe addresses.
|
| + configurator_->AddHostPatternToBypass("*-ds.metric.gstatic.com");
|
| + configurator_->AddHostPatternToBypass("*-v4.metric.gstatic.com");
|
| +}
|
| +
|
| +void DataReductionProxyConfig::RecordProbeURLFetchResult(
|
| + ProbeURLFetchResult result) {
|
| + UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL, result,
|
| + PROBE_URL_FETCH_RESULT_COUNT);
|
| +}
|
| +
|
| +net::URLFetcher* DataReductionProxyConfig::GetURLFetcherForProbe() {
|
| + net::URLFetcher* fetcher =
|
| + net::URLFetcher::Create(params_->probe_url(), net::URLFetcher::GET, this);
|
| + fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
|
| + DCHECK(url_request_context_getter_);
|
| + fetcher->SetRequestContext(url_request_context_getter_);
|
| + // Configure max retries to be at most kMaxRetries times for 5xx errors.
|
| + static const int kMaxRetries = 5;
|
| + fetcher->SetMaxRetriesOn5xx(kMaxRetries);
|
| + fetcher->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
|
| + return fetcher;
|
| +}
|
| +
|
| +void DataReductionProxyConfig::ProbeWhetherDataReductionProxyIsAvailable() {
|
| + net::URLFetcher* fetcher = GetURLFetcherForProbe();
|
| + if (!fetcher)
|
| + return;
|
| + fetcher_.reset(fetcher);
|
| +
|
| + bound_net_log_ = net::BoundNetLog::Make(
|
| + net_log_, net::NetLog::SOURCE_DATA_REDUCTION_PROXY);
|
| + if (event_store_) {
|
| + event_store_->BeginCanaryRequest(bound_net_log_,
|
| + fetcher_->GetOriginalURL());
|
| + }
|
| +
|
| + fetcher_->Start();
|
| +}
|
| +
|
| +void DataReductionProxyConfig::GetNetworkList(
|
| + net::NetworkInterfaceList* interfaces,
|
| + int policy) {
|
| + net::GetNetworkList(interfaces, policy);
|
| +}
|
| +
|
| +bool DataReductionProxyConfig::DisableIfVPN() {
|
| + net::NetworkInterfaceList network_interfaces;
|
| + GetNetworkList(&network_interfaces, 0);
|
| + // VPNs use a "tun" interface, so the presence of a "tun" interface indicates
|
| + // a VPN is in use.
|
| + // TODO(kundaji): Verify this works on Windows.
|
| + const std::string vpn_interface_name_prefix = "tun";
|
| + for (size_t i = 0; i < network_interfaces.size(); ++i) {
|
| + std::string interface_name = network_interfaces[i].name;
|
| + if (LowerCaseEqualsASCII(
|
| + interface_name.begin(),
|
| + interface_name.begin() + vpn_interface_name_prefix.size(),
|
| + vpn_interface_name_prefix.c_str())) {
|
| + SetProxyConfigs(false, alternative_enabled_by_user_, false, false);
|
| + disabled_on_vpn_ = true;
|
| + RecordNetworkChangeEvent(DISABLED_ON_VPN);
|
| + return true;
|
| + }
|
| + }
|
| + if (disabled_on_vpn_) {
|
| + SetProxyConfigs(enabled_by_user_, alternative_enabled_by_user_,
|
| + restricted_by_carrier_, false);
|
| + }
|
| + disabled_on_vpn_ = false;
|
| + return false;
|
| +}
|
| +
|
| +} // namespace data_reduction_proxy
|
|
|