Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(866)

Side by Side Diff: chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc

Issue 23458016: Added probe to determine if data reduction proxy can be used (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/command_line.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/prefs/proxy_prefs.h"
21 #include "chrome/browser/prefs/scoped_user_pref_update.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "jni/DataReductionProxySettingsAndroid_jni.h"
27 #include "net/base/load_flags.h"
28 #include "net/base/net_errors.h"
29 #include "net/url_request/url_fetcher.h"
30 #include "net/url_request/url_fetcher_delegate.h"
31 #include "net/url_request/url_request_status.h"
32 #include "url/gurl.h"
33
34 using base::android::CheckException;
35 using base::android::ConvertJavaStringToUTF8;
36 using base::android::ConvertUTF8ToJavaString;
37 using base::android::ScopedJavaLocalRef;
38 using base::StringPrintf;
39
40
41 namespace {
42
43 // The c++ definition of enum SpdyProxyAuthState defined in
44 // tools/histograms/histograms.xml.
45 enum {
46 CHROME_STARTUP,
47 SPDY_PROXY_AUTH_ON_AT_STARTUP,
48 SPDY_PROXY_AUTH_ON_BY_USER,
49 SPDY_PROXY_AUTH_OFF_BY_USER,
50 // Used by UMA histograms and should always be the last value.
51 NUM_SPDY_PROXY_AUTH_STATE
52 };
53
54 // SpdyProxyValue switch.
55 const char kSpdyProxyValueSwitch[] = "spdy-proxy-auth-value";
56
57 const unsigned int kNumDaysInHistory = 60;
58 const unsigned int kNumDaysInHistorySummary = 30;
59
60 } // namespace
61
62 DataReductionProxySettingsAndroid::DataReductionProxySettingsAndroid(
63 JNIEnv* env, jobject obj) :
64 has_turned_on_(false),
65 has_turned_off_(false),
66 disabled_by_carrier_(false),
67 enabled_by_user_(false) {
68 AddDefaultProxyBypassRules();
69 net::NetworkChangeNotifier::AddIPAddressObserver(this);
70 }
71
72 DataReductionProxySettingsAndroid::~DataReductionProxySettingsAndroid() {
73 }
74
75 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyAvailable(
76 JNIEnv* env, jobject obj) {
77 return IsDataReductionProxyAvailable();
78 }
79
80 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAvailable(
81 JNIEnv* env, jobject obj) {
82 return IsDataReductionProxyPromoAvailable();
83 }
84
85 ScopedJavaLocalRef<jstring>
86 DataReductionProxySettingsAndroid::GetDataReductionProxyOrigin(
87 JNIEnv* env, jobject obj) {
88 if (!IsDataReductionProxyAvailable())
89 ConvertUTF8ToJavaString(env, std::string());
90 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
91 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) {
92 return ConvertUTF8ToJavaString(env, command_line.GetSwitchValueASCII(
93 switches::kSpdyProxyAuthOrigin));
94 }
95 #if defined(SPDY_PROXY_AUTH_ORIGIN)
96 return ConvertUTF8ToJavaString(env, SPDY_PROXY_AUTH_ORIGIN);
97 #endif
98 return ConvertUTF8ToJavaString(env, std::string());
99 }
100
101 ScopedJavaLocalRef<jstring>
102 DataReductionProxySettingsAndroid::GetDataReductionProxyValue(
103 JNIEnv* env, jobject obj) {
104 if (!IsDataReductionProxyAvailable())
105 return ConvertUTF8ToJavaString(env, std::string());
106 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
107 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) {
108 // If an origin is provided via a switch, then only consider the value
109 // that is provided by a switch. Do not use the preprocessor constant.
110 if (command_line.HasSwitch(kSpdyProxyValueSwitch)) {
111 return ConvertUTF8ToJavaString(env,
112 command_line.GetSwitchValueASCII(kSpdyProxyValueSwitch));
113 }
114 }
115 #if defined(SPDY_PROXY_AUTH_VALUE)
116 return ConvertUTF8ToJavaString(env, SPDY_PROXY_AUTH_VALUE);
117 #endif
118 return ConvertUTF8ToJavaString(env, std::string());
119 }
120
121 jlong DataReductionProxySettingsAndroid::GetDataReductionLastUpdateTime(
122 JNIEnv* env, jobject obj) {
123 PrefService* local_state = g_browser_process->local_state();
124 int64 last_update_internal =
125 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
126 base::Time last_update = base::Time::FromInternalValue(last_update_internal);
127 return static_cast<int64>(last_update.ToJsTime());
128 }
129
130 base::android::ScopedJavaLocalRef<jobject>
131 DataReductionProxySettingsAndroid::GetContentLengths(JNIEnv* env,
132 jobject obj) {
133 int64 original_content_length;
134 int64 received_content_length;
135 int64 last_update_internal;
136 GetContentLengths(kNumDaysInHistorySummary, &original_content_length,
137 &received_content_length, &last_update_internal);
138
139 return Java_ContentLengths_create(env,
140 original_content_length,
141 received_content_length);
142 }
143
144 void DataReductionProxySettingsAndroid::AddDefaultProxyBypassRules() {
145 // localhost
146 AddHostToBypass("localhost");
147 AddHostPatternToBypass("localhost.*");
148 AddHostToBypass("127.0.0.1");
149
150 // BUG(169959): For some reason DataReductionProxy is breaking the omnibox
nyquist 2013/09/04 02:20:15 TODO(bengr): ...blah... See: http://crbug.com/1699
bengr 2013/09/05 02:03:49 Done.
151 // SearchProvider. Remove this rule when this is fixed.
152 AddURLSubstringToBypass(
153 "http://www.google.com/complete/search", 0, 37);
154
155 // http://freezone.google.com/*
156 // http://www.freezone.google.com/*
157 // http://accounts.freezone.google.com/*
158 // http://mail.freezone.google.com/*
159 // http://plus.freezone.google.com/*
160 // http://search.freezone.google.com/*
161 AddHostPatternToBypass("*freezone.google.com");
nyquist 2013/09/04 02:20:15 Seems like this pattern might match too much. Coul
bengr 2013/09/05 02:03:49 I've added a TODO. On 2013/09/04 02:20:15, nyquis
162 // http://freezone.googleusercontent.com/*
163 AddHostPatternToBypass("freezone.googleusercontent.com");
164 // http://g.co/gms/*
165 AddURLPatternToBypass("http://g.co/gms/*");
166 // http://g.co/freezone*
167 AddURLPatternToBypass("http://g.co/freezone*");
168 // Check for proxy availability
169 AddURLPatternToBypass(GetProxyCheckURL());
170 }
171
172 void DataReductionProxySettingsAndroid::AddURLPatternToBypass(
173 const std::string& pattern) {
174 AddPatternToBypass("url", pattern);
175 }
176
177 void DataReductionProxySettingsAndroid::AddHostPatternToBypass(
178 const std::string& pattern) {
179 AddPatternToBypass("host", pattern);
180 }
181
182 void DataReductionProxySettingsAndroid::AddPatternToBypass(
183 const std::string& url_or_host,
184 const std::string& pattern) {
185 bypass_rules_.push_back(
186 StringPrintf("shExpMatch(%s, \"%s\")",
187 url_or_host.c_str(), pattern.c_str()));
188 }
189
190 void DataReductionProxySettingsAndroid::AddHostToBypass(
191 const std::string& host) {
192 bypass_rules_.push_back(
193 StringPrintf("host == \"%s\"", host.c_str()));
194 }
195
196 void DataReductionProxySettingsAndroid::AddURLSubstringToBypass(
197 const std::string& url,
198 int from,
199 int to) {
200 bypass_rules_.push_back(
201 StringPrintf("url.substring(%d, %d) == \"%s\"", from, to, url.c_str()));
202 }
203
204 bool DataReductionProxySettingsAndroid::IsDataReductionProxyAvailable() {
205 return (base::FieldTrialList::FindFullName(
206 "DataCompressionProxyRollout") == "Enabled");
207 }
208
209 bool DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAvailable() {
210 return (IsDataReductionProxyAvailable() && base::FieldTrialList::FindFullName(
211 "DataCompressionProxyPromoVisibility") == "Enabled");
212 }
213
214 std::string DataReductionProxySettingsAndroid::GetProxyPacScript() {
215 std::string bypass_clause = "(" + JoinString(bypass_rules_, ") || (") + ")";
216
217 // We want to fall back to direct loading when the proxy is unavailable and
218 // only process HTTP traffic, so we concoct a PAC configuration
219 // accordingly. (With a statically configured proxy, proxy failures will
220 // simply result in a connection error presented to users.)
221
222 std::string pac = "function FindProxyForURL(url, host) {"
223 " if (" + bypass_clause + ") {"
224 " return \"DIRECT\";"
225 " } "
226 " if (url.substring(0, 5) == \"http:\") {"
227 " return \"HTTPS " + GetDataReductionProxyOriginHostPort() +
228 "; DIRECT\";"
229 " }"
230 " return \"DIRECT\";"
231 "}";
232 return pac;
233 }
234
235 PrefService* DataReductionProxySettingsAndroid::GetPrefService() {
236 return g_browser_process->profile_manager()->GetDefaultProfile()->
237 GetOriginalProfile()->GetPrefs();
238 }
239
240 std::string
241 DataReductionProxySettingsAndroid::GetDataReductionProxyOriginHostPort() {
242 std::string spdy_proxy = "";
243
244 PrefService* local_state = g_browser_process->local_state();
245 if (local_state->HasPrefPath(prefs::kSpdyProxyAuthOrigin)) {
246 spdy_proxy = local_state->GetString(prefs::kSpdyProxyAuthOrigin);
247 } else {
248 #if defined(SPDY_PROXY_AUTH_ORIGIN)
249 spdy_proxy = SPDY_PROXY_AUTH_ORIGIN;
250 #endif
251 }
252
253 if (!spdy_proxy.empty()) {
254 // Remove a trailing slash from the proxy string if one exists as well as
255 // leading HTTPS scheme.
256 unsigned len = spdy_proxy.size();
257 if (len > 0 && spdy_proxy[len - 1] == '/') {
258 spdy_proxy.erase(len - 1, 1);
259 }
260 std::string https_scheme("https://");
261 if (len > https_scheme.length() &&
262 spdy_proxy.compare(0, https_scheme.length(), https_scheme) == 0) {
263 spdy_proxy.erase(0, https_scheme.length());
264 }
265 } else {
266 DLOG(ERROR) << "A SPDY proxy has not been set.";
267 }
268 return spdy_proxy;
269 }
270
271 void DataReductionProxySettingsAndroid::ResetDataReductionStatistics() {
272 PrefService* prefs = g_browser_process->local_state();
273 if (!prefs)
274 return;
275 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
276 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
277 original_update->Clear();
278 received_update->Clear();
279 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
280 original_update->AppendString(base::Int64ToString(0));
281 received_update->AppendString(base::Int64ToString(0));
282 }
283 }
284
285 void DataReductionProxySettingsAndroid::InitDataReductionProxySettings(
286 JNIEnv* env,
287 jobject obj) {
288 // Disable the proxy is it's not meant to be available.
289 if (!IsDataReductionProxyAvailable()) return;
290
291 PrefService* prefs = GetPrefService();
292 CommandLine& command_line = *CommandLine::ForCurrentProcess();
293 bool spdy_proxy_enabled = prefs->GetBoolean(prefs::kSpdyProxyAuthEnabled);
294
295 // Setting the kEnableSpdyProxyAuth switch has the same effect as enabling
296 // the feature via settings, in that once set, the preference will be sticky
297 // across instances of Chrome. Disabling the feature can only be done through
298 // the settings menu.
299 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State", CHROME_STARTUP,
300 NUM_SPDY_PROXY_AUTH_STATE);
301 if (command_line.HasSwitch(switches::kEnableSpdyProxyAuth) ||
302 spdy_proxy_enabled) {
303 SetDataReductionProxyEnabled(NULL, NULL, true);
304 } else {
305 LOG(WARNING) << "SPDY proxy OFF at startup.";
nyquist 2013/09/04 02:20:15 DLOG?
bengr 2013/09/05 02:03:49 We need this to be a WARNING so that it is include
306 }
307 }
308
309 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyEnabled(
310 JNIEnv* env, jobject obj) {
311 return GetPrefService()->GetBoolean(prefs::kSpdyProxyAuthEnabled);
312 }
313
314 void DataReductionProxySettingsAndroid::SetDataReductionProxyEnabled(
315 JNIEnv* env,
316 jobject obj,
317 jboolean enabled) {
318
319 // Disable the proxy is it's not meant to be available.
320 if (!IsDataReductionProxyAvailable()) return;
321
322 // Check if the proxy has been disabled explicitly by the carrier.
323 CheckDataReductionProxyIsAvailable(GetProxyCheckURL());
324
325 PrefService* prefs = GetPrefService();
326
327 prefs->SetBoolean(prefs::kSpdyProxyAuthEnabled, enabled);
328
329 if (enabled && !prefs->GetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore)) {
330 prefs->SetBoolean(prefs::kSpdyProxyAuthWasEnabledBefore, true);
331 ResetDataReductionStatistics();
332 }
333
334 std::string spdy_proxy_origin = GetDataReductionProxyOriginHostPort();
335
336 // Configure use of the data reduction proxy if it is enabled and the proxy
337 // origin is non-empty.
338 enabled_by_user_= enabled && spdy_proxy_origin != "";
339 SetProxyPac(enabled_by_user_, !env);
340
341 }
342
343 void DataReductionProxySettingsAndroid::SetProxyPac(bool enable_spdy_proxy,
344 bool at_startup) {
345 PrefService* prefs = GetPrefService();
346 DCHECK(prefs);
347 // Keys duplicated from proxy_config_dictionary.cc
nyquist 2013/09/04 02:20:15 Add TODO about moving them to proxy_config_diction
bengr 2013/09/05 02:03:49 Done.
348 const char kProxyMode[] = "mode";
349 const char kProxyPacURL[] = "pac_url";
350 const char kAtStartup[] = "at startup";
351 const char kByUser[] = "by user action";
352
353 DictionaryPrefUpdate update(prefs, prefs::kProxy);
354 DictionaryValue* dict = update.Get();
355 if (enable_spdy_proxy) {
356 LOG(WARNING) << "SPDY proxy ON " << (at_startup ? kAtStartup : kByUser);
357 // Convert to a data URI and update the PAC settings.
358 std::string base64_pac;
359 base::Base64Encode(GetProxyPacScript(), &base64_pac);
360
361 dict->SetString(kProxyPacURL,
362 "data:application/x-ns-proxy-autoconfig;base64," +
363 base64_pac);
364 dict->SetString(kProxyMode,
365 ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT));
366
367 if (at_startup) {
368 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
369 SPDY_PROXY_AUTH_ON_AT_STARTUP,
370 NUM_SPDY_PROXY_AUTH_STATE);
371 } else if (!has_turned_on_) {
372 // SPDY proxy auth is turned on by user action for the first time in
373 // this session.
374 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
375 SPDY_PROXY_AUTH_ON_BY_USER,
376 NUM_SPDY_PROXY_AUTH_STATE);
377 has_turned_on_ = true;
378 }
379 } else {
380 LOG(WARNING) << "SPDY proxy OFF " << (at_startup ? kAtStartup : kByUser);
381 dict->SetString(kProxyMode, ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
382 dict->SetString(kProxyPacURL, "");
383
384 if (!at_startup && !has_turned_off_) {
385 UMA_HISTOGRAM_ENUMERATION("SpdyProxyAuth.State",
386 SPDY_PROXY_AUTH_OFF_BY_USER,
387 NUM_SPDY_PROXY_AUTH_STATE);
388 has_turned_off_ = true;
389 }
390 }
391 }
392
393 void DataReductionProxySettingsAndroid::OnIPAddressChanged() {
394 CheckDataReductionProxyIsAvailable(GetProxyCheckURL());
395 }
396
397 void DataReductionProxySettingsAndroid::CheckDataReductionProxyIsAvailable(
398 std::string url) {
399 fetcher_.reset(net::URLFetcher::Create(0, GURL(url),
400 net::URLFetcher::GET, this));
401 fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
402 net::LOAD_IGNORE_ALL_CERT_ERRORS);
403 Profile* profile = g_browser_process->profile_manager()->
404 GetDefaultProfile();
405 fetcher_->SetRequestContext(profile->GetRequestContext());
406 // Configure to max_retries at most kMaxRetries times for 5xx errors.
407 static const int kMaxRetries = 5;
408 fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
409 fetcher_->Start();
410 }
411
412 void DataReductionProxySettingsAndroid::OnURLFetchComplete(
413 const net::URLFetcher* source) {
414 net::URLRequestStatus status = source->GetStatus();
415 if (status.status() == net::URLRequestStatus::FAILED &&
416 status.error() == net::ERR_INTERNET_DISCONNECTED) {
417 return;
418 }
419
420 std::string response;
421 source->GetResponseAsString(&response);
422
423 if ("OK" == response.substr(0, 2)) {
424 DVLOG(1) << "The data reduction proxy is not blocked.";
425
426 // The user enabled the proxy, but sometime previously in the session,
427 // the carrier had disabled the proxy. Now that the carrier is enabling
428 // it, configure it to the user's desires.
429 if (enabled_by_user_ && disabled_by_carrier_)
430 SetProxyPac(true, false);
431 disabled_by_carrier_ = false;
432 return;
433 }
434 DVLOG(1) << "The data reduction proxy is blocked.";
435 // Disable the proxy.
436 if (enabled_by_user_ && !disabled_by_carrier_)
437 SetProxyPac(false, false);
438 disabled_by_carrier_ = true;
439 }
440
441 std::string DataReductionProxySettingsAndroid::GetProxyCheckURL() {
442 std::string origin = "http://" + GetDataReductionProxyOriginHostPort();
443 GURL gurl(origin);
444 return gurl.scheme() + "://enabled." + gurl.host() + gurl.path() + "connect";
445 }
446
447 void DataReductionProxySettingsAndroid::CheckDataReductionProxy(
448 JNIEnv* env, jobject obj) {
449 CheckDataReductionProxyIsAvailable(GetProxyCheckURL());
450 }
451
452 ScopedJavaLocalRef<jlongArray>
453 DataReductionProxySettingsAndroid::GetDailyContentLengths(
454 JNIEnv* env, const char* pref_name) {
455 jlongArray result = env->NewLongArray(kNumDaysInHistory);
456 PrefService* local_state = g_browser_process->local_state();
457 if (!local_state)
458 return ScopedJavaLocalRef<jlongArray>(env, result);
459
460 const ListValue* list_value = local_state->GetList(pref_name);
461 if (list_value->GetSize() != kNumDaysInHistory)
462 return ScopedJavaLocalRef<jlongArray>(env, result);
463
464 jlong jval[kNumDaysInHistory];
465 for (size_t i = 0; i < kNumDaysInHistory; ++i) {
466 int64 val = 0;
467 std::string pref_value;
468 bool rv = list_value->GetString(i, &pref_value);
469 DCHECK(rv);
470 if (rv) {
471 rv = base::StringToInt64(pref_value, &val);
472 DCHECK(rv);
473 }
474 jval[i] = val;
475 }
476 env->SetLongArrayRegion(result, 0, kNumDaysInHistory, jval);
477 return ScopedJavaLocalRef<jlongArray>(env, result);
478 }
479
480 ScopedJavaLocalRef<jlongArray>
481 DataReductionProxySettingsAndroid::GetDailyOriginalContentLengths(
482 JNIEnv* env, jobject obj) {
483 return GetDailyContentLengths(env, prefs::kDailyHttpOriginalContentLength);
484 }
485
486 ScopedJavaLocalRef<jlongArray>
487 DataReductionProxySettingsAndroid::GetDailyReceivedContentLengths(
488 JNIEnv* env, jobject obj) {
489 return GetDailyContentLengths(env, prefs::kDailyHttpReceivedContentLength);
490 }
491
492 void DataReductionProxySettingsAndroid::GetContentLengths(
493 int days,
494 int64* original_content_length,
495 int64* received_content_length,
496 int64* last_update_time) {
497 PrefService* local_state = g_browser_process->local_state();
498 if (!local_state) {
499 *original_content_length = 0L;
500 *received_content_length = 0L;
501 *last_update_time = 0L;
502 return;
503 }
504
505 const ListValue* original_list =
506 local_state->GetList(prefs::kDailyHttpOriginalContentLength);
507 const ListValue* received_list =
508 local_state->GetList(prefs::kDailyHttpReceivedContentLength);
509 int64 last_update_internal =
510 local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
511
512 if (original_list->GetSize() != kNumDaysInHistory ||
513 received_list->GetSize() != kNumDaysInHistory) {
514 *original_content_length = 0L;
515 *received_content_length = 0L;
516 *last_update_time = 0L;
517 return;
518 }
519
520 int64 orig = 0L;
521 int64 recv = 0L;
522 DCHECK_GE(static_cast<int>(kNumDaysInHistory), days);
523 DCHECK_LE(0, days);
524 // We include days from the end of the list going backwards.
525 for (int i = 0; i < days; ++i) {
526 int read_index = kNumDaysInHistory - 1 - i;
527 std::string result("0");
528 int64 val;
529 if (original_list->GetString(read_index, &result)) {
530 if (base::StringToInt64(result, &val))
531 orig +=val;
532 else
533 DCHECK(false);
534 } else {
535 DCHECK(false);
536 }
537 if (received_list->GetString(read_index, &result)) {
538 if (base::StringToInt64(result, &val))
539 recv +=val;
540 else
541 DCHECK(false);
542 } else {
543 DCHECK(false);
544 }
545 }
546 *original_content_length = orig;
547 *received_content_length = recv;
548 *last_update_time = last_update_internal;
549 }
550
551 static jint Init(JNIEnv* env, jobject obj) {
552 DataReductionProxySettingsAndroid* settings =
553 new DataReductionProxySettingsAndroid(env, obj);
554 return reinterpret_cast<jint>(settings);
555 }
556
557 // static
558 bool DataReductionProxySettingsAndroid::Register(JNIEnv* env) {
559 bool register_natives_impl_result = RegisterNativesImpl(env);
560 return register_natives_impl_result;
561 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698