1 // Copyright 2013 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_settings_android.h"
7 #include "base/android/build_info.h"
8 #include "base/android/jni_android.h"
9 #include "base/android/jni_string.h"
10 #include "base/base64.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_member.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/prefs/scoped_user_pref_update.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/prefs/proxy_prefs.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "jni/DataReductionProxySettings_jni.h"
28 #include "net/base/auth.h"
29 #include "net/base/host_port_pair.h"
30 #include "net/base/load_flags.h"
31 #include "net/base/net_errors.h"
32 #include "net/url_request/url_fetcher.h"
33 #include "net/url_request/url_fetcher_delegate.h"
34 #include "net/url_request/url_request_status.h"
37 using base::android::CheckException;
38 using base::android::ConvertJavaStringToUTF8;
39 using base::android::ConvertUTF16ToJavaString;
40 using base::android::ConvertUTF8ToJavaString;
41 using base::android::ScopedJavaLocalRef;
42 using base::StringPrintf;
46 // The C++ definition of enum SpdyProxyAuthState defined in
47 // tools/histograms/histograms.xml.
48 // New values should be added at the end before |NUM_SPDY_PROXY_AUTH_STATE|.
51 SPDY_PROXY_AUTH_ON_AT_STARTUP,
52 SPDY_PROXY_AUTH_ON_BY_USER,
53 SPDY_PROXY_AUTH_OFF_BY_USER,
54 // Used by UMA histograms and should always be the last value.
55 NUM_SPDY_PROXY_AUTH_STATE
58 // Generates a PAC proxy string component, including trailing semicolon and
59 // space, for |origin|. Eg:
60 // "http://foo.com/" -> "PROXY foo.com:80; "
61 // "https://bar.com:10443" -> "HTTPS bar.coom:10443; "
62 // The returned strings are suitable for concatenating into a PAC string.
63 // If |origin| is empty, returns an empty string.
64 std::string ProtocolAndHostForPACString(const std::string& origin) {
68 GURL url = GURL(origin);
69 std::string protocol = url.SchemeIsSecure() ? "HTTPS " : "PROXY ";
70 return protocol + net::HostPortPair::FromURL(url).ToString() + "; ";
75 DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid(
76 JNIEnv* env, jobject obj): DataReductionProxySettings() {
79 DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid() {}
81 DataReductionProxySettingsAndroid::~DataReductionProxySettingsAndroid() {}
83 void DataReductionProxySettingsAndroid::InitDataReductionProxySettings(
86 DataReductionProxySettings::InitDataReductionProxySettings();
89 void DataReductionProxySettingsAndroid::BypassHostPattern(
90 JNIEnv* env, jobject obj, jstring pattern) {
91 DataReductionProxySettings::AddHostPatternToBypass(
92 ConvertJavaStringToUTF8(env, pattern));
94 void DataReductionProxySettingsAndroid::BypassURLPattern(
95 JNIEnv* env, jobject obj, jstring pattern) {
96 AddURLPatternToBypass(ConvertJavaStringToUTF8(env, pattern));
99 void DataReductionProxySettingsAndroid::AddURLPatternToBypass(
100 const std::string& pattern) {
101 pac_bypass_rules_.push_back(
102 StringPrintf("shExpMatch(%s, '%s')", "url", pattern.c_str()));
105 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyAllowed(
106 JNIEnv* env, jobject obj) {
107 return DataReductionProxySettings::IsDataReductionProxyAllowed();
110 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAllowed(
111 JNIEnv* env, jobject obj) {
112 return DataReductionProxySettings::IsDataReductionProxyPromoAllowed();
115 ScopedJavaLocalRef<jstring>
116 DataReductionProxySettingsAndroid::GetDataReductionProxyOrigin(
117 JNIEnv* env, jobject obj) {
118 return ConvertUTF8ToJavaString(
119 env, DataReductionProxySettings::GetDataReductionProxyOrigin());
122 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyEnabled(
123 JNIEnv* env, jobject obj) {
124 return DataReductionProxySettings::IsDataReductionProxyEnabled();
127 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyManaged(
128 JNIEnv* env, jobject obj) {
129 return DataReductionProxySettings::IsDataReductionProxyManaged();
132 void DataReductionProxySettingsAndroid::SetDataReductionProxyEnabled(
136 DataReductionProxySettings::SetDataReductionProxyEnabled(enabled);
139 jlong DataReductionProxySettingsAndroid::GetDataReductionLastUpdateTime(
140 JNIEnv* env, jobject obj) {
141 return DataReductionProxySettings::GetDataReductionLastUpdateTime();
144 base::android::ScopedJavaLocalRef<jobject>
145 DataReductionProxySettingsAndroid::GetContentLengths(JNIEnv* env,
147 int64 original_content_length;
148 int64 received_content_length;
149 int64 last_update_internal;
150 DataReductionProxySettings::GetContentLengths(
151 spdyproxy::kNumDaysInHistorySummary,
152 &original_content_length,
153 &received_content_length,
154 &last_update_internal);
156 return Java_ContentLengths_create(env,
157 original_content_length,
158 received_content_length);
161 jboolean DataReductionProxySettingsAndroid::IsAcceptableAuthChallenge(
166 scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
167 auth_info->realm = ConvertJavaStringToUTF8(env, realm);
168 auth_info->challenger =
169 net::HostPortPair::FromString(ConvertJavaStringToUTF8(env, host));
170 return DataReductionProxySettings::IsAcceptableAuthChallenge(auth_info.get());
173 ScopedJavaLocalRef<jstring>
174 DataReductionProxySettingsAndroid::GetTokenForAuthChallenge(JNIEnv* env,
178 scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo);
179 auth_info->realm = ConvertJavaStringToUTF8(env, realm);
180 auth_info->challenger =
181 net::HostPortPair::FromString(ConvertJavaStringToUTF8(env, host));
183 // If an empty string != null in Java, then here we should test for the
184 // token being empty and return a java null.
185 return ConvertUTF16ToJavaString(env,
186 DataReductionProxySettings::GetTokenForAuthChallenge(auth_info.get()));
189 ScopedJavaLocalRef<jlongArray>
190 DataReductionProxySettingsAndroid::GetDailyOriginalContentLengths(
191 JNIEnv* env, jobject obj) {
192 return GetDailyContentLengths(env, prefs::kDailyHttpOriginalContentLength);
195 ScopedJavaLocalRef<jlongArray>
196 DataReductionProxySettingsAndroid::GetDailyReceivedContentLengths(
197 JNIEnv* env, jobject obj) {
198 return GetDailyContentLengths(env, prefs::kDailyHttpReceivedContentLength);
202 bool DataReductionProxySettingsAndroid::Register(JNIEnv* env) {
203 bool register_natives_impl_result = RegisterNativesImpl(env);
204 return register_natives_impl_result;
207 // Metrics methods -- obsolete; see crbug/241518
208 void DataReductionProxySettingsAndroid::RecordDataReductionInit() {
209 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State", CHROME_STARTUP,
210 NUM_SPDY_PROXY_AUTH_STATE);
213 void DataReductionProxySettingsAndroid::AddDefaultProxyBypassRules() {
214 DataReductionProxySettings::AddDefaultProxyBypassRules();
216 // TODO(bengr): See http://crbug.com/169959. For some reason the data
217 // reduction proxy is breaking the omnibox SearchProvider. Remove this rule
218 // when this is fixed.
219 AddURLPatternToBypass("http://www.google.com/complete/search*");
222 void DataReductionProxySettingsAndroid::SetProxyConfigs(bool enabled,
224 // Keys duplicated from proxy_config_dictionary.cc
225 // TODO(bengr): Move these to proxy_config_dictionary.h and reuse them here.
226 const char kProxyMode[] = "mode";
227 const char kProxyPacURL[] = "pac_url";
228 const char kProxyBypassList[] = "bypass_list";
230 LogProxyState(enabled, at_startup);
232 PrefService* prefs = GetOriginalProfilePrefs();
234 DictionaryPrefUpdate update(prefs, prefs::kProxy);
235 base::DictionaryValue* dict = update.Get();
236 // TODO(marq): All of the UMA in here are obsolete.
238 // Convert to a data URI and update the PAC settings.
239 std::string base64_pac;
240 base::Base64Encode(GetProxyPacScript(), &base64_pac);
242 dict->SetString(kProxyPacURL,
243 "data:application/x-ns-proxy-autoconfig;base64," +
245 dict->SetString(kProxyMode,
246 ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
247 dict->SetString(kProxyBypassList, JoinString(BypassRules(), ", "));
250 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
251 SPDY_PROXY_AUTH_ON_AT_STARTUP,
252 NUM_SPDY_PROXY_AUTH_STATE);
253 } else if (!DataReductionProxySettings::HasTurnedOn()) {
254 // SPDY proxy auth is turned on by user action for the first time in
256 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
257 SPDY_PROXY_AUTH_ON_BY_USER,
258 NUM_SPDY_PROXY_AUTH_STATE);
259 DataReductionProxySettings::SetHasTurnedOn();
262 dict->SetString(kProxyMode, ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
263 dict->SetString(kProxyPacURL, "");
264 dict->SetString(kProxyBypassList, "");
266 if (!at_startup && !DataReductionProxySettings::HasTurnedOff()) {
267 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
268 SPDY_PROXY_AUTH_OFF_BY_USER,
269 NUM_SPDY_PROXY_AUTH_STATE);
270 DataReductionProxySettings::SetHasTurnedOff();
275 ScopedJavaLocalRef<jlongArray>
276 DataReductionProxySettingsAndroid::GetDailyContentLengths(
277 JNIEnv* env, const char* pref_name) {
278 jlongArray result = env->NewLongArray(spdyproxy::kNumDaysInHistory);
280 DataReductionProxySettings::ContentLengthList lengths =
281 DataReductionProxySettings::GetDailyContentLengths(pref_name);
283 if (!lengths.empty()) {
284 DCHECK_EQ(lengths.size(), spdyproxy::kNumDaysInHistory);
285 env->SetLongArrayRegion(result, 0, lengths.size(), &lengths[0]);
286 return ScopedJavaLocalRef<jlongArray>(env, result);
289 return ScopedJavaLocalRef<jlongArray>(env, result);
292 // TODO(bengr): Replace with our own ProxyResolver.
293 std::string DataReductionProxySettingsAndroid::GetProxyPacScript() {
294 // Compose the PAC-only bypass code; these will be URL patterns that
295 // are matched by regular expression. Host bypasses are handled outside
296 // of the PAC file using the regular proxy bypass list configs.
297 std::string bypass_clause =
298 "(" + JoinString(pac_bypass_rules_, ") || (") + ")";
300 // Generate a proxy PAC that falls back to direct loading when the proxy is
301 // unavailable and only process HTTP traffic.
303 std::string proxy_host = ProtocolAndHostForPACString(
304 DataReductionProxySettings::GetDataReductionProxyOrigin());
305 std::string fallback_host = ProtocolAndHostForPACString(
306 DataReductionProxySettings::GetDataReductionProxyFallback());
307 std::string pac = "function FindProxyForURL(url, host) {"
308 " if (" + bypass_clause + ") {"
311 " if (url.substring(0, 5) == 'http:') {"
312 " return '" + proxy_host + fallback_host + "DIRECT';"
319 // Used by generated jni code.
320 static jint Init(JNIEnv* env, jobject obj) {
321 DataReductionProxySettingsAndroid* settings =
322 new DataReductionProxySettingsAndroid(env, obj);
323 return reinterpret_cast<jint>(settings);