| // 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 <stddef.h> |
| |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/macros.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram.h" |
| #include "base/metrics/histogram_base.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/sparse_histogram.h" |
| #include "base/optional.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_piece.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/time/default_tick_clock.h" |
| #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" |
| #include "components/data_reduction_proxy/core/browser/warmup_url_fetcher.h" |
| #include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h" |
| #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.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_use_measurement/core/data_use_user_data.h" |
| #include "components/previews/core/previews_decider.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/load_flags.h" |
| #include "net/base/network_change_notifier.h" |
| #include "net/log/net_log_source_type.h" |
| #include "net/nqe/effective_connection_type.h" |
| #include "net/proxy/proxy_server.h" |
| #include "net/traffic_annotation/network_traffic_annotation.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "net/url_request/url_request_status.h" |
| |
| #if defined(OS_ANDROID) |
| #include "net/android/network_library.h" |
| #endif // OS_ANDROID |
| |
| using base::FieldTrialList; |
| |
| namespace { |
| |
| // Values of the UMA DataReductionProxy.Protocol.NotAcceptingTransform histogram |
| // defined in metrics/histograms/histograms.xml. This enum must remain |
| // synchronized with DataReductionProxyProtocolNotAcceptingTransformReason in |
| // tools/metrics/histograms/enums.xml. |
| enum NotAcceptingTransformReason { |
| NOT_ACCEPTING_TRANSFORM_DISABLED = 0, |
| NOT_ACCEPTING_TRANSFORM_BLACKLISTED = 1, |
| NOT_ACCEPTING_TRANSFORM_CELLULAR_ONLY = 2, |
| NOT_ACCEPTING_TRANSFORM_REASON_BOUNDARY |
| }; |
| |
| // 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 { |
| // The client IP address changed. |
| IP_CHANGED = 0, |
| // [Deprecated] Proxy is disabled because a VPN is running. |
| DEPRECATED_DISABLED_ON_VPN = 1, |
| // There was a network change. |
| NETWORK_CHANGED = 2, |
| CHANGE_EVENT_COUNT = NETWORK_CHANGED + 1 |
| |
| }; |
| |
| // 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); |
| } |
| |
| // Records UMA containing the result of requesting the secure proxy check. |
| void RecordSecureProxyCheckFetchResult( |
| data_reduction_proxy::SecureProxyCheckFetchResult result) { |
| UMA_HISTOGRAM_ENUMERATION( |
| kUMAProxyProbeURL, result, |
| data_reduction_proxy::SECURE_PROXY_CHECK_FETCH_RESULT_COUNT); |
| } |
| |
| enum class WarmupURLFetchAttemptEvent { |
| kFetchInitiated = 0, |
| kConnectionTypeNone = 1, |
| kProxyNotEnabledByUser = 2, |
| kWarmupURLFetchingDisabled = 3, |
| kCount |
| }; |
| |
| void RecordWarmupURLFetchAttemptEvent( |
| WarmupURLFetchAttemptEvent warmup_url_fetch_event) { |
| DCHECK_GT(WarmupURLFetchAttemptEvent::kCount, warmup_url_fetch_event); |
| UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.WarmupURL.FetchAttemptEvent", |
| warmup_url_fetch_event, |
| WarmupURLFetchAttemptEvent::kCount); |
| } |
| |
| } // namespace |
| |
| namespace data_reduction_proxy { |
| |
| DataReductionProxyConfig::DataReductionProxyConfig( |
| scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
| net::NetLog* net_log, |
| std::unique_ptr<DataReductionProxyConfigValues> config_values, |
| DataReductionProxyConfigurator* configurator, |
| DataReductionProxyEventCreator* event_creator) |
| : unreachable_(false), |
| enabled_by_user_(false), |
| config_values_(std::move(config_values)), |
| io_task_runner_(io_task_runner), |
| net_log_(net_log), |
| configurator_(configurator), |
| event_creator_(event_creator), |
| connection_type_(net::NetworkChangeNotifier::GetConnectionType()), |
| weak_factory_(this) { |
| DCHECK(io_task_runner_); |
| DCHECK(configurator); |
| DCHECK(event_creator); |
| // Constructed on the UI thread, but should be checked on the IO thread. |
| thread_checker_.DetachFromThread(); |
| } |
| |
| DataReductionProxyConfig::~DataReductionProxyConfig() { |
| net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
| } |
| |
| void DataReductionProxyConfig::InitializeOnIOThread( |
| const scoped_refptr<net::URLRequestContextGetter>& |
| basic_url_request_context_getter, |
| const scoped_refptr<net::URLRequestContextGetter>& |
| url_request_context_getter) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| secure_proxy_checker_.reset( |
| new SecureProxyChecker(basic_url_request_context_getter)); |
| warmup_url_fetcher_.reset(new WarmupURLFetcher(url_request_context_getter)); |
| |
| if (ShouldAddDefaultProxyBypassRules()) |
| AddDefaultProxyBypassRules(); |
| net::NetworkChangeNotifier::AddIPAddressObserver(this); |
| net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| } |
| |
| bool DataReductionProxyConfig::ShouldAddDefaultProxyBypassRules() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return true; |
| } |
| |
| void DataReductionProxyConfig::OnNewClientConfigFetched() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| ReloadConfig(); |
| } |
| |
| void DataReductionProxyConfig::ReloadConfig() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(configurator_); |
| |
| if (enabled_by_user_ && !params::IsIncludedInHoldbackFieldTrial() && |
| !config_values_->proxies_for_http().empty()) { |
| configurator_->Enable(!network_properties_manager_.IsSecureProxyAllowed(), |
| !network_properties_manager_.IsInsecureProxyAllowed(), |
| config_values_->proxies_for_http()); |
| } else { |
| configurator_->Disable(); |
| } |
| } |
| |
| bool DataReductionProxyConfig::WasDataReductionProxyUsed( |
| const net::URLRequest* request, |
| DataReductionProxyTypeInfo* proxy_info) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(request); |
| return IsDataReductionProxy(request->proxy_server(), proxy_info); |
| } |
| |
| bool DataReductionProxyConfig::IsDataReductionProxy( |
| const net::ProxyServer& proxy_server, |
| DataReductionProxyTypeInfo* proxy_info) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (!proxy_server.is_valid() || proxy_server.is_direct()) |
| return false; |
| |
| // Only compare the host port pair of the |proxy_server| since the proxy |
| // scheme of the stored data reduction proxy may be different than the proxy |
| // scheme of |proxy_server|. This may happen even when the |proxy_server| is a |
| // valid data reduction proxy. As an example, the stored data reduction proxy |
| // may have a proxy scheme of HTTPS while |proxy_server| may have QUIC as the |
| // proxy scheme. |
| const net::HostPortPair& host_port_pair = proxy_server.host_port_pair(); |
| |
| const std::vector<DataReductionProxyServer>& data_reduction_proxy_servers = |
| config_values_->proxies_for_http(); |
| |
| const auto proxy_it = std::find_if( |
| data_reduction_proxy_servers.begin(), data_reduction_proxy_servers.end(), |
| [&host_port_pair](const DataReductionProxyServer& proxy) { |
| return proxy.proxy_server().is_valid() && |
| proxy.proxy_server().host_port_pair().Equals(host_port_pair); |
| }); |
| |
| if (proxy_it == data_reduction_proxy_servers.end()) |
| return false; |
| |
| if (!proxy_info) |
| return true; |
| |
| proxy_info->proxy_servers = |
| DataReductionProxyServer::ConvertToNetProxyServers( |
| std::vector<DataReductionProxyServer>( |
| proxy_it, data_reduction_proxy_servers.end())); |
| proxy_info->proxy_index = |
| static_cast<size_t>(proxy_it - data_reduction_proxy_servers.begin()); |
| return true; |
| } |
| |
| bool DataReductionProxyConfig::IsBypassedByDataReductionProxyLocalRules( |
| const net::URLRequest& request, |
| const net::ProxyConfig& data_reduction_proxy_config) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(request.context()); |
| DCHECK(request.context()->proxy_service()); |
| net::ProxyInfo result; |
| data_reduction_proxy_config.proxy_rules().Apply( |
| request.url(), &result); |
| if (!result.proxy_server().is_valid()) |
| return true; |
| if (result.proxy_server().is_direct()) |
| return true; |
| return !IsDataReductionProxy(result.proxy_server(), nullptr); |
| } |
| |
| bool DataReductionProxyConfig::AreDataReductionProxiesBypassed( |
| const net::URLRequest& request, |
| const net::ProxyConfig& data_reduction_proxy_config, |
| base::TimeDelta* min_retry_delay) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (request.context() != nullptr && |
| request.context()->proxy_service() != nullptr) { |
| return AreProxiesBypassed( |
| request.context()->proxy_service()->proxy_retry_info(), |
| data_reduction_proxy_config.proxy_rules(), |
| request.url().SchemeIsCryptographic(), min_retry_delay); |
| } |
| |
| return false; |
| } |
| |
| bool DataReductionProxyConfig::AreProxiesBypassed( |
| const net::ProxyRetryInfoMap& retry_map, |
| const net::ProxyConfig::ProxyRules& proxy_rules, |
| bool is_https, |
| base::TimeDelta* min_retry_delay) const { |
| // Data reduction proxy config is TYPE_PROXY_PER_SCHEME. |
| if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) |
| return false; |
| |
| if (is_https) |
| return false; |
| |
| const net::ProxyList* proxies = |
| proxy_rules.MapUrlSchemeToProxyList(url::kHttpScheme); |
| |
| if (!proxies) |
| return false; |
| |
| base::TimeDelta min_delay = base::TimeDelta::Max(); |
| bool bypassed = false; |
| |
| for (const net::ProxyServer& proxy : proxies->GetAll()) { |
| if (!proxy.is_valid() || proxy.is_direct()) |
| continue; |
| |
| base::TimeDelta delay; |
| if (IsDataReductionProxy(proxy, nullptr)) { |
| if (!IsProxyBypassed(retry_map, proxy, &delay)) |
| return false; |
| if (delay < min_delay) |
| min_delay = delay; |
| bypassed = true; |
| } |
| } |
| |
| if (min_retry_delay && bypassed) |
| *min_retry_delay = min_delay; |
| |
| return bypassed; |
| } |
| |
| bool DataReductionProxyConfig::IsProxyBypassed( |
| const net::ProxyRetryInfoMap& retry_map, |
| const net::ProxyServer& proxy_server, |
| base::TimeDelta* retry_delay) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| net::ProxyRetryInfoMap::const_iterator found = |
| retry_map.find(proxy_server.ToURI()); |
| |
| if (found == retry_map.end() || found->second.bad_until < GetTicksNow()) { |
| return false; |
| } |
| |
| if (retry_delay) |
| *retry_delay = found->second.current_delay; |
| |
| return true; |
| } |
| |
| bool DataReductionProxyConfig::ContainsDataReductionProxy( |
| const net::ProxyConfig::ProxyRules& proxy_rules) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| // Data Reduction Proxy configurations are always TYPE_PROXY_PER_SCHEME. |
| if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) |
| return false; |
| |
| const net::ProxyList* http_proxy_list = |
| proxy_rules.MapUrlSchemeToProxyList("http"); |
| if (http_proxy_list && !http_proxy_list->IsEmpty() && |
| // Sufficient to check only the first proxy. |
| IsDataReductionProxy(http_proxy_list->Get(), nullptr)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void DataReductionProxyConfig::SetProxyConfig(bool enabled, bool at_startup) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| enabled_by_user_ = enabled; |
| ReloadConfig(); |
| |
| if (enabled_by_user_) { |
| HandleCaptivePortal(); |
| |
| // Check if the proxy has been restricted explicitly by the carrier. |
| // It is safe to use base::Unretained here, since it gets executed |
| // synchronously on the IO thread, and |this| outlives |
| // |secure_proxy_checker_|. |
| SecureProxyCheck( |
| base::Bind(&DataReductionProxyConfig::HandleSecureProxyCheckResponse, |
| base::Unretained(this))); |
| } |
| FetchWarmupURL(); |
| } |
| |
| void DataReductionProxyConfig::HandleCaptivePortal() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| bool is_captive_portal = GetIsCaptivePortal(); |
| UMA_HISTOGRAM_BOOLEAN("DataReductionProxy.CaptivePortalDetected.Platform", |
| is_captive_portal); |
| if (is_captive_portal == network_properties_manager_.IsCaptivePortal()) |
| return; |
| network_properties_manager_.SetIsCaptivePortal(is_captive_portal); |
| ReloadConfig(); |
| } |
| |
| bool DataReductionProxyConfig::GetIsCaptivePortal() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| #if defined(OS_ANDROID) |
| return net::android::GetIsCaptivePortal(); |
| #endif // OS_ANDROID |
| return false; |
| } |
| |
| void DataReductionProxyConfig::UpdateConfigForTesting( |
| bool enabled, |
| bool secure_proxies_allowed, |
| bool insecure_proxies_allowed) { |
| enabled_by_user_ = enabled; |
| network_properties_manager_.SetIsSecureProxyDisallowedByCarrier( |
| !secure_proxies_allowed); |
| network_properties_manager_.SetHasWarmupURLProbeFailed( |
| false, !insecure_proxies_allowed); |
| } |
| |
| void DataReductionProxyConfig::HandleSecureProxyCheckResponse( |
| const std::string& response, |
| const net::URLRequestStatus& status, |
| int http_response_code) { |
| bool success_response = |
| base::StartsWith(response, "OK", base::CompareCase::SENSITIVE); |
| if (event_creator_) { |
| event_creator_->EndSecureProxyCheck(net_log_with_source_, status.error(), |
| http_response_code, success_response); |
| } |
| |
| if (!status.is_success()) { |
| if (status.error() == net::ERR_INTERNET_DISCONNECTED) { |
| RecordSecureProxyCheckFetchResult(INTERNET_DISCONNECTED); |
| return; |
| } |
| // TODO(bengr): Remove once we understand the reasons secure proxy checks |
| // are failing. Secure proxy check 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())); |
| } |
| |
| bool secure_proxy_allowed_past = |
| !network_properties_manager_.IsSecureProxyDisallowedByCarrier(); |
| network_properties_manager_.SetIsSecureProxyDisallowedByCarrier( |
| !success_response); |
| if (!enabled_by_user_) |
| return; |
| |
| if (!network_properties_manager_.IsSecureProxyDisallowedByCarrier() != |
| secure_proxy_allowed_past) |
| ReloadConfig(); |
| |
| // Record the result. |
| if (secure_proxy_allowed_past && |
| !network_properties_manager_.IsSecureProxyDisallowedByCarrier()) { |
| RecordSecureProxyCheckFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED); |
| } else if (secure_proxy_allowed_past && |
| network_properties_manager_.IsSecureProxyDisallowedByCarrier()) { |
| RecordSecureProxyCheckFetchResult(FAILED_PROXY_DISABLED); |
| } else if (!secure_proxy_allowed_past && |
| !network_properties_manager_.IsSecureProxyDisallowedByCarrier()) { |
| RecordSecureProxyCheckFetchResult(SUCCEEDED_PROXY_ENABLED); |
| } else { |
| DCHECK(!secure_proxy_allowed_past && |
| network_properties_manager_.IsSecureProxyDisallowedByCarrier()); |
| RecordSecureProxyCheckFetchResult(FAILED_PROXY_ALREADY_DISABLED); |
| } |
| } |
| |
| void DataReductionProxyConfig::OnNetworkChanged( |
| net::NetworkChangeNotifier::ConnectionType type) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| connection_type_ = type; |
| RecordNetworkChangeEvent(NETWORK_CHANGED); |
| |
| FetchWarmupURL(); |
| } |
| |
| void DataReductionProxyConfig::OnIPAddressChanged() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (enabled_by_user_) { |
| RecordNetworkChangeEvent(IP_CHANGED); |
| |
| HandleCaptivePortal(); |
| // It is safe to use base::Unretained here, since it gets executed |
| // synchronously on the IO thread, and |this| outlives |
| // |secure_proxy_checker_|. |
| SecureProxyCheck( |
| base::Bind(&DataReductionProxyConfig::HandleSecureProxyCheckResponse, |
| base::Unretained(this))); |
| } |
| } |
| |
| void DataReductionProxyConfig::AddDefaultProxyBypassRules() { |
| DCHECK(configurator_); |
| configurator_->SetBypassRules( |
| // localhost |
| "<local>," |
| |
| // RFC6890 loopback addresses. |
| // TODO(tbansal): Remove this once crbug/446705 is fixed. |
| "127.0.0.0/8," |
| |
| // RFC6890 current network (only valid as source address). |
| "0.0.0.0/8," |
| |
| // RFC1918 private addresses. |
| "10.0.0.0/8," |
| "172.16.0.0/12," |
| "192.168.0.0/16," |
| |
| // RFC3513 unspecified address. |
| "::/128," |
| |
| // RFC4193 private addresses. |
| "fc00::/7," |
| |
| // IPV6 probe addresses. |
| "*-ds.metric.gstatic.com," |
| "*-v4.metric.gstatic.com"); |
| } |
| |
| void DataReductionProxyConfig::SecureProxyCheck( |
| SecureProxyCheckerCallback fetcher_callback) { |
| net_log_with_source_ = net::NetLogWithSource::Make( |
| net_log_, net::NetLogSourceType::DATA_REDUCTION_PROXY); |
| if (event_creator_) { |
| event_creator_->BeginSecureProxyCheck(net_log_with_source_, |
| params::GetSecureProxyCheckURL()); |
| } |
| |
| secure_proxy_checker_->CheckIfSecureProxyIsAllowed(fetcher_callback); |
| } |
| |
| void DataReductionProxyConfig::FetchWarmupURL() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (!enabled_by_user_) { |
| RecordWarmupURLFetchAttemptEvent( |
| WarmupURLFetchAttemptEvent::kProxyNotEnabledByUser); |
| return; |
| } |
| |
| if (!params::FetchWarmupURLEnabled()) { |
| RecordWarmupURLFetchAttemptEvent( |
| WarmupURLFetchAttemptEvent::kWarmupURLFetchingDisabled); |
| return; |
| } |
| |
| if (connection_type_ == net::NetworkChangeNotifier::CONNECTION_NONE) { |
| RecordWarmupURLFetchAttemptEvent( |
| WarmupURLFetchAttemptEvent::kConnectionTypeNone); |
| return; |
| } |
| |
| RecordWarmupURLFetchAttemptEvent(WarmupURLFetchAttemptEvent::kFetchInitiated); |
| |
| warmup_url_fetcher_->FetchWarmupURL(); |
| } |
| |
| bool DataReductionProxyConfig::ShouldEnableLoFi( |
| const net::URLRequest& request, |
| const previews::PreviewsDecider& previews_decider) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK((request.load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) != 0); |
| DCHECK(!request.url().SchemeIsCryptographic()); |
| |
| return ShouldAcceptServerPreview(request, previews_decider); |
| } |
| |
| bool DataReductionProxyConfig::ShouldEnableLitePages( |
| const net::URLRequest& request, |
| const previews::PreviewsDecider& previews_decider) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK((request.load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) != 0); |
| DCHECK(!request.url().SchemeIsCryptographic()); |
| |
| return ShouldAcceptServerPreview(request, previews_decider); |
| } |
| |
| bool DataReductionProxyConfig::enabled_by_user_and_reachable() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return enabled_by_user_ && !unreachable_; |
| } |
| |
| bool DataReductionProxyConfig::IsBlackListedOrDisabled( |
| const net::URLRequest& request, |
| const previews::PreviewsDecider& previews_decider, |
| previews::PreviewsType previews_type) const { |
| // Make sure request is not locally blacklisted. |
| // Pass in net::EFFECTIVE_CONNECTION_TYPE_4G as the threshold since we |
| // just want to check blacklisting here. |
| // TODO(crbug.com/720102): Consider new method to just check blacklist. |
| return !previews_decider.ShouldAllowPreviewAtECT( |
| request, previews_type, net::EFFECTIVE_CONNECTION_TYPE_4G, |
| std::vector<std::string>()); |
| } |
| |
| bool DataReductionProxyConfig::ShouldAcceptServerPreview( |
| const net::URLRequest& request, |
| const previews::PreviewsDecider& previews_decider) const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (!base::FeatureList::IsEnabled( |
| features::kDataReductionProxyDecidesTransform)) { |
| return false; |
| } |
| |
| // For the transition to server-driven previews decisions, we will |
| // use existing Lo-Fi flags for disabling and cellular-only mode. |
| // TODO(dougarnett): Refactor flag names as part of bug 725645. |
| if (params::IsLoFiDisabledViaFlags()) { |
| UMA_HISTOGRAM_ENUMERATION( |
| "DataReductionProxy.Protocol.NotAcceptingTransform", |
| NOT_ACCEPTING_TRANSFORM_DISABLED, |
| NOT_ACCEPTING_TRANSFORM_REASON_BOUNDARY); |
| return false; |
| } |
| |
| // AlwaysOn skips blacklist or disabled checks. |
| if (params::IsLoFiAlwaysOnViaFlags()) |
| return true; |
| |
| if (IsBlackListedOrDisabled(request, previews_decider, |
| previews::PreviewsType::LITE_PAGE) || |
| IsBlackListedOrDisabled(request, previews_decider, |
| previews::PreviewsType::LOFI)) { |
| UMA_HISTOGRAM_ENUMERATION( |
| "DataReductionProxy.Protocol.NotAcceptingTransform", |
| NOT_ACCEPTING_TRANSFORM_BLACKLISTED, |
| NOT_ACCEPTING_TRANSFORM_REASON_BOUNDARY); |
| return false; |
| } |
| |
| if (params::IsLoFiCellularOnlyViaFlags() && |
| !net::NetworkChangeNotifier::IsConnectionCellular(connection_type_)) { |
| UMA_HISTOGRAM_ENUMERATION( |
| "DataReductionProxy.Protocol.NotAcceptingTransform", |
| NOT_ACCEPTING_TRANSFORM_CELLULAR_ONLY, |
| NOT_ACCEPTING_TRANSFORM_REASON_BOUNDARY); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| base::TimeTicks DataReductionProxyConfig::GetTicksNow() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return base::TimeTicks::Now(); |
| } |
| |
| void DataReductionProxyConfig::OnInsecureProxyWarmupURLProbeStatusChange( |
| bool insecure_proxies_allowed) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| bool old_status = network_properties_manager_.IsInsecureProxyAllowed(); |
| network_properties_manager_.SetHasWarmupURLProbeFailed( |
| false, !insecure_proxies_allowed); |
| |
| if (old_status == network_properties_manager_.IsInsecureProxyAllowed()) |
| return; |
| ReloadConfig(); |
| } |
| |
| net::ProxyConfig DataReductionProxyConfig::ProxyConfigIgnoringHoldback() const { |
| if (!enabled_by_user_ || config_values_->proxies_for_http().empty()) |
| return net::ProxyConfig::CreateDirect(); |
| return configurator_->CreateProxyConfig( |
| !network_properties_manager_.IsSecureProxyAllowed(), |
| !network_properties_manager_.IsInsecureProxyAllowed(), |
| config_values_->proxies_for_http()); |
| } |
| |
| bool DataReductionProxyConfig::secure_proxy_allowed() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return network_properties_manager_.IsSecureProxyAllowed(); |
| } |
| |
| bool DataReductionProxyConfig::insecure_proxies_allowed() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return network_properties_manager_.IsInsecureProxyAllowed(); |
| } |
| |
| std::vector<DataReductionProxyServer> |
| DataReductionProxyConfig::GetProxiesForHttp() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (!enabled_by_user_) |
| return std::vector<DataReductionProxyServer>(); |
| |
| return config_values_->proxies_for_http(); |
| } |
| |
| } // namespace data_reduction_proxy |