15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_android.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/system_properties.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_string.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sequenced_task_runner.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/stringprintf.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jni/ProxyChangeListener_jni.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config.h" 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_parse.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::AttachCurrentThread; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ConvertUTF8ToJavaString; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ConvertJavaStringToUTF8; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::CheckException; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ClearException; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ScopedJavaGlobalRef; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ProxyConfigServiceAndroid::GetPropertyCallback GetPropertyCallback; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns whether the provided string was successfully converted to a port. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ConvertStringToPort(const std::string& port, int* output) { 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu url::Component component(0, port.size()); 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int result = url::ParsePort(port.c_str(), component); 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (result == url::PORT_INVALID || result == url::PORT_UNSPECIFIED) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = result; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyServer ConstructProxyServer(ProxyServer::Scheme scheme, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& proxy_host, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& proxy_port) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!proxy_host.empty()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port_as_int = 0; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proxy_port.empty()) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_as_int = ProxyServer::GetDefaultPortForScheme(scheme); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!ConvertStringToPort(proxy_port, &port_as_int)) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyServer(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(port_as_int > 0); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyServer( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostPortPair(proxy_host, static_cast<uint16>(port_as_int))); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyServer LookupProxy(const std::string& prefix, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GetPropertyCallback& get_property, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyServer::Scheme scheme) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!prefix.empty()); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proxy_host = get_property.Run(prefix + ".proxyHost"); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!proxy_host.empty()) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proxy_port = get_property.Run(prefix + ".proxyPort"); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ConstructProxyServer(scheme, proxy_host, proxy_port); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall back to default proxy, if any. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proxy_host = get_property.Run("proxyHost"); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!proxy_host.empty()) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proxy_port = get_property.Run("proxyPort"); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ConstructProxyServer(scheme, proxy_host, proxy_port); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyServer(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyServer LookupSocksProxy(const GetPropertyCallback& get_property) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proxy_host = get_property.Run("socksProxyHost"); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!proxy_host.empty()) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proxy_port = get_property.Run("socksProxyPort"); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ConstructProxyServer(ProxyServer::SCHEME_SOCKS5, proxy_host, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proxy_port); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyServer(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddBypassRules(const std::string& scheme, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GetPropertyCallback& get_property, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyBypassRules* bypass_rules) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of a hostname pattern is a list of hostnames that are separated 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by | and that use * as a wildcard. For example, setting the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http.nonProxyHosts property to *.android.com|*.kernel.org will cause 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // requests to http://developer.android.com to be made without a proxy. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string non_proxy_hosts = 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_property.Run(scheme + ".nonProxyHosts"); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (non_proxy_hosts.empty()) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringTokenizer tokenizer(non_proxy_hosts, "|"); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (tokenizer.GetNext()) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string token = tokenizer.token(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string pattern; 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TrimWhitespaceASCII(token, base::TRIM_ALL, &pattern); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern.empty()) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // '?' is not one of the specified pattern characters above. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(std::string::npos, pattern.find('?')); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bypass_rules->AddRuleForHostname(scheme, pattern, -1); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if a valid proxy was found. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProxyRules(const GetPropertyCallback& get_property, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfig::ProxyRules* rules) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See libcore/luni/src/main/java/java/net/ProxySelectorImpl.java for the 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mostly equivalent Android implementation. There is one intentional 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // difference: by default Chromium uses the HTTP port (80) for HTTPS 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // connections via proxy. This default is identical on other platforms. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // On the opposite, Java spec suggests to use HTTPS port (443) by default (the 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // default value of https.proxyPort). 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rules->type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->proxies_for_http.SetSingleProxyServer( 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LookupProxy("http", get_property, ProxyServer::SCHEME_HTTP)); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->proxies_for_https.SetSingleProxyServer( 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LookupProxy("https", get_property, ProxyServer::SCHEME_HTTP)); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->proxies_for_ftp.SetSingleProxyServer( 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LookupProxy("ftp", get_property, ProxyServer::SCHEME_HTTP)); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->fallback_proxies.SetSingleProxyServer(LookupSocksProxy(get_property)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rules->bypass_rules.Clear(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddBypassRules("ftp", get_property, &rules->bypass_rules); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddBypassRules("http", get_property, &rules->bypass_rules); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddBypassRules("https", get_property, &rules->bypass_rules); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We know a proxy was found if not all of the proxy lists are empty. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !(rules->proxies_for_http.IsEmpty() && 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->proxies_for_https.IsEmpty() && 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->proxies_for_ftp.IsEmpty() && 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules->fallback_proxies.IsEmpty()); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetLatestProxyConfigInternal(const GetPropertyCallback& get_property, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfig* config) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetProxyRules(get_property, &config->proxy_rules())) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *config = ProxyConfig::CreateDirect(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetJavaProperty(const std::string& property) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use Java System.getProperty to get configuration information. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pliard): Conversion to/from UTF8 ok here? 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, property); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedJavaLocalRef<jstring> result = 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Java_ProxyChangeListener_getProperty(env, str.obj()); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.is_null() ? 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string() : ConvertJavaStringToUTF8(env, result.obj()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void CreateStaticProxyConfig(const std::string& host, int port, 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ProxyConfig* config) { 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (port != 0) { 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string rules = base::StringPrintf("%s:%d", host.c_str(), port); 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) config->proxy_rules().ParseFromString(rules); 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *config = ProxyConfig::CreateDirect(); 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyConfigServiceAndroid::Delegate 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe<Delegate> { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate(base::SequencedTaskRunner* network_task_runner, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SequencedTaskRunner* jni_task_runner, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GetPropertyCallback& get_property_callback) 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : jni_delegate_(this), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner_(network_task_runner), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_task_runner_(jni_task_runner), 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_property_callback_(get_property_callback) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetupJNI() { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnJNIThread()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (java_proxy_change_listener_.is_null()) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_proxy_change_listener_.Reset( 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Java_ProxyChangeListener_create( 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env, base::android::GetApplicationContext())); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!java_proxy_change_listener_.is_null()); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Java_ProxyChangeListener_start( 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_proxy_change_listener_.obj(), 198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reinterpret_cast<intptr_t>(&jni_delegate_)); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FetchInitialConfig() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnJNIThread()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfig proxy_config; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner_->PostTask( 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Delegate::SetNewConfigOnNetworkThread, this, proxy_config)); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Shutdown() { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OnJNIThread()) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShutdownOnJNIThread(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_task_runner_->PostTask( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Delegate::ShutdownOnJNIThread, this)); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called only on the network thread. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddObserver(Observer* observer) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnNetworkThread()); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveObserver(Observer* observer) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnNetworkThread()); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnNetworkThread()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!config) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyConfigService::CONFIG_UNSET; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *config = proxy_config_; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProxyConfigService::CONFIG_VALID; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the JNI thread. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ProxySettingsChanged() { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnJNIThread()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfig proxy_config; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner_->PostTask( 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind( 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &Delegate::SetNewConfigOnNetworkThread, this, proxy_config)); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Called on the JNI thread. 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void ProxySettingsChangedTo(const std::string& host, int port) { 2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(OnJNIThread()); 2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ProxyConfig proxy_config; 2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateStaticProxyConfig(host, port, &proxy_config); 2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) network_task_runner_->PostTask( 2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind( 2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &Delegate::SetNewConfigOnNetworkThread, this, proxy_config)); 2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Delegate>; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class JNIDelegateImpl : public ProxyConfigServiceAndroid::JNIDelegate { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProxyConfigServiceAndroid::JNIDelegate overrides. 2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void ProxySettingsChangedTo(JNIEnv* env, jobject jself, 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) jstring jhost, jint jport) OVERRIDE { 2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string host = ConvertJavaStringToUTF8(env, jhost); 2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) delegate_->ProxySettingsChangedTo(host, jport); 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void ProxySettingsChanged(JNIEnv* env, jobject self) OVERRIDE { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->ProxySettingsChanged(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* const delegate_; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Delegate() {} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ShutdownOnJNIThread() { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (java_proxy_change_listener_.is_null()) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Java_ProxyChangeListener_stop(env, java_proxy_change_listener_.obj()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the network thread. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetNewConfigOnNetworkThread(const ProxyConfig& proxy_config) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnNetworkThread()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proxy_config_ = proxy_config; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnProxyConfigChanged(proxy_config, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfigService::CONFIG_VALID)); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool OnJNIThread() const { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return jni_task_runner_->RunsTasksOnCurrentThread(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool OnNetworkThread() const { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return network_task_runner_->RunsTasksOnCurrentThread(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedJavaGlobalRef<jobject> java_proxy_change_listener_; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIDelegateImpl jni_delegate_; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObserverList<Observer> observers_; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> network_task_runner_; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> jni_task_runner_; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetPropertyCallback get_property_callback_; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyConfig proxy_config_; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Delegate); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigServiceAndroid::ProxyConfigServiceAndroid( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SequencedTaskRunner* network_task_runner, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SequencedTaskRunner* jni_task_runner) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(new Delegate( 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner, jni_task_runner, base::Bind(&GetJavaProperty))) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetupJNI(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->FetchInitialConfig(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigServiceAndroid::~ProxyConfigServiceAndroid() { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->Shutdown(); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyConfigServiceAndroid::Register(JNIEnv* env) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RegisterNativesImpl(env); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyConfigServiceAndroid::AddObserver(Observer* observer) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->AddObserver(observer); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyConfigServiceAndroid::RemoveObserver(Observer* observer) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->RemoveObserver(observer); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigService::ConfigAvailability 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigServiceAndroid::GetLatestProxyConfig(ProxyConfig* config) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->GetLatestProxyConfig(config); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigServiceAndroid::ProxyConfigServiceAndroid( 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SequencedTaskRunner* network_task_runner, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SequencedTaskRunner* jni_task_runner, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetPropertyCallback get_property_callback) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(new Delegate( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_task_runner, jni_task_runner, get_property_callback)) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetupJNI(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->FetchInitialConfig(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyConfigServiceAndroid::ProxySettingsChanged() { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->ProxySettingsChanged(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 367