1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/data_reduction_proxy/browser/data_reduction_proxy_config_service.h" 6 7#include "base/bind.h" 8#include "base/memory/ref_counted.h" 9#include "base/message_loop/message_loop.h" 10#include "base/strings/string_util.h" 11 12namespace data_reduction_proxy { 13 14DataReductionProxyConfigService::DataReductionProxyConfigService( 15 scoped_ptr<net::ProxyConfigService> base_service) 16 : config_read_pending_(true), 17 registered_observer_(false), 18 enabled_(false), 19 restricted_(false) { 20 base_service_ = base_service.Pass(); 21} 22 23DataReductionProxyConfigService::~DataReductionProxyConfigService() { 24 if (registered_observer_ && base_service_.get()) 25 base_service_->RemoveObserver(this); 26} 27 28void DataReductionProxyConfigService::AddObserver( 29 net::ProxyConfigService::Observer* observer) { 30 RegisterObserver(); 31 observers_.AddObserver(observer); 32} 33 34void DataReductionProxyConfigService::RemoveObserver( 35 net::ProxyConfigService::Observer* observer) { 36 observers_.RemoveObserver(observer); 37} 38 39net::ProxyConfigService::ConfigAvailability 40DataReductionProxyConfigService::GetLatestProxyConfig( 41 net::ProxyConfig* config) { 42 RegisterObserver(); 43 44 if (enabled_) { 45 *config = config_; 46 return net::ProxyConfigService::CONFIG_VALID; 47 } 48 49 // Ask the base service if available. 50 net::ProxyConfig system_config; 51 ConfigAvailability system_availability = 52 net::ProxyConfigService::CONFIG_UNSET; 53 if (base_service_.get()) { 54 system_availability = base_service_->GetLatestProxyConfig(&system_config); 55 *config = system_config; 56 } 57 if (system_availability == net::ProxyConfigService::CONFIG_UNSET) { 58 *config = net::ProxyConfig::CreateDirect(); 59 } 60 61 return net::ProxyConfigService::CONFIG_VALID; 62} 63 64void DataReductionProxyConfigService::OnLazyPoll() { 65 if (base_service_.get()) 66 base_service_->OnLazyPoll(); 67} 68 69void DataReductionProxyConfigService::UpdateProxyConfig( 70 bool enabled, 71 const net::ProxyConfig& config) { 72 73 config_read_pending_ = false; 74 enabled_ = enabled; 75 config_ = config; 76 77 if (!observers_.might_have_observers()) 78 return; 79 80 // Evaluate the proxy configuration. If GetLatestProxyConfig returns 81 // CONFIG_PENDING, we are using the system proxy service, but it doesn't have 82 // a valid configuration yet. Once it is ready, OnProxyConfigChanged() will be 83 // called and broadcast the proxy configuration. 84 // Note: If a switch between a preference proxy configuration and the system 85 // proxy configuration occurs an unnecessary notification might get sent if 86 // the two configurations agree. This case should be rare however, so we don't 87 // handle that case specially. 88 net::ProxyConfig new_config; 89 ConfigAvailability availability = GetLatestProxyConfig(&new_config); 90 if (availability != CONFIG_PENDING) { 91 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, 92 OnProxyConfigChanged(new_config, availability)); 93 } 94} 95 96void DataReductionProxyConfigService::OnProxyConfigChanged( 97 const net::ProxyConfig& config, 98 ConfigAvailability availability) { 99 100 // Check whether the data reduction proxy is enabled. In this case that proxy 101 // configuration takes precedence and the change event from the delegate proxy 102 // service can be disregarded. 103 if (!enabled_) { 104 net::ProxyConfig actual_config; 105 availability = GetLatestProxyConfig(&actual_config); 106 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, 107 OnProxyConfigChanged(actual_config, availability)); 108 } 109} 110 111void DataReductionProxyConfigService::RegisterObserver() { 112 if (!registered_observer_ && base_service_.get()) { 113 base_service_->AddObserver(this); 114 registered_observer_ = true; 115 } 116} 117 118DataReductionProxyConfigTracker::DataReductionProxyConfigTracker( 119 base::Callback<void(bool, const net::ProxyConfig&)> update_proxy_config, 120 base::TaskRunner* task_runner) 121 : update_proxy_config_(update_proxy_config), 122 task_runner_(task_runner) { 123} 124 125DataReductionProxyConfigTracker::~DataReductionProxyConfigTracker() { 126} 127 128void DataReductionProxyConfigTracker::Enable( 129 bool primary_restricted, 130 bool fallback_restricted, 131 const std::string& primary_origin, 132 const std::string& fallback_origin, 133 const std::string& ssl_origin) { 134 135 std::vector<std::string> proxies; 136 if (!primary_restricted) { 137 std::string trimmed_primary; 138 base::TrimString(primary_origin, "/", &trimmed_primary); 139 if (!trimmed_primary.empty()) 140 proxies.push_back(trimmed_primary); 141 } 142 if (!fallback_restricted) { 143 std::string trimmed_fallback; 144 base::TrimString(fallback_origin, "/", &trimmed_fallback); 145 if (!trimmed_fallback.empty()) 146 proxies.push_back(trimmed_fallback); 147 } 148 if (proxies.empty()) { 149 std::string mode; 150 Disable(); 151 return; 152 } 153 154 std::string trimmed_ssl; 155 base::TrimString(ssl_origin, "/", &trimmed_ssl); 156 157 std::string server = "http=" + JoinString(proxies, ",") + ",direct://;" 158 + (ssl_origin.empty() ? "" : ("https=" + ssl_origin + ",direct://;")); 159 160 net::ProxyConfig config; 161 config.proxy_rules().ParseFromString(server); 162 config.proxy_rules().bypass_rules.ParseFromString( 163 JoinString(bypass_rules_, ", ")); 164 UpdateProxyConfigOnIOThread(true, config); 165} 166 167 168void DataReductionProxyConfigTracker::Disable() { 169 net::ProxyConfig config = net::ProxyConfig::CreateDirect(); 170 UpdateProxyConfigOnIOThread(false, config); 171} 172 173void DataReductionProxyConfigTracker::AddHostPatternToBypass( 174 const std::string& pattern) { 175 bypass_rules_.push_back(pattern); 176} 177 178void DataReductionProxyConfigTracker::AddURLPatternToBypass( 179 const std::string& pattern) { 180 size_t pos = pattern.find("/"); 181 if (pattern.find("/", pos + 1) == pos + 1) 182 pos = pattern.find("/", pos + 2); 183 184 std::string host_pattern; 185 if (pos != std::string::npos) 186 host_pattern = pattern.substr(0, pos); 187 else 188 host_pattern = pattern; 189 190 AddHostPatternToBypass(host_pattern); 191} 192 193void DataReductionProxyConfigTracker::UpdateProxyConfigOnIOThread( 194 bool enabled, 195 const net::ProxyConfig& config) { 196 task_runner_->PostTask( 197 FROM_HERE, base::Bind(update_proxy_config_, enabled, config)); 198} 199 200} // namespace data_reduction_proxy 201