- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / spdyproxy / data_reduction_proxy_settings_android.cc
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.
4
5 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h"
6
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"
35 #include "url/gurl.h"
36
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;
43
44 namespace {
45
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|.
49 enum {
50   CHROME_STARTUP,
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
56 };
57
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) {
65   if (origin.empty()) {
66     return std::string();
67   }
68   GURL url = GURL(origin);
69   std::string protocol = url.SchemeIsSecure() ? "HTTPS "  : "PROXY ";
70   return protocol + net::HostPortPair::FromURL(url).ToString() + "; ";
71 }
72
73 }  // namespace
74
75 DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid(
76     JNIEnv* env, jobject obj): DataReductionProxySettings() {
77 }
78
79 DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid() {}
80
81 DataReductionProxySettingsAndroid::~DataReductionProxySettingsAndroid() {}
82
83 void DataReductionProxySettingsAndroid::InitDataReductionProxySettings(
84     JNIEnv* env,
85     jobject obj) {
86   DataReductionProxySettings::InitDataReductionProxySettings();
87 }
88
89 void DataReductionProxySettingsAndroid::BypassHostPattern(
90     JNIEnv* env, jobject obj, jstring pattern) {
91   DataReductionProxySettings::AddHostPatternToBypass(
92       ConvertJavaStringToUTF8(env, pattern));
93 }
94 void DataReductionProxySettingsAndroid::BypassURLPattern(
95     JNIEnv* env, jobject obj, jstring pattern) {
96   AddURLPatternToBypass(ConvertJavaStringToUTF8(env, pattern));
97 }
98
99 void DataReductionProxySettingsAndroid::AddURLPatternToBypass(
100     const std::string& pattern) {
101   pac_bypass_rules_.push_back(
102       StringPrintf("shExpMatch(%s, '%s')", "url", pattern.c_str()));
103 }
104
105 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyAllowed(
106     JNIEnv* env, jobject obj) {
107   return DataReductionProxySettings::IsDataReductionProxyAllowed();
108 }
109
110 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAllowed(
111     JNIEnv* env, jobject obj) {
112   return DataReductionProxySettings::IsDataReductionProxyPromoAllowed();
113 }
114
115 ScopedJavaLocalRef<jstring>
116 DataReductionProxySettingsAndroid::GetDataReductionProxyOrigin(
117     JNIEnv* env, jobject obj) {
118   return ConvertUTF8ToJavaString(
119       env, DataReductionProxySettings::GetDataReductionProxyOrigin());
120 }
121
122 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyEnabled(
123     JNIEnv* env, jobject obj) {
124   return DataReductionProxySettings::IsDataReductionProxyEnabled();
125 }
126
127 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyManaged(
128     JNIEnv* env, jobject obj) {
129   return DataReductionProxySettings::IsDataReductionProxyManaged();
130 }
131
132 void DataReductionProxySettingsAndroid::SetDataReductionProxyEnabled(
133     JNIEnv* env,
134     jobject obj,
135     jboolean enabled) {
136   DataReductionProxySettings::SetDataReductionProxyEnabled(enabled);
137 }
138
139 jlong DataReductionProxySettingsAndroid::GetDataReductionLastUpdateTime(
140     JNIEnv* env, jobject obj) {
141   return DataReductionProxySettings::GetDataReductionLastUpdateTime();
142 }
143
144 base::android::ScopedJavaLocalRef<jobject>
145 DataReductionProxySettingsAndroid::GetContentLengths(JNIEnv* env,
146                                                      jobject obj) {
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);
155
156   return Java_ContentLengths_create(env,
157                                     original_content_length,
158                                     received_content_length);
159 }
160
161 jboolean DataReductionProxySettingsAndroid::IsAcceptableAuthChallenge(
162     JNIEnv* env,
163     jobject obj,
164     jstring host,
165     jstring realm) {
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());
171 }
172
173 ScopedJavaLocalRef<jstring>
174 DataReductionProxySettingsAndroid::GetTokenForAuthChallenge(JNIEnv* env,
175                                                             jobject obj,
176                                                             jstring host,
177                                                             jstring realm) {
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));
182
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()));
187  }
188
189 ScopedJavaLocalRef<jlongArray>
190 DataReductionProxySettingsAndroid::GetDailyOriginalContentLengths(
191     JNIEnv* env, jobject obj) {
192   return GetDailyContentLengths(env, prefs::kDailyHttpOriginalContentLength);
193 }
194
195 ScopedJavaLocalRef<jlongArray>
196 DataReductionProxySettingsAndroid::GetDailyReceivedContentLengths(
197     JNIEnv* env, jobject obj) {
198   return GetDailyContentLengths(env, prefs::kDailyHttpReceivedContentLength);
199 }
200
201 // static
202 bool DataReductionProxySettingsAndroid::Register(JNIEnv* env) {
203   bool register_natives_impl_result = RegisterNativesImpl(env);
204   return register_natives_impl_result;
205 }
206
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);
211 }
212
213 void DataReductionProxySettingsAndroid::AddDefaultProxyBypassRules() {
214    DataReductionProxySettings::AddDefaultProxyBypassRules();
215
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*");
220 }
221
222 void DataReductionProxySettingsAndroid::SetProxyConfigs(bool enabled,
223                                                         bool at_startup) {
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";
229
230   LogProxyState(enabled, at_startup);
231
232   PrefService* prefs = GetOriginalProfilePrefs();
233   DCHECK(prefs);
234   DictionaryPrefUpdate update(prefs, prefs::kProxy);
235   base::DictionaryValue* dict = update.Get();
236   // TODO(marq): All of the UMA in here are obsolete.
237   if (enabled) {
238     // Convert to a data URI and update the PAC settings.
239     std::string base64_pac;
240     base::Base64Encode(GetProxyPacScript(), &base64_pac);
241
242     dict->SetString(kProxyPacURL,
243                     "data:application/x-ns-proxy-autoconfig;base64," +
244                     base64_pac);
245     dict->SetString(kProxyMode,
246                     ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
247     dict->SetString(kProxyBypassList, JoinString(BypassRules(), ", "));
248
249     if (at_startup) {
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
255       // this session.
256       UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
257                                 SPDY_PROXY_AUTH_ON_BY_USER,
258                                 NUM_SPDY_PROXY_AUTH_STATE);
259       DataReductionProxySettings::SetHasTurnedOn();
260     }
261   } else {
262     dict->SetString(kProxyMode, ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
263     dict->SetString(kProxyPacURL, "");
264     dict->SetString(kProxyBypassList, "");
265
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();
271     }
272   }
273 }
274
275 ScopedJavaLocalRef<jlongArray>
276 DataReductionProxySettingsAndroid::GetDailyContentLengths(
277     JNIEnv* env,  const char* pref_name) {
278   jlongArray result = env->NewLongArray(spdyproxy::kNumDaysInHistory);
279
280   DataReductionProxySettings::ContentLengthList lengths  =
281       DataReductionProxySettings::GetDailyContentLengths(pref_name);
282
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);
287   }
288
289   return ScopedJavaLocalRef<jlongArray>(env, result);
290 }
291
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_, ") || (") + ")";
299
300   // Generate a proxy PAC that falls back to direct loading when the proxy is
301   // unavailable and only process HTTP traffic.
302
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 + ") {"
309       "    return 'DIRECT';"
310       "  } "
311       "  if (url.substring(0, 5) == 'http:') {"
312       "    return '" + proxy_host + fallback_host + "DIRECT';"
313       "  }"
314       "  return 'DIRECT';"
315       "}";
316   return pac;
317 }
318
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);
324 }