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 base::Callback
<void(bool, const net::ProxyConfig
&)> update_proxy_config
,
120 const scoped_refptr
<base::TaskRunner
>& task_runner
)
121 : update_proxy_config_(update_proxy_config
),
122 task_runner_(task_runner
) {
125 DataReductionProxyConfigTracker::~DataReductionProxyConfigTracker() {
128 void 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
) {
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
);
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
);
148 if (proxies
.empty()) {
154 std::string trimmed_ssl
;
155 base::TrimString(ssl_origin
, "/", &trimmed_ssl
);
157 std::string server
= "http=" + JoinString(proxies
, ",") + ",direct://;"
158 + (ssl_origin
.empty() ? "" : ("https=" + ssl_origin
+ ",direct://;"));
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
);
168 void DataReductionProxyConfigTracker::Disable() {
169 net::ProxyConfig config
= net::ProxyConfig::CreateDirect();
170 UpdateProxyConfigOnIOThread(false, config
);
173 void DataReductionProxyConfigTracker::AddHostPatternToBypass(
174 const std::string
& pattern
) {
175 bypass_rules_
.push_back(pattern
);
178 void 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);
184 std::string host_pattern
;
185 if (pos
!= std::string::npos
)
186 host_pattern
= pattern
.substr(0, pos
);
188 host_pattern
= pattern
;
190 AddHostPatternToBypass(host_pattern
);
193 void DataReductionProxyConfigTracker::UpdateProxyConfigOnIOThread(
195 const net::ProxyConfig
& config
) {
196 task_runner_
->PostTask(
197 FROM_HERE
, base::Bind(update_proxy_config_
, enabled
, config
));
200 } // namespace data_reduction_proxy