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.
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_config_service.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
12 namespace data_reduction_proxy {
14 DataReductionProxyConfigService::DataReductionProxyConfigService(
15 scoped_ptr<net::ProxyConfigService> base_service)
16 : config_read_pending_(true),
17 registered_observer_(false),
20 base_service_ = base_service.Pass();
23 DataReductionProxyConfigService::~DataReductionProxyConfigService() {
24 if (registered_observer_ && base_service_.get())
25 base_service_->RemoveObserver(this);
28 void DataReductionProxyConfigService::AddObserver(
29 net::ProxyConfigService::Observer* observer) {
31 observers_.AddObserver(observer);
34 void DataReductionProxyConfigService::RemoveObserver(
35 net::ProxyConfigService::Observer* observer) {
36 observers_.RemoveObserver(observer);
39 net::ProxyConfigService::ConfigAvailability
40 DataReductionProxyConfigService::GetLatestProxyConfig(
41 net::ProxyConfig* config) {
46 return net::ProxyConfigService::CONFIG_VALID;
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;
57 if (system_availability == net::ProxyConfigService::CONFIG_UNSET) {
58 *config = net::ProxyConfig::CreateDirect();
61 return net::ProxyConfigService::CONFIG_VALID;
64 void DataReductionProxyConfigService::OnLazyPoll() {
65 if (base_service_.get())
66 base_service_->OnLazyPoll();
69 void DataReductionProxyConfigService::UpdateProxyConfig(
71 const net::ProxyConfig& config) {
73 config_read_pending_ = false;
77 if (!observers_.might_have_observers())
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));
96 void DataReductionProxyConfigService::OnProxyConfigChanged(
97 const net::ProxyConfig& config,
98 ConfigAvailability availability) {
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.
104 net::ProxyConfig actual_config;
105 availability = GetLatestProxyConfig(&actual_config);
106 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
107 OnProxyConfigChanged(actual_config, availability));
111 void DataReductionProxyConfigService::RegisterObserver() {
112 if (!registered_observer_ && base_service_.get()) {
113 base_service_->AddObserver(this);
114 registered_observer_ = true;
118 DataReductionProxyConfigTracker::DataReductionProxyConfigTracker(
119 DataReductionProxyConfigService* config_service,
120 base::TaskRunner* task_runner)
121 : config_service_(config_service),
122 task_runner_(task_runner) {
123 DCHECK(config_service);
126 DataReductionProxyConfigTracker::~DataReductionProxyConfigTracker() {
129 void DataReductionProxyConfigTracker::Enable(
130 bool primary_restricted,
131 bool fallback_restricted,
132 const std::string& primary_origin,
133 const std::string& fallback_origin,
134 const std::string& ssl_origin) {
136 std::vector<std::string> proxies;
137 if (!primary_restricted) {
138 std::string trimmed_primary;
139 base::TrimString(primary_origin, "/", &trimmed_primary);
140 if (!trimmed_primary.empty())
141 proxies.push_back(trimmed_primary);
143 if (!fallback_restricted) {
144 std::string trimmed_fallback;
145 base::TrimString(fallback_origin, "/", &trimmed_fallback);
146 if (!trimmed_fallback.empty())
147 proxies.push_back(trimmed_fallback);
149 if (proxies.empty()) {
155 std::string trimmed_ssl;
156 base::TrimString(ssl_origin, "/", &trimmed_ssl);
158 std::string server = "http=" + JoinString(proxies, ",") + ",direct://;"
159 + (ssl_origin.empty() ? "" : ("https=" + ssl_origin + ",direct://;"));
161 net::ProxyConfig config;
162 config.proxy_rules().ParseFromString(server);
163 config.proxy_rules().bypass_rules.ParseFromString(
164 JoinString(bypass_rules_, ", "));
165 UpdateProxyConfigOnIOThread(true, config);
169 void DataReductionProxyConfigTracker::Disable() {
170 net::ProxyConfig config = net::ProxyConfig::CreateDirect();
171 UpdateProxyConfigOnIOThread(false, config);
174 void DataReductionProxyConfigTracker::AddHostPatternToBypass(
175 const std::string& pattern) {
176 bypass_rules_.push_back(pattern);
179 void DataReductionProxyConfigTracker::AddURLPatternToBypass(
180 const std::string& pattern) {
181 size_t pos = pattern.find("/");
182 if (pattern.find("/", pos + 1) == pos + 1)
183 pos = pattern.find("/", pos + 2);
185 std::string host_pattern;
186 if (pos != std::string::npos)
187 host_pattern = pattern.substr(0, pos);
189 host_pattern = pattern;
191 AddHostPatternToBypass(host_pattern);
194 void DataReductionProxyConfigTracker::UpdateProxyConfigOnIOThread(
196 const net::ProxyConfig& config) {
197 task_runner_->PostTask(FROM_HERE,
199 &DataReductionProxyConfigService::UpdateProxyConfig,
200 base::Unretained(config_service_),
204 } // namespace data_reduction_proxy