Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / net / spdyproxy / data_reduction_proxy_chrome_settings.cc
blob3c71fe4af7e94aaa5fb38df407ba68294bf349f7
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"
7 #include <string>
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"
36 namespace {
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)) {
50 return true;
53 return false;
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) {
70 DCHECK(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);
78 } // namespace
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(
86 PrefService* prefs) {
87 ProxyPrefMigrationResult proxy_pref_status =
88 MigrateDataReductionProxyOffProxyPrefsHelper(prefs);
89 UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ProxyPrefMigrationResult",
90 proxy_pref_status,
91 DataReductionProxyChromeSettings::PROXY_PREF_MAX);
94 DataReductionProxyChromeSettings::ProxyPrefMigrationResult
95 DataReductionProxyChromeSettings::MigrateDataReductionProxyOffProxyPrefsHelper(
96 PrefService* prefs) {
97 base::DictionaryValue* dict = (base::DictionaryValue*)prefs->GetUserPrefValue(
98 proxy_config::prefs::kProxy);
99 if (!dict)
100 return PROXY_PREF_NOT_CLEARED;
102 // Clear empty "proxy" dictionary created by a bug. See http://crbug/448172.
103 if (dict->empty()) {
104 prefs->ClearPref(proxy_config::prefs::kProxy);
105 return PROXY_PREF_CLEARED_EMPTY;
108 std::string mode;
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
119 // proxy pref.
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;
135 else
136 return PROXY_PREF_NOT_CLEARED;
138 prefs->ClearPref(proxy_config::prefs::kProxy);
139 return rv;
142 // Before M35, the DRP was configured using a PAC script base64 encoded into a
143 // PAC url.
144 if (ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT) == mode) {
145 std::string pac_url;
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();
192 #else
193 base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60);
194 #endif
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,
200 commit_delay));
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(
208 base::Bind(
209 &ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial));
210 // TODO(bengr): Remove after M46. See http://crbug.com/445599.
211 MigrateDataReductionProxyOffProxyPrefs(profile_prefs);
214 // static
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;
236 #else
237 return data_reduction_proxy::Client::UNKNOWN;
238 #endif