aw_pac_processor.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // Copyright 2019 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. #include "android_webview/browser/aw_pac_processor.h"
  5. #include <android/multinetwork.h>
  6. #include <arpa/inet.h>
  7. #include <dlfcn.h>
  8. #include <netdb.h>
  9. #include <unistd.h>
  10. #include <cstddef>
  11. #include <memory>
  12. #include <string>
  13. #include "android_webview/browser_jni_headers/AwPacProcessor_jni.h"
  14. #include "base/android/jni_android.h"
  15. #include "base/android/jni_array.h"
  16. #include "base/android/jni_string.h"
  17. #include "base/bind.h"
  18. #include "base/logging.h"
  19. #include "base/memory/raw_ptr.h"
  20. #include "base/task/thread_pool/thread_pool_instance.h"
  21. #include "base/threading/thread_restrictions.h"
  22. #include "net/base/address_list.h"
  23. #include "net/base/completion_once_callback.h"
  24. #include "net/base/net_errors.h"
  25. #include "net/base/network_isolation_key.h"
  26. #include "net/proxy_resolution/pac_file_data.h"
  27. #include "net/proxy_resolution/proxy_info.h"
  28. using base::android::AttachCurrentThread;
  29. using base::android::ConvertJavaStringToUTF8;
  30. using base::android::ConvertUTF8ToJavaString;
  31. using base::android::JavaParamRef;
  32. using base::android::JavaRef;
  33. using base::android::ScopedJavaGlobalRef;
  34. using base::android::ScopedJavaLocalRef;
  35. class NetworkIsolationKey;
  36. namespace android_webview {
  37. namespace {
  38. static_assert(NETWORK_UNSPECIFIED == 0,
  39. "Java side AwPacProcessor#NETWORK_UNSPECIFIED needs update");
  40. typedef int (*getaddrinfofornetwork_ptr_t)(net_handle_t,
  41. const char*,
  42. const char*,
  43. const struct addrinfo*,
  44. struct addrinfo**);
  45. // The definition of android_getaddrinfofornetwork is conditional
  46. // on __ANDROID_API__ >= 23. It's not possible to just have a runtime check for
  47. // the SDK level to guard a call that might not exist on older platform
  48. // versions: all native function imports are resolved at load time and loading
  49. // the library will fail if they're unresolvable. Therefore we need to search
  50. // for the function via dlsym.
  51. int AndroidGetAddrInfoForNetwork(net_handle_t network,
  52. const char* node,
  53. const char* service,
  54. const struct addrinfo* hints,
  55. struct addrinfo** res) {
  56. static getaddrinfofornetwork_ptr_t getaddrinfofornetwork = [] {
  57. getaddrinfofornetwork_ptr_t ptr =
  58. reinterpret_cast<getaddrinfofornetwork_ptr_t>(
  59. dlsym(RTLD_DEFAULT, "android_getaddrinfofornetwork"));
  60. DCHECK(ptr);
  61. return ptr;
  62. }();
  63. return getaddrinfofornetwork(network, node, service, hints, res);
  64. }
  65. scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
  66. struct ThreadHolder {
  67. base::Thread thread_;
  68. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  69. ThreadHolder() : thread_("AwPacProcessor") {
  70. thread_.Start();
  71. task_runner_ = thread_.task_runner();
  72. }
  73. };
  74. static ThreadHolder thread_holder;
  75. return thread_holder.task_runner_;
  76. }
  77. proxy_resolver::ProxyResolverV8TracingFactory* GetProxyResolverFactory() {
  78. static std::unique_ptr<proxy_resolver::ProxyResolverV8TracingFactory>
  79. factory = proxy_resolver::ProxyResolverV8TracingFactory::Create();
  80. return factory.get();
  81. }
  82. } // namespace
  83. // TODO(amalova): We could use a separate thread or thread pool for executing
  84. // blocking DNS queries, to get better performance.
  85. class HostResolver : public proxy_resolver::ProxyHostResolver {
  86. public:
  87. std::unique_ptr<proxy_resolver::ProxyHostResolver::Request> CreateRequest(
  88. const std::string& hostname,
  89. net::ProxyResolveDnsOperation operation,
  90. const net::NetworkIsolationKey&) override {
  91. return std::make_unique<RequestImpl>(hostname, operation, net_handle_,
  92. link_addresses_);
  93. }
  94. void SetNetworkAndLinkAddresses(
  95. const net_handle_t net_handle,
  96. const std::vector<net::IPAddress>& link_addresses) {
  97. link_addresses_ = link_addresses;
  98. net_handle_ = net_handle;
  99. }
  100. private:
  101. net_handle_t net_handle_ = 0;
  102. std::vector<net::IPAddress> link_addresses_;
  103. class RequestImpl : public proxy_resolver::ProxyHostResolver::Request {
  104. public:
  105. RequestImpl(const std::string& hostname,
  106. net::ProxyResolveDnsOperation operation,
  107. net_handle_t net_handle,
  108. const std::vector<net::IPAddress>& link_addresses)
  109. : hostname_(hostname),
  110. operation_(operation),
  111. net_handle_(net_handle),
  112. link_addresses_(link_addresses) {}
  113. ~RequestImpl() override = default;
  114. int Start(net::CompletionOnceCallback callback) override {
  115. bool success = false;
  116. switch (operation_) {
  117. case net::ProxyResolveDnsOperation::DNS_RESOLVE:
  118. success = DnsResolveImpl(hostname_);
  119. break;
  120. case net::ProxyResolveDnsOperation::DNS_RESOLVE_EX:
  121. success = DnsResolveExImpl(hostname_);
  122. break;
  123. case net::ProxyResolveDnsOperation::MY_IP_ADDRESS:
  124. success = MyIpAddressImpl();
  125. break;
  126. case net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX:
  127. success = MyIpAddressExImpl();
  128. break;
  129. }
  130. return success ? net::OK : net::ERR_NAME_RESOLUTION_FAILED;
  131. }
  132. const std::vector<net::IPAddress>& GetResults() const override {
  133. return results_;
  134. }
  135. private:
  136. bool IsNetworkSpecified() { return net_handle_ != NETWORK_UNSPECIFIED; }
  137. bool MyIpAddressImpl() {
  138. // For network-aware queries the results are set from Java on
  139. // NetworkCallback#onLinkPropertiesChanged.
  140. // See SetNetworkAndLinkAddresses.
  141. if (IsNetworkSpecified()) {
  142. results_.push_back(link_addresses_.front());
  143. return true;
  144. }
  145. std::string my_hostname = GetHostName();
  146. if (my_hostname.empty())
  147. return false;
  148. return DnsResolveImpl(my_hostname);
  149. }
  150. bool MyIpAddressExImpl() {
  151. if (IsNetworkSpecified()) {
  152. results_ = link_addresses_;
  153. return true;
  154. }
  155. std::string my_hostname = GetHostName();
  156. if (my_hostname.empty())
  157. return false;
  158. return DnsResolveExImpl(my_hostname);
  159. }
  160. bool DnsResolveImpl(const std::string& host) {
  161. struct addrinfo hints;
  162. memset(&hints, 0, sizeof hints);
  163. hints.ai_family = AF_INET;
  164. struct addrinfo* res = nullptr;
  165. int result = IsNetworkSpecified()
  166. ? AndroidGetAddrInfoForNetwork(net_handle_, host.c_str(),
  167. nullptr, &hints, &res)
  168. : getaddrinfo(host.c_str(), nullptr, &hints, &res);
  169. if (result != 0) {
  170. return false;
  171. }
  172. net::AddressList address_list = net::AddressList::CreateFromAddrinfo(res);
  173. results_.push_back(address_list.front().address());
  174. freeaddrinfo(res);
  175. return !results_.empty();
  176. }
  177. bool DnsResolveExImpl(const std::string& host) {
  178. struct addrinfo* res = nullptr;
  179. int result = IsNetworkSpecified()
  180. ? AndroidGetAddrInfoForNetwork(net_handle_, host.c_str(),
  181. nullptr, nullptr, &res)
  182. : getaddrinfo(host.c_str(), nullptr, nullptr, &res);
  183. if (result != 0) {
  184. return false;
  185. }
  186. net::AddressList address_list = net::AddressList::CreateFromAddrinfo(res);
  187. for (net::IPEndPoint endpoint : address_list.endpoints()) {
  188. results_.push_back(endpoint.address());
  189. }
  190. freeaddrinfo(res);
  191. return !results_.empty();
  192. }
  193. std::string GetHostName() {
  194. char buffer[HOST_NAME_MAX + 1];
  195. if (gethostname(buffer, HOST_NAME_MAX + 1) != 0) {
  196. return std::string();
  197. }
  198. // It's unspecified whether gethostname NULL-terminates if the hostname
  199. // must be truncated and no error is returned if that happens.
  200. buffer[HOST_NAME_MAX] = '\0';
  201. return std::string(buffer);
  202. }
  203. const std::string hostname_;
  204. const net::ProxyResolveDnsOperation operation_;
  205. net_handle_t net_handle_;
  206. std::vector<net::IPAddress> results_;
  207. std::vector<net::IPAddress> link_addresses_;
  208. };
  209. };
  210. class Bindings : public proxy_resolver::ProxyResolverV8Tracing::Bindings {
  211. public:
  212. Bindings(HostResolver* host_resolver) : host_resolver_(host_resolver) {}
  213. void Alert(const std::u16string& message) override {}
  214. void OnError(int line_number, const std::u16string& message) override {}
  215. proxy_resolver::ProxyHostResolver* GetHostResolver() override {
  216. return host_resolver_;
  217. }
  218. net::NetLogWithSource GetNetLogWithSource() override {
  219. return net::NetLogWithSource();
  220. }
  221. private:
  222. raw_ptr<HostResolver> host_resolver_;
  223. };
  224. // Public methods of AwPacProcessor may be called on multiple threads.
  225. // ProxyResolverV8TracingFactory/ProxyResolverV8Tracing
  226. // expects its public interface to always be called on the same thread with
  227. // Chromium task runner so it can post it back to that thread
  228. // with the result of the queries.
  229. //
  230. // Job and its subclasses wrap queries from public methods of AwPacProcessor,
  231. // post them on a special thread and blocks on WaitableEvent
  232. // until the query is finished. |OnSignal| is passed to
  233. // ProxyResolverV8TracingFactory/ProxyResolverV8Tracing methods.
  234. // This callback is called once the request is processed and,
  235. // it signals WaitableEvent and returns result to the calling thread.
  236. //
  237. // ProxyResolverV8TracingFactory/ProxyResolverV8Tracing behaviour is the
  238. // following: if the corresponding request is destroyed,
  239. // the query is cancelled and the callback is never called.
  240. // That means that we need to signal WaitableEvent to unblock calling thread
  241. // when we cancel Job. We keep track of unfinished Jobs in |jobs_|. This field
  242. // is always accessed on the same thread.
  243. //
  244. // All Jobs must be cancelled prior to destruction of |proxy_resolver_| since
  245. // its destructor asserts there are no pending requests.
  246. class Job {
  247. public:
  248. virtual ~Job() = default;
  249. bool ExecSync() {
  250. GetTaskRunner()->PostTask(
  251. FROM_HERE, base::BindOnce(&Job::Exec, base::Unretained(this)));
  252. event_.Wait();
  253. return net_error_ == net::OK;
  254. }
  255. void Exec() {
  256. processor_->jobs_.insert(this);
  257. std::move(task_).Run();
  258. }
  259. virtual void Cancel() = 0;
  260. void OnSignal(int net_error) {
  261. net_error_ = net_error;
  262. // Both SetProxyScriptJob#request_ and MakeProxyRequestJob#request_
  263. // have to be destroyed on the same thread on which they are created.
  264. // If we destroy them before callback is called the request_ is cancelled.
  265. // Reset them here on the correct thread when the job is already finished
  266. // so no cancellation occurs.
  267. Cancel();
  268. }
  269. base::OnceClosure task_;
  270. int net_error_ = net::ERR_ABORTED;
  271. base::WaitableEvent event_;
  272. raw_ptr<AwPacProcessor> processor_;
  273. };
  274. class SetProxyScriptJob : public Job {
  275. public:
  276. SetProxyScriptJob(AwPacProcessor* processor, std::string script) {
  277. processor_ = processor;
  278. task_ = base::BindOnce(
  279. &AwPacProcessor::SetProxyScriptNative, base::Unretained(processor_),
  280. &request_, std::move(script),
  281. base::BindOnce(&SetProxyScriptJob::OnSignal, base::Unretained(this)));
  282. }
  283. void Cancel() override {
  284. processor_->jobs_.erase(this);
  285. request_.reset();
  286. event_.Signal();
  287. }
  288. private:
  289. std::unique_ptr<net::ProxyResolverFactory::Request> request_;
  290. };
  291. class MakeProxyRequestJob : public Job {
  292. public:
  293. MakeProxyRequestJob(AwPacProcessor* processor, std::string url) {
  294. processor_ = processor;
  295. task_ = base::BindOnce(
  296. &AwPacProcessor::MakeProxyRequestNative, base::Unretained(processor_),
  297. &request_, std::move(url), &proxy_info_,
  298. base::BindOnce(&MakeProxyRequestJob::OnSignal, base::Unretained(this)));
  299. }
  300. void Cancel() override {
  301. processor_->jobs_.erase(this);
  302. request_.reset();
  303. event_.Signal();
  304. }
  305. net::ProxyInfo proxy_info() { return proxy_info_; }
  306. private:
  307. net::ProxyInfo proxy_info_;
  308. std::unique_ptr<net::ProxyResolver::Request> request_;
  309. };
  310. AwPacProcessor::AwPacProcessor() {
  311. host_resolver_ = std::make_unique<HostResolver>();
  312. }
  313. AwPacProcessor::~AwPacProcessor() {
  314. base::WaitableEvent event;
  315. // |proxy_resolver_| must be destroyed on the same thread it is created.
  316. GetTaskRunner()->PostTask(
  317. FROM_HERE,
  318. base::BindOnce(&AwPacProcessor::Destroy, base::Unretained(this),
  319. base::Unretained(&event)));
  320. event.Wait();
  321. }
  322. void AwPacProcessor::Destroy(base::WaitableEvent* event) {
  323. // Cancel all unfinished jobs to unblock calling thread.
  324. for (auto* job : jobs_) {
  325. job->Cancel();
  326. }
  327. proxy_resolver_.reset();
  328. event->Signal();
  329. }
  330. void AwPacProcessor::DestroyNative(
  331. JNIEnv* env,
  332. const base::android::JavaParamRef<jobject>& obj) {
  333. delete this;
  334. }
  335. void AwPacProcessor::SetProxyScriptNative(
  336. std::unique_ptr<net::ProxyResolverFactory::Request>* request,
  337. const std::string& script,
  338. net::CompletionOnceCallback complete) {
  339. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  340. GetProxyResolverFactory()->CreateProxyResolverV8Tracing(
  341. net::PacFileData::FromUTF8(script),
  342. std::make_unique<Bindings>(host_resolver_.get()), &proxy_resolver_,
  343. std::move(complete), request);
  344. }
  345. void AwPacProcessor::MakeProxyRequestNative(
  346. std::unique_ptr<net::ProxyResolver::Request>* request,
  347. const std::string& url,
  348. net::ProxyInfo* proxy_info,
  349. net::CompletionOnceCallback complete) {
  350. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  351. if (proxy_resolver_) {
  352. proxy_resolver_->GetProxyForURL(
  353. GURL(url), net::NetworkIsolationKey(), proxy_info, std::move(complete),
  354. request, std::make_unique<Bindings>(host_resolver_.get()));
  355. } else {
  356. std::move(complete).Run(net::ERR_FAILED);
  357. }
  358. }
  359. bool AwPacProcessor::SetProxyScript(std::string script) {
  360. SetProxyScriptJob job(this, script);
  361. return job.ExecSync();
  362. }
  363. jboolean AwPacProcessor::SetProxyScript(JNIEnv* env,
  364. const JavaParamRef<jobject>& obj,
  365. const JavaParamRef<jstring>& jscript) {
  366. std::string script = ConvertJavaStringToUTF8(env, jscript);
  367. return SetProxyScript(script);
  368. }
  369. bool AwPacProcessor::MakeProxyRequest(std::string url, std::string* result) {
  370. MakeProxyRequestJob job(this, url);
  371. if (job.ExecSync()) {
  372. *result = job.proxy_info().ToPacString();
  373. return true;
  374. } else {
  375. return false;
  376. }
  377. }
  378. ScopedJavaLocalRef<jstring> AwPacProcessor::MakeProxyRequest(
  379. JNIEnv* env,
  380. const JavaParamRef<jobject>& obj,
  381. const JavaParamRef<jstring>& jurl) {
  382. std::string url = ConvertJavaStringToUTF8(env, jurl);
  383. std::string result;
  384. if (MakeProxyRequest(url, &result)) {
  385. return ConvertUTF8ToJavaString(env, result);
  386. } else {
  387. return nullptr;
  388. }
  389. }
  390. void AwPacProcessor::SetNetworkAndLinkAddresses(
  391. JNIEnv* env,
  392. net_handle_t net_handle,
  393. const base::android::JavaParamRef<jobjectArray>& jlink_addresses) {
  394. std::vector<std::string> string_link_addresses;
  395. base::android::AppendJavaStringArrayToStringVector(env, jlink_addresses,
  396. &string_link_addresses);
  397. std::vector<net::IPAddress> link_addresses;
  398. for (const std::string& address : string_link_addresses) {
  399. net::IPAddress ip_address;
  400. if (ip_address.AssignFromIPLiteral(address)) {
  401. link_addresses.push_back(ip_address);
  402. } else {
  403. LOG(ERROR) << "Not a supported IP literal: " << address;
  404. }
  405. }
  406. GetTaskRunner()->PostTask(
  407. FROM_HERE, base::BindOnce(&HostResolver::SetNetworkAndLinkAddresses,
  408. base::Unretained(host_resolver_.get()),
  409. net_handle, std::move(link_addresses)));
  410. }
  411. static jlong JNI_AwPacProcessor_CreateNativePacProcessor(JNIEnv* env) {
  412. AwPacProcessor* processor = new AwPacProcessor();
  413. return reinterpret_cast<intptr_t>(processor);
  414. }
  415. static void JNI_AwPacProcessor_InitializeEnvironment(JNIEnv* env) {
  416. base::ThreadPoolInstance::CreateAndStartWithDefaultParams("AwPacProcessor");
  417. }
  418. } // namespace android_webview