• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 "net/proxy_resolution/proxy_config_service_android.h"
6 
7 #include <sys/system_properties.h>
8 
9 #include "base/android/jni_array.h"
10 #include "base/android/jni_string.h"
11 #include "base/check_op.h"
12 #include "base/compiler_specific.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback.h"
15 #include "base/location.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/observer_list.h"
19 #include "base/strings/string_tokenizer.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/task/sequenced_task_runner.h"
23 #include "net/base/host_port_pair.h"
24 #include "net/base/proxy_server.h"
25 #include "net/base/proxy_string_util.h"
26 #include "net/net_jni_headers/ProxyChangeListener_jni.h"
27 #include "net/proxy_resolution/proxy_config_with_annotation.h"
28 #include "url/third_party/mozilla/url_parse.h"
29 
30 using base::android::AttachCurrentThread;
31 using base::android::ConvertUTF8ToJavaString;
32 using base::android::ConvertJavaStringToUTF8;
33 using base::android::CheckException;
34 using base::android::ClearException;
35 using base::android::JavaParamRef;
36 using base::android::ScopedJavaGlobalRef;
37 using base::android::ScopedJavaLocalRef;
38 
39 namespace net {
40 
41 namespace {
42 
43 typedef ProxyConfigServiceAndroid::GetPropertyCallback GetPropertyCallback;
44 
45 // Returns whether the provided string was successfully converted to a port.
ConvertStringToPort(const std::string & port,int * output)46 bool ConvertStringToPort(const std::string& port, int* output) {
47   url::Component component(0, port.size());
48   int result = url::ParsePort(port.c_str(), component);
49   if (result == url::PORT_INVALID || result == url::PORT_UNSPECIFIED)
50     return false;
51   *output = result;
52   return true;
53 }
54 
ConstructProxyServer(ProxyServer::Scheme scheme,const std::string & proxy_host,const std::string & proxy_port)55 ProxyServer ConstructProxyServer(ProxyServer::Scheme scheme,
56                                  const std::string& proxy_host,
57                                  const std::string& proxy_port) {
58   DCHECK(!proxy_host.empty());
59   int port_as_int = 0;
60   if (proxy_port.empty())
61     port_as_int = ProxyServer::GetDefaultPortForScheme(scheme);
62   else if (!ConvertStringToPort(proxy_port, &port_as_int))
63     return ProxyServer();
64   DCHECK(port_as_int > 0);
65   return ProxyServer(
66       scheme, HostPortPair(proxy_host, static_cast<uint16_t>(port_as_int)));
67 }
68 
LookupProxy(const std::string & prefix,const GetPropertyCallback & get_property,ProxyServer::Scheme scheme)69 ProxyServer LookupProxy(const std::string& prefix,
70                         const GetPropertyCallback& get_property,
71                         ProxyServer::Scheme scheme) {
72   DCHECK(!prefix.empty());
73   std::string proxy_host = get_property.Run(prefix + ".proxyHost");
74   if (!proxy_host.empty()) {
75     std::string proxy_port = get_property.Run(prefix + ".proxyPort");
76     return ConstructProxyServer(scheme, proxy_host, proxy_port);
77   }
78   // Fall back to default proxy, if any.
79   proxy_host = get_property.Run("proxyHost");
80   if (!proxy_host.empty()) {
81     std::string proxy_port = get_property.Run("proxyPort");
82     return ConstructProxyServer(scheme, proxy_host, proxy_port);
83   }
84   return ProxyServer();
85 }
86 
LookupSocksProxy(const GetPropertyCallback & get_property)87 ProxyServer LookupSocksProxy(const GetPropertyCallback& get_property) {
88   std::string proxy_host = get_property.Run("socksProxyHost");
89   if (!proxy_host.empty()) {
90     std::string proxy_port = get_property.Run("socksProxyPort");
91     return ConstructProxyServer(ProxyServer::SCHEME_SOCKS5, proxy_host,
92                                 proxy_port);
93   }
94   return ProxyServer();
95 }
96 
AddBypassRules(const std::string & scheme,const GetPropertyCallback & get_property,ProxyBypassRules * bypass_rules)97 void AddBypassRules(const std::string& scheme,
98                     const GetPropertyCallback& get_property,
99                     ProxyBypassRules* bypass_rules) {
100   // The format of a hostname pattern is a list of hostnames that are separated
101   // by | and that use * as a wildcard. For example, setting the
102   // http.nonProxyHosts property to *.android.com|*.kernel.org will cause
103   // requests to http://developer.android.com to be made without a proxy.
104 
105   std::string non_proxy_hosts =
106       get_property.Run(scheme + ".nonProxyHosts");
107   if (non_proxy_hosts.empty())
108     return;
109   base::StringTokenizer tokenizer(non_proxy_hosts, "|");
110   while (tokenizer.GetNext()) {
111     std::string token = tokenizer.token();
112     std::string pattern;
113     base::TrimWhitespaceASCII(token, base::TRIM_ALL, &pattern);
114     if (pattern.empty())
115       continue;
116     // '?' is not one of the specified pattern characters above.
117     DCHECK_EQ(std::string::npos, pattern.find('?'));
118     bypass_rules->AddRuleFromString(scheme + "://" + pattern);
119   }
120 }
121 
122 // Returns true if a valid proxy was found.
GetProxyRules(const GetPropertyCallback & get_property,ProxyConfig::ProxyRules * rules)123 bool GetProxyRules(const GetPropertyCallback& get_property,
124                    ProxyConfig::ProxyRules* rules) {
125   // See libcore/luni/src/main/java/java/net/ProxySelectorImpl.java for the
126   // mostly equivalent Android implementation.  There is one intentional
127   // difference: by default Chromium uses the HTTP port (80) for HTTPS
128   // connections via proxy.  This default is identical on other platforms.
129   // On the opposite, Java spec suggests to use HTTPS port (443) by default (the
130   // default value of https.proxyPort).
131   rules->type = ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
132   rules->proxies_for_http.SetSingleProxyServer(
133       LookupProxy("http", get_property, ProxyServer::SCHEME_HTTP));
134   rules->proxies_for_https.SetSingleProxyServer(
135       LookupProxy("https", get_property, ProxyServer::SCHEME_HTTP));
136   rules->proxies_for_ftp.SetSingleProxyServer(
137       LookupProxy("ftp", get_property, ProxyServer::SCHEME_HTTP));
138   rules->fallback_proxies.SetSingleProxyServer(LookupSocksProxy(get_property));
139   rules->bypass_rules.Clear();
140   AddBypassRules("ftp", get_property, &rules->bypass_rules);
141   AddBypassRules("http", get_property, &rules->bypass_rules);
142   AddBypassRules("https", get_property, &rules->bypass_rules);
143   // We know a proxy was found if not all of the proxy lists are empty.
144   return !(rules->proxies_for_http.IsEmpty() &&
145       rules->proxies_for_https.IsEmpty() &&
146       rules->proxies_for_ftp.IsEmpty() &&
147       rules->fallback_proxies.IsEmpty());
148 }
149 
GetLatestProxyConfigInternal(const GetPropertyCallback & get_property,ProxyConfigWithAnnotation * config)150 void GetLatestProxyConfigInternal(const GetPropertyCallback& get_property,
151                                   ProxyConfigWithAnnotation* config) {
152   ProxyConfig proxy_config;
153   proxy_config.set_from_system(true);
154   if (GetProxyRules(get_property, &proxy_config.proxy_rules())) {
155     *config =
156         ProxyConfigWithAnnotation(proxy_config, MISSING_TRAFFIC_ANNOTATION);
157   } else {
158     *config = ProxyConfigWithAnnotation::CreateDirect();
159   }
160 }
161 
GetJavaProperty(const std::string & property)162 std::string GetJavaProperty(const std::string& property) {
163   // Use Java System.getProperty to get configuration information.
164   // TODO(pliard): Conversion to/from UTF8 ok here?
165   JNIEnv* env = AttachCurrentThread();
166   ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, property);
167   ScopedJavaLocalRef<jstring> result =
168       Java_ProxyChangeListener_getProperty(env, str);
169   return result.is_null() ?
170       std::string() : ConvertJavaStringToUTF8(env, result.obj());
171 }
172 
CreateStaticProxyConfig(const std::string & host,int port,const std::string & pac_url,const std::vector<std::string> & exclusion_list,ProxyConfigWithAnnotation * config)173 void CreateStaticProxyConfig(const std::string& host,
174                              int port,
175                              const std::string& pac_url,
176                              const std::vector<std::string>& exclusion_list,
177                              ProxyConfigWithAnnotation* config) {
178   ProxyConfig proxy_config;
179   if (!pac_url.empty()) {
180     proxy_config.set_pac_url(GURL(pac_url));
181     proxy_config.set_pac_mandatory(false);
182     *config =
183         ProxyConfigWithAnnotation(proxy_config, MISSING_TRAFFIC_ANNOTATION);
184   } else if (port != 0) {
185     std::string rules = base::StringPrintf("%s:%d", host.c_str(), port);
186     proxy_config.proxy_rules().ParseFromString(rules);
187     proxy_config.proxy_rules().bypass_rules.Clear();
188 
189     std::vector<std::string>::const_iterator it;
190     for (it = exclusion_list.begin(); it != exclusion_list.end(); ++it) {
191       std::string pattern;
192       base::TrimWhitespaceASCII(*it, base::TRIM_ALL, &pattern);
193       if (pattern.empty())
194           continue;
195       proxy_config.proxy_rules().bypass_rules.AddRuleFromString(pattern);
196     }
197     *config =
198         ProxyConfigWithAnnotation(proxy_config, MISSING_TRAFFIC_ANNOTATION);
199   } else {
200     *config = ProxyConfigWithAnnotation::CreateDirect();
201   }
202 }
203 
ParseOverrideRules(const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> & override_rules,ProxyConfig::ProxyRules * proxy_rules)204 std::string ParseOverrideRules(
205     const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule>&
206         override_rules,
207     ProxyConfig::ProxyRules* proxy_rules) {
208   // If no rules were specified, use DIRECT for everything.
209   if (override_rules.empty()) {
210     DCHECK(proxy_rules->empty());
211     return "";
212   }
213 
214   // Otherwise use a proxy list per URL scheme.
215   proxy_rules->type = ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
216 
217   for (const auto& rule : override_rules) {
218     // Parse the proxy URL.
219     ProxyServer proxy_server =
220         ProxyUriToProxyServer(rule.proxy_url, ProxyServer::Scheme::SCHEME_HTTP);
221     if (!proxy_server.is_valid()) {
222       return "Invalid Proxy URL: " + rule.proxy_url;
223     } else if (proxy_server.is_quic()) {
224       return "Unsupported proxy scheme: " + rule.proxy_url;
225     }
226 
227     // Parse the URL scheme.
228     if (base::EqualsCaseInsensitiveASCII(rule.url_scheme, "http")) {
229       proxy_rules->proxies_for_http.AddProxyServer(proxy_server);
230     } else if (base::EqualsCaseInsensitiveASCII(rule.url_scheme, "https")) {
231       proxy_rules->proxies_for_https.AddProxyServer(proxy_server);
232     } else if (rule.url_scheme == "*") {
233       proxy_rules->fallback_proxies.AddProxyServer(proxy_server);
234     } else {
235       return "Unsupported URL scheme: " + rule.url_scheme;
236     }
237   }
238 
239   // If there is no per-URL scheme distinction simplify the ProxyRules.
240   if (proxy_rules->proxies_for_http.IsEmpty() &&
241       proxy_rules->proxies_for_https.IsEmpty() &&
242       !proxy_rules->fallback_proxies.IsEmpty()) {
243     proxy_rules->type = ProxyConfig::ProxyRules::Type::PROXY_LIST;
244     std::swap(proxy_rules->single_proxies, proxy_rules->fallback_proxies);
245   }
246 
247   return "";
248 }
249 
CreateOverrideProxyConfig(const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> & proxy_rules,const std::vector<std::string> & bypass_rules,const bool reverse_bypass,ProxyConfigWithAnnotation * config)250 std::string CreateOverrideProxyConfig(
251     const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule>&
252         proxy_rules,
253     const std::vector<std::string>& bypass_rules,
254     const bool reverse_bypass,
255     ProxyConfigWithAnnotation* config) {
256   ProxyConfig proxy_config;
257   auto result = ParseOverrideRules(proxy_rules, &proxy_config.proxy_rules());
258   if (!result.empty()) {
259     return result;
260   }
261 
262   proxy_config.proxy_rules().reverse_bypass = reverse_bypass;
263 
264   for (const auto& bypass_rule : bypass_rules) {
265     if (!proxy_config.proxy_rules().bypass_rules.AddRuleFromString(
266             bypass_rule)) {
267       return "Invalid bypass rule " + bypass_rule;
268     }
269   }
270   *config = ProxyConfigWithAnnotation(proxy_config, MISSING_TRAFFIC_ANNOTATION);
271   return "";
272 }
273 
274 }  // namespace
275 
276 class ProxyConfigServiceAndroid::Delegate
277     : public base::RefCountedThreadSafe<Delegate> {
278  public:
Delegate(const scoped_refptr<base::SequencedTaskRunner> & main_task_runner,const scoped_refptr<base::SequencedTaskRunner> & jni_task_runner,const GetPropertyCallback & get_property_callback)279   Delegate(const scoped_refptr<base::SequencedTaskRunner>& main_task_runner,
280            const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner,
281            const GetPropertyCallback& get_property_callback)
282       : jni_delegate_(this),
283         main_task_runner_(main_task_runner),
284         jni_task_runner_(jni_task_runner),
285         get_property_callback_(get_property_callback) {}
286 
287   Delegate(const Delegate&) = delete;
288   Delegate& operator=(const Delegate&) = delete;
289 
SetupJNI()290   void SetupJNI() {
291     DCHECK(InJNISequence());
292     JNIEnv* env = AttachCurrentThread();
293     if (java_proxy_change_listener_.is_null()) {
294       java_proxy_change_listener_.Reset(Java_ProxyChangeListener_create(env));
295       CHECK(!java_proxy_change_listener_.is_null());
296     }
297     Java_ProxyChangeListener_start(env, java_proxy_change_listener_,
298                                    reinterpret_cast<intptr_t>(&jni_delegate_));
299   }
300 
FetchInitialConfig()301   void FetchInitialConfig() {
302     DCHECK(InJNISequence());
303     ProxyConfigWithAnnotation proxy_config;
304     GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);
305     main_task_runner_->PostTask(
306         FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInMainSequence, this,
307                                   proxy_config));
308   }
309 
Shutdown()310   void Shutdown() {
311     if (InJNISequence()) {
312       ShutdownInJNISequence();
313     } else {
314       jni_task_runner_->PostTask(
315           FROM_HERE, base::BindOnce(&Delegate::ShutdownInJNISequence, this));
316     }
317   }
318 
319   // Called only in the network sequence.
AddObserver(Observer * observer)320   void AddObserver(Observer* observer) {
321     DCHECK(InMainSequence());
322     observers_.AddObserver(observer);
323   }
324 
RemoveObserver(Observer * observer)325   void RemoveObserver(Observer* observer) {
326     DCHECK(InMainSequence());
327     observers_.RemoveObserver(observer);
328   }
329 
GetLatestProxyConfig(ProxyConfigWithAnnotation * config)330   ConfigAvailability GetLatestProxyConfig(ProxyConfigWithAnnotation* config) {
331     DCHECK(InMainSequence());
332     if (!config)
333       return ProxyConfigService::CONFIG_UNSET;
334     *config = proxy_config_;
335     return ProxyConfigService::CONFIG_VALID;
336   }
337 
338   // Called in the JNI sequence.
ProxySettingsChanged()339   void ProxySettingsChanged() {
340     DCHECK(InJNISequence());
341     if (has_proxy_override_)
342       return;
343 
344     ProxyConfigWithAnnotation proxy_config;
345     GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);
346     main_task_runner_->PostTask(
347         FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInMainSequence, this,
348                                   proxy_config));
349   }
350 
351   // Called in the JNI sequence.
ProxySettingsChangedTo(const std::string & host,int port,const std::string & pac_url,const std::vector<std::string> & exclusion_list)352   void ProxySettingsChangedTo(const std::string& host,
353                               int port,
354                               const std::string& pac_url,
355                               const std::vector<std::string>& exclusion_list) {
356     DCHECK(InJNISequence());
357     if (has_proxy_override_)
358       return;
359 
360     ProxyConfigWithAnnotation proxy_config;
361     if (exclude_pac_url_) {
362       CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config);
363     } else {
364       CreateStaticProxyConfig(host, port, pac_url, exclusion_list,
365           &proxy_config);
366     }
367     main_task_runner_->PostTask(
368         FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInMainSequence, this,
369                                   proxy_config));
370   }
371 
set_exclude_pac_url(bool enabled)372   void set_exclude_pac_url(bool enabled) {
373     exclude_pac_url_ = enabled;
374   }
375 
376   // Called in the JNI sequence.
SetProxyOverride(const std::vector<ProxyOverrideRule> & proxy_rules,const std::vector<std::string> & bypass_rules,const bool reverse_bypass,base::OnceClosure callback)377   std::string SetProxyOverride(
378       const std::vector<ProxyOverrideRule>& proxy_rules,
379       const std::vector<std::string>& bypass_rules,
380       const bool reverse_bypass,
381       base::OnceClosure callback) {
382     DCHECK(InJNISequence());
383     has_proxy_override_ = true;
384 
385     // Creates a new proxy config
386     ProxyConfigWithAnnotation proxy_config;
387     std::string result = CreateOverrideProxyConfig(
388         proxy_rules, bypass_rules, reverse_bypass, &proxy_config);
389     if (!result.empty()) {
390       return result;
391     }
392 
393     main_task_runner_->PostTaskAndReply(
394         FROM_HERE,
395         base::BindOnce(&Delegate::SetNewConfigInMainSequence, this,
396                        proxy_config),
397         std::move(callback));
398 
399     return "";
400   }
401 
402   // Called in the JNI sequence.
ClearProxyOverride(base::OnceClosure callback)403   void ClearProxyOverride(base::OnceClosure callback) {
404     DCHECK(InJNISequence());
405     if (!has_proxy_override_) {
406       std::move(callback).Run();
407       return;
408     }
409 
410     ProxyConfigWithAnnotation proxy_config;
411     GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);
412     main_task_runner_->PostTaskAndReply(
413         FROM_HERE,
414         base::BindOnce(&Delegate::SetNewConfigInMainSequence, this,
415                        proxy_config),
416         std::move(callback));
417     has_proxy_override_ = false;
418   }
419 
420  private:
421   friend class base::RefCountedThreadSafe<Delegate>;
422 
423   class JNIDelegateImpl : public ProxyConfigServiceAndroid::JNIDelegate {
424    public:
JNIDelegateImpl(Delegate * delegate)425     explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {}
426 
427     // ProxyConfigServiceAndroid::JNIDelegate overrides.
ProxySettingsChangedTo(JNIEnv * env,const JavaParamRef<jobject> & jself,const JavaParamRef<jstring> & jhost,jint jport,const JavaParamRef<jstring> & jpac_url,const JavaParamRef<jobjectArray> & jexclusion_list)428     void ProxySettingsChangedTo(
429         JNIEnv* env,
430         const JavaParamRef<jobject>& jself,
431         const JavaParamRef<jstring>& jhost,
432         jint jport,
433         const JavaParamRef<jstring>& jpac_url,
434         const JavaParamRef<jobjectArray>& jexclusion_list) override {
435       std::string host = ConvertJavaStringToUTF8(env, jhost);
436       std::string pac_url;
437       if (jpac_url)
438         ConvertJavaStringToUTF8(env, jpac_url, &pac_url);
439       std::vector<std::string> exclusion_list;
440       base::android::AppendJavaStringArrayToStringVector(
441           env, jexclusion_list, &exclusion_list);
442       delegate_->ProxySettingsChangedTo(host, jport, pac_url, exclusion_list);
443     }
444 
ProxySettingsChanged(JNIEnv * env,const JavaParamRef<jobject> & self)445     void ProxySettingsChanged(JNIEnv* env,
446                               const JavaParamRef<jobject>& self) override {
447       delegate_->ProxySettingsChanged();
448     }
449 
450    private:
451     const raw_ptr<Delegate> delegate_;
452   };
453 
454   virtual ~Delegate() = default;
455 
ShutdownInJNISequence()456   void ShutdownInJNISequence() {
457     if (java_proxy_change_listener_.is_null())
458       return;
459     JNIEnv* env = AttachCurrentThread();
460     Java_ProxyChangeListener_stop(env, java_proxy_change_listener_);
461   }
462 
463   // Called on the network sequence.
SetNewConfigInMainSequence(const ProxyConfigWithAnnotation & proxy_config)464   void SetNewConfigInMainSequence(
465       const ProxyConfigWithAnnotation& proxy_config) {
466     DCHECK(InMainSequence());
467     proxy_config_ = proxy_config;
468     for (auto& observer : observers_) {
469       observer.OnProxyConfigChanged(proxy_config,
470                                     ProxyConfigService::CONFIG_VALID);
471     }
472   }
473 
InJNISequence() const474   bool InJNISequence() const {
475     return jni_task_runner_->RunsTasksInCurrentSequence();
476   }
477 
InMainSequence() const478   bool InMainSequence() const {
479     return main_task_runner_->RunsTasksInCurrentSequence();
480   }
481 
482   ScopedJavaGlobalRef<jobject> java_proxy_change_listener_;
483 
484   JNIDelegateImpl jni_delegate_;
485   base::ObserverList<Observer>::Unchecked observers_;
486   scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
487   scoped_refptr<base::SequencedTaskRunner> jni_task_runner_;
488   GetPropertyCallback get_property_callback_;
489   ProxyConfigWithAnnotation proxy_config_;
490   bool exclude_pac_url_ = false;
491   // This may only be accessed or modified on the JNI thread
492   bool has_proxy_override_ = false;
493 };
494 
ProxyConfigServiceAndroid(const scoped_refptr<base::SequencedTaskRunner> & main_task_runner,const scoped_refptr<base::SequencedTaskRunner> & jni_task_runner)495 ProxyConfigServiceAndroid::ProxyConfigServiceAndroid(
496     const scoped_refptr<base::SequencedTaskRunner>& main_task_runner,
497     const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner)
498     : delegate_(base::MakeRefCounted<Delegate>(
499           main_task_runner,
500           jni_task_runner,
501           base::BindRepeating(&GetJavaProperty))) {
502   delegate_->SetupJNI();
503   delegate_->FetchInitialConfig();
504 }
505 
~ProxyConfigServiceAndroid()506 ProxyConfigServiceAndroid::~ProxyConfigServiceAndroid() {
507   delegate_->Shutdown();
508 }
509 
set_exclude_pac_url(bool enabled)510 void ProxyConfigServiceAndroid::set_exclude_pac_url(bool enabled) {
511   delegate_->set_exclude_pac_url(enabled);
512 }
513 
AddObserver(Observer * observer)514 void ProxyConfigServiceAndroid::AddObserver(Observer* observer) {
515   delegate_->AddObserver(observer);
516 }
517 
RemoveObserver(Observer * observer)518 void ProxyConfigServiceAndroid::RemoveObserver(Observer* observer) {
519   delegate_->RemoveObserver(observer);
520 }
521 
522 ProxyConfigService::ConfigAvailability
GetLatestProxyConfig(ProxyConfigWithAnnotation * config)523 ProxyConfigServiceAndroid::GetLatestProxyConfig(
524     ProxyConfigWithAnnotation* config) {
525   return delegate_->GetLatestProxyConfig(config);
526 }
527 
ProxyConfigServiceAndroid(const scoped_refptr<base::SequencedTaskRunner> & main_task_runner,const scoped_refptr<base::SequencedTaskRunner> & jni_task_runner,GetPropertyCallback get_property_callback)528 ProxyConfigServiceAndroid::ProxyConfigServiceAndroid(
529     const scoped_refptr<base::SequencedTaskRunner>& main_task_runner,
530     const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner,
531     GetPropertyCallback get_property_callback)
532     : delegate_(base::MakeRefCounted<Delegate>(main_task_runner,
533                                                jni_task_runner,
534                                                get_property_callback)) {
535   delegate_->SetupJNI();
536   delegate_->FetchInitialConfig();
537 }
538 
ProxySettingsChangedTo(const std::string & host,int port,const std::string & pac_url,const std::vector<std::string> & exclusion_list)539 void ProxyConfigServiceAndroid::ProxySettingsChangedTo(
540     const std::string& host,
541     int port,
542     const std::string& pac_url,
543     const std::vector<std::string>& exclusion_list) {
544   delegate_->ProxySettingsChangedTo(host, port, pac_url, exclusion_list);
545 }
546 
ProxySettingsChanged()547 void ProxyConfigServiceAndroid::ProxySettingsChanged() {
548   delegate_->ProxySettingsChanged();
549 }
550 
SetProxyOverride(const std::vector<ProxyOverrideRule> & proxy_rules,const std::vector<std::string> & bypass_rules,const bool reverse_bypass,base::OnceClosure callback)551 std::string ProxyConfigServiceAndroid::SetProxyOverride(
552     const std::vector<ProxyOverrideRule>& proxy_rules,
553     const std::vector<std::string>& bypass_rules,
554     const bool reverse_bypass,
555     base::OnceClosure callback) {
556   return delegate_->SetProxyOverride(proxy_rules, bypass_rules, reverse_bypass,
557                                      std::move(callback));
558 }
559 
ClearProxyOverride(base::OnceClosure callback)560 void ProxyConfigServiceAndroid::ClearProxyOverride(base::OnceClosure callback) {
561   delegate_->ClearProxyOverride(std::move(callback));
562 }
563 
564 } // namespace net
565