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 "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
9 #include "base/base64.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/strings/string_util.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
22 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
23 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
24 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
25 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
26 #include "components/data_reduction_proxy/core/browser/data_store.h"
27 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
28 #include "components/proxy_config/proxy_config_pref_names.h"
29 #include "components/proxy_config/proxy_prefs.h"
30 #include "net/base/host_port_pair.h"
31 #include "net/proxy/proxy_config.h"
32 #include "net/proxy/proxy_list.h"
33 #include "net/proxy/proxy_server.h"
34 #include "net/url_request/url_request_context_getter.h"
38 // Assume that any proxy host ending with this suffix is a Data Reduction Proxy.
39 const char kDataReductionProxyDefaultHostSuffix
[] = ".googlezip.net";
41 // Searches |proxy_list| for any Data Reduction Proxies, even if they don't
42 // match a currently configured Data Reduction Proxy.
43 bool ContainsDataReductionProxyDefaultHostSuffix(
44 const net::ProxyList
& proxy_list
) {
45 for (const net::ProxyServer
& proxy
: proxy_list
.GetAll()) {
46 if (proxy
.is_valid() && !proxy
.is_direct() &&
47 base::EndsWith(proxy
.host_port_pair().host(),
48 kDataReductionProxyDefaultHostSuffix
,
49 base::CompareCase::SENSITIVE
)) {
56 // Searches |proxy_rules| for any Data Reduction Proxies, even if they don't
57 // match a currently configured Data Reduction Proxy.
58 bool ContainsDataReductionProxyDefaultHostSuffix(
59 const net::ProxyConfig::ProxyRules
& proxy_rules
) {
60 return ContainsDataReductionProxyDefaultHostSuffix(
61 proxy_rules
.proxies_for_http
) ||
62 ContainsDataReductionProxyDefaultHostSuffix(
63 proxy_rules
.proxies_for_https
);
66 // Extract the embedded PAC script from the given |pac_url|, and store the
67 // extracted script in |pac_script|. Returns true if extraction was successful,
68 // otherwise returns false. |pac_script| must not be NULL.
69 bool GetEmbeddedPacScript(const std::string
& pac_url
, std::string
* pac_script
) {
71 const std::string kPacURLPrefix
=
72 "data:application/x-ns-proxy-autoconfig;base64,";
73 return base::StartsWith(pac_url
, kPacURLPrefix
,
74 base::CompareCase::SENSITIVE
) &&
75 base::Base64Decode(pac_url
.substr(kPacURLPrefix
.size()), pac_script
);
80 // The Data Reduction Proxy has been turned into a "best effort" proxy,
81 // meaning it is used only if the effective proxy configuration resolves to
82 // DIRECT for a URL. It no longer can be a ProxyConfig in the proxy preference
83 // hierarchy. This method removes the Data Reduction Proxy configuration from
84 // prefs, if present. |proxy_pref_name| is the name of the proxy pref.
85 void DataReductionProxyChromeSettings::MigrateDataReductionProxyOffProxyPrefs(
87 ProxyPrefMigrationResult proxy_pref_status
=
88 MigrateDataReductionProxyOffProxyPrefsHelper(prefs
);
89 UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ProxyPrefMigrationResult",
91 DataReductionProxyChromeSettings::PROXY_PREF_MAX
);
94 DataReductionProxyChromeSettings::ProxyPrefMigrationResult
95 DataReductionProxyChromeSettings::MigrateDataReductionProxyOffProxyPrefsHelper(
97 base::DictionaryValue
* dict
= (base::DictionaryValue
*)prefs
->GetUserPrefValue(
98 proxy_config::prefs::kProxy
);
100 return PROXY_PREF_NOT_CLEARED
;
102 // Clear empty "proxy" dictionary created by a bug. See http://crbug/448172.
104 prefs
->ClearPref(proxy_config::prefs::kProxy
);
105 return PROXY_PREF_CLEARED_EMPTY
;
109 if (!dict
->GetString("mode", &mode
))
110 return PROXY_PREF_NOT_CLEARED
;
111 // Clear "system" proxy entry since this is the default. This entry was
112 // created by bug (http://crbug/448172).
113 if (ProxyModeToString(ProxyPrefs::MODE_SYSTEM
) == mode
) {
114 prefs
->ClearPref(proxy_config::prefs::kProxy
);
115 return PROXY_PREF_CLEARED_MODE_SYSTEM
;
118 // From M36 to M40, the DRP was configured using MODE_FIXED_SERVERS in the
120 if (ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS
) == mode
) {
121 std::string proxy_server
;
122 if (!dict
->GetString("server", &proxy_server
))
123 return PROXY_PREF_NOT_CLEARED
;
124 net::ProxyConfig::ProxyRules proxy_rules
;
125 proxy_rules
.ParseFromString(proxy_server
);
126 // Clear the proxy pref if it matches a currently configured Data Reduction
127 // Proxy, or if the proxy host ends with ".googlezip.net", in order to
128 // ensure that any DRP in the pref is cleared even if the DRP configuration
129 // was changed. See http://crbug.com/476610.
130 ProxyPrefMigrationResult rv
;
131 if (Config()->ContainsDataReductionProxy(proxy_rules
))
132 rv
= PROXY_PREF_CLEARED_DRP
;
133 else if (ContainsDataReductionProxyDefaultHostSuffix(proxy_rules
))
134 rv
= PROXY_PREF_CLEARED_GOOGLEZIP
;
136 return PROXY_PREF_NOT_CLEARED
;
138 prefs
->ClearPref(proxy_config::prefs::kProxy
);
142 // Before M35, the DRP was configured using a PAC script base64 encoded into a
144 if (ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT
) == mode
) {
146 std::string pac_script
;
147 if (!dict
->GetString("pac_url", &pac_url
) ||
148 !GetEmbeddedPacScript(pac_url
, &pac_script
)) {
149 return PROXY_PREF_NOT_CLEARED
;
152 // In M35 and earlier, the way of specifying the DRP in a PAC script would
153 // always include the port number after the host even if the port number
154 // could be implied, so searching for ".googlezip.net:" in the PAC script
155 // indicates whether there's a proxy in that PAC script with a host of the
156 // form "*.googlezip.net".
157 if (pac_script
.find(".googlezip.net:") == std::string::npos
)
158 return PROXY_PREF_NOT_CLEARED
;
160 prefs
->ClearPref(proxy_config::prefs::kProxy
);
161 return PROXY_PREF_CLEARED_PAC_GOOGLEZIP
;
164 return PROXY_PREF_NOT_CLEARED
;
167 DataReductionProxyChromeSettings::DataReductionProxyChromeSettings()
168 : data_reduction_proxy::DataReductionProxySettings() {
171 DataReductionProxyChromeSettings::~DataReductionProxyChromeSettings() {
174 void DataReductionProxyChromeSettings::Shutdown() {
175 data_reduction_proxy_service()->Shutdown();
178 void DataReductionProxyChromeSettings::InitDataReductionProxySettings(
179 data_reduction_proxy::DataReductionProxyIOData
* io_data
,
180 PrefService
* profile_prefs
,
181 net::URLRequestContextGetter
* request_context_getter
,
182 scoped_ptr
<data_reduction_proxy::DataStore
> store
,
183 const scoped_refptr
<base::SingleThreadTaskRunner
>& ui_task_runner
,
184 const scoped_refptr
<base::SequencedTaskRunner
>& db_task_runner
) {
185 #if defined(OS_ANDROID) || defined(OS_IOS)
186 // On mobile we write Data Reduction Proxy prefs directly to the pref service.
187 // On desktop we store Data Reduction Proxy prefs in memory, writing to disk
188 // every 60 minutes and on termination. Shutdown hooks must be added for
189 // Android and iOS in order for non-zero delays to be supported.
190 // (http://crbug.com/408264)
191 base::TimeDelta commit_delay
= base::TimeDelta();
193 base::TimeDelta commit_delay
= base::TimeDelta::FromMinutes(60);
196 scoped_ptr
<data_reduction_proxy::DataReductionProxyService
> service
=
197 make_scoped_ptr(new data_reduction_proxy::DataReductionProxyService(
198 this, profile_prefs
, request_context_getter
, store
.Pass(),
199 ui_task_runner
, io_data
->io_task_runner(), db_task_runner
,
201 data_reduction_proxy::DataReductionProxySettings::
202 InitDataReductionProxySettings(profile_prefs
, io_data
, service
.Pass());
203 io_data
->SetDataReductionProxyService(
204 data_reduction_proxy_service()->GetWeakPtr());
206 data_reduction_proxy::DataReductionProxySettings::
207 SetCallbackToRegisterSyntheticFieldTrial(
209 &ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial
));
210 // TODO(bengr): Remove after M46. See http://crbug.com/445599.
211 MigrateDataReductionProxyOffProxyPrefs(profile_prefs
);
215 data_reduction_proxy::Client
DataReductionProxyChromeSettings::GetClient() {
216 #if defined(OS_ANDROID)
217 return data_reduction_proxy::Client::CHROME_ANDROID
;
218 #elif defined(OS_IOS)
219 return data_reduction_proxy::Client::CHROME_IOS
;
220 #elif defined(OS_MACOSX)
221 return data_reduction_proxy::Client::CHROME_MAC
;
222 #elif defined(OS_CHROMEOS)
223 return data_reduction_proxy::Client::CHROME_CHROMEOS
;
224 #elif defined(OS_LINUX)
225 return data_reduction_proxy::Client::CHROME_LINUX
;
226 #elif defined(OS_WIN)
227 return data_reduction_proxy::Client::CHROME_WINDOWS
;
228 #elif defined(OS_FREEBSD)
229 return data_reduction_proxy::Client::CHROME_FREEBSD
;
230 #elif defined(OS_OPENBSD)
231 return data_reduction_proxy::Client::CHROME_OPENBSD
;
232 #elif defined(OS_SOLARIS)
233 return data_reduction_proxy::Client::CHROME_SOLARIS
;
234 #elif defined(OS_QNX)
235 return data_reduction_proxy::Client::CHROME_QNX
;
237 return data_reduction_proxy::Client::UNKNOWN
;