1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "components/data_reduction_proxy/browser/data_reduction_proxy_config_service.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/memory/ref_counted.h" 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/message_loop/message_loop.h" 10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_util.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace data_reduction_proxy { 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DataReductionProxyConfigService::DataReductionProxyConfigService( 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<net::ProxyConfigService> base_service) 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : config_read_pending_(true), 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registered_observer_(false), 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) enabled_(false), 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) restricted_(false) { 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base_service_ = base_service.Pass(); 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DataReductionProxyConfigService::~DataReductionProxyConfigService() { 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (registered_observer_ && base_service_.get()) 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base_service_->RemoveObserver(this); 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::AddObserver( 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfigService::Observer* observer) { 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RegisterObserver(); 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) observers_.AddObserver(observer); 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::RemoveObserver( 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfigService::Observer* observer) { 36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) observers_.RemoveObserver(observer); 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)net::ProxyConfigService::ConfigAvailability 40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DataReductionProxyConfigService::GetLatestProxyConfig( 41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig* config) { 42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RegisterObserver(); 43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (enabled_) { 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *config = config_; 46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return net::ProxyConfigService::CONFIG_VALID; 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Ask the base service if available. 50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig system_config; 51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ConfigAvailability system_availability = 52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfigService::CONFIG_UNSET; 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (base_service_.get()) { 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) system_availability = base_service_->GetLatestProxyConfig(&system_config); 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *config = system_config; 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (system_availability == net::ProxyConfigService::CONFIG_UNSET) { 58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *config = net::ProxyConfig::CreateDirect(); 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return net::ProxyConfigService::CONFIG_VALID; 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::OnLazyPoll() { 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (base_service_.get()) 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base_service_->OnLazyPoll(); 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::UpdateProxyConfig( 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool enabled, 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const net::ProxyConfig& config) { 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) config_read_pending_ = false; 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) enabled_ = enabled; 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) config_ = config; 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!observers_.might_have_observers()) 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Evaluate the proxy configuration. If GetLatestProxyConfig returns 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // CONFIG_PENDING, we are using the system proxy service, but it doesn't have 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // a valid configuration yet. Once it is ready, OnProxyConfigChanged() will be 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // called and broadcast the proxy configuration. 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: If a switch between a preference proxy configuration and the system 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // proxy configuration occurs an unnecessary notification might get sent if 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // the two configurations agree. This case should be rare however, so we don't 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // handle that case specially. 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig new_config; 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ConfigAvailability availability = GetLatestProxyConfig(&new_config); 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (availability != CONFIG_PENDING) { 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) OnProxyConfigChanged(new_config, availability)); 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::OnProxyConfigChanged( 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const net::ProxyConfig& config, 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ConfigAvailability availability) { 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Check whether the data reduction proxy is enabled. In this case that proxy 101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // configuration takes precedence and the change event from the delegate proxy 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // service can be disregarded. 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!enabled_) { 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig actual_config; 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) availability = GetLatestProxyConfig(&actual_config); 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) OnProxyConfigChanged(actual_config, availability)); 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigService::RegisterObserver() { 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!registered_observer_ && base_service_.get()) { 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base_service_->AddObserver(this); 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) registered_observer_ = true; 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DataReductionProxyConfigTracker::DataReductionProxyConfigTracker( 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Callback<void(bool, const net::ProxyConfig&)> update_proxy_config, 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::TaskRunner* task_runner) 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : update_proxy_config_(update_proxy_config), 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) task_runner_(task_runner) { 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DataReductionProxyConfigTracker::~DataReductionProxyConfigTracker() { 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigTracker::Enable( 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool primary_restricted, 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool fallback_restricted, 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& primary_origin, 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& fallback_origin, 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& ssl_origin) { 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::vector<std::string> proxies; 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!primary_restricted) { 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string trimmed_primary; 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::TrimString(primary_origin, "/", &trimmed_primary); 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!trimmed_primary.empty()) 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) proxies.push_back(trimmed_primary); 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!fallback_restricted) { 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string trimmed_fallback; 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::TrimString(fallback_origin, "/", &trimmed_fallback); 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!trimmed_fallback.empty()) 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) proxies.push_back(trimmed_fallback); 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (proxies.empty()) { 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string mode; 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Disable(); 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string trimmed_ssl; 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::TrimString(ssl_origin, "/", &trimmed_ssl); 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string server = "http=" + JoinString(proxies, ",") + ",direct://;" 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) + (ssl_origin.empty() ? "" : ("https=" + ssl_origin + ",direct://;")); 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig config; 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) config.proxy_rules().ParseFromString(server); 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) config.proxy_rules().bypass_rules.ParseFromString( 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) JoinString(bypass_rules_, ", ")); 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UpdateProxyConfigOnIOThread(true, config); 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigTracker::Disable() { 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) net::ProxyConfig config = net::ProxyConfig::CreateDirect(); 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UpdateProxyConfigOnIOThread(false, config); 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigTracker::AddHostPatternToBypass( 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& pattern) { 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bypass_rules_.push_back(pattern); 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigTracker::AddURLPatternToBypass( 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& pattern) { 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) size_t pos = pattern.find("/"); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (pattern.find("/", pos + 1) == pos + 1) 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) pos = pattern.find("/", pos + 2); 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string host_pattern; 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (pos != std::string::npos) 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) host_pattern = pattern.substr(0, pos); 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) else 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) host_pattern = pattern; 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) AddHostPatternToBypass(host_pattern); 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DataReductionProxyConfigTracker::UpdateProxyConfigOnIOThread( 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool enabled, 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const net::ProxyConfig& config) { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) task_runner_->PostTask( 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, base::Bind(update_proxy_config_, enabled, config)); 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace data_reduction_proxy 201