blob: 54b4a12a4e9f6cb831f8b3dc66c43312575e1949 [file] [log] [blame]
mef2028ab742014-09-12 15:16:431// Copyright 2014 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
mef63643db2015-02-10 02:18:255#include <jni.h>
Misha Efimov1770a1b2018-01-11 15:27:276#include <memory>
7#include <string>
8#include <utility>
mef63643db2015-02-10 02:18:259
michaelbai0c7df61f2015-03-10 17:57:0410#include "base/android/base_jni_onload.h"
Paul Jensenfccbefe2018-06-25 16:23:4411#include "base/android/build_info.h"
mef2028ab742014-09-12 15:16:4312#include "base/android/jni_android.h"
13#include "base/android/jni_registrar.h"
Yaron Friedman8d84b832017-08-22 17:30:1914#include "base/android/jni_string.h"
xunjieli3b8f5682015-02-24 18:22:5915#include "base/android/jni_utils.h"
michaelbai0c7df61f2015-03-10 17:57:0416#include "base/android/library_loader/library_loader_hooks.h"
Hans Wennborgdf87046c2020-04-28 11:06:2417#include "base/check_op.h"
kapishnikov3180f532016-06-29 17:39:5018#include "base/feature_list.h"
Carlos Caballerodd8bf7b042019-07-30 14:14:1519#include "base/message_loop/message_pump_type.h"
Misha Efimovd4ab38302018-01-30 23:56:4220#include "base/synchronization/waitable_event.h"
Carlos Caballerob25fe8472020-07-17 10:27:1721#include "base/task/current_thread.h"
Alex Clarkef7fb8a82019-06-06 15:41:5322#include "base/task/single_thread_task_executor.h"
Gabriel Charetteeadf58862019-08-29 05:20:2723#include "base/task/thread_pool/thread_pool_instance.h"
Paul Jensenfccbefe2018-06-25 16:23:4424#include "build/build_config.h"
Shenghuai Ji9e1d2ed2018-07-26 00:51:3025#include "components/cronet/android/buildflags.h"
Mohamed Heikalbd641312019-06-22 00:14:3726#include "components/cronet/android/cronet_jni_headers/CronetLibraryLoader_jni.h"
Misha Efimov1770a1b2018-01-11 15:27:2727#include "components/cronet/cronet_global_state.h"
xunjieli6f35690c2015-06-04 20:53:2328#include "components/cronet/version.h"
mef63643db2015-02-10 02:18:2529#include "net/android/network_change_notifier_factory_android.h"
30#include "net/base/network_change_notifier.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5631#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4032#include "net/proxy_resolution/proxy_config_service_android.h"
Paul Jensenfccbefe2018-06-25 16:23:4433#include "third_party/zlib/zlib.h"
Scott Violetfd6ee112019-01-10 19:05:3234#include "url/buildflags.h"
mef2028ab742014-09-12 15:16:4335
torned8b7d9252016-08-04 19:41:4536#if !BUILDFLAG(USE_PLATFORM_ICU_ALTERNATIVES)
mgershf3e57312016-06-01 21:55:0037#include "base/i18n/icu_util.h" // nogncheck
mef2028ab742014-09-12 15:16:4338#endif
39
Shenghuai Ji9e1d2ed2018-07-26 00:51:3040#if !BUILDFLAG(INTEGRATED_MODE)
41#include "components/cronet/android/cronet_jni_registration.h"
42#include "components/cronet/android/cronet_library_loader.h"
43#endif
44
tornebc8890f2016-08-05 11:48:4445using base::android::JavaParamRef;
46using base::android::ScopedJavaLocalRef;
47
mef2028ab742014-09-12 15:16:4348namespace cronet {
49namespace {
50
Alex Clarkef7fb8a82019-06-06 15:41:5351// SingleThreadTaskExecutor on the init thread, which is where objects that
52// receive Java notifications generally live.
53base::SingleThreadTaskExecutor* g_init_task_executor = nullptr;
mef63643db2015-02-10 02:18:2554
Shenghuai Ji9e1d2ed2018-07-26 00:51:3055#if !BUILDFLAG(INTEGRATED_MODE)
Erik Andersonca163bb92019-06-18 16:10:4856std::unique_ptr<net::NetworkChangeNotifier> g_network_change_notifier;
Shenghuai Ji9e1d2ed2018-07-26 00:51:3057#endif
mef2028ab742014-09-12 15:16:4358
Misha Efimovd4ab38302018-01-30 23:56:4259base::WaitableEvent g_init_thread_init_done(
60 base::WaitableEvent::ResetPolicy::MANUAL,
61 base::WaitableEvent::InitialState::NOT_SIGNALED);
62
63void NativeInit() {
Paul Jensena6d848cb2018-10-17 19:22:4764// In integrated mode, ICU and FeatureList has been initialized by the host.
65#if !BUILDFLAG(INTEGRATED_MODE)
66#if !BUILDFLAG(USE_PLATFORM_ICU_ALTERNATIVES)
67 base::i18n::InitializeICU();
68#endif
69 base::FeatureList::InitializeInstance(std::string(), std::string());
70#endif
71
Gabriel Charette43fd3702019-05-29 16:36:5172 if (!base::ThreadPoolInstance::Get())
73 base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Cronet");
michaelbai0c7df61f2015-03-10 17:57:0474}
75
mef2028ab742014-09-12 15:16:4376} // namespace
77
pauljensen6815aef2017-05-05 03:00:0678bool OnInitThread() {
Alex Clarkef7fb8a82019-06-06 15:41:5379 DCHECK(g_init_task_executor);
80 return g_init_task_executor->task_runner()->RunsTasksInCurrentSequence();
pauljensen6815aef2017-05-05 03:00:0681}
82
Shenghuai Ji9e1d2ed2018-07-26 00:51:3083// In integrated mode, Cronet native library is built and loaded together with
84// the native library of the host app.
85#if !BUILDFLAG(INTEGRATED_MODE)
mef2028ab742014-09-12 15:16:4386// Checks the available version of JNI. Also, caches Java reflection artifacts.
87jint CronetOnLoad(JavaVM* vm, void* reserved) {
tobiasjsb9e287e2017-02-08 11:09:5088 base::android::InitVM(vm);
89 JNIEnv* env = base::android::AttachCurrentThread();
Yipeng Wang158dbc5c2017-06-30 18:16:4190 if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) {
91 return -1;
92 }
Misha Efimovd4ab38302018-01-30 23:56:4293 if (!base::android::OnJNIOnLoadInit())
mef2028ab742014-09-12 15:16:4394 return -1;
Misha Efimovd4ab38302018-01-30 23:56:4295 NativeInit();
mef2028ab742014-09-12 15:16:4396 return JNI_VERSION_1_6;
97}
98
99void CronetOnUnLoad(JavaVM* jvm, void* reserved) {
Gabriel Charette43fd3702019-05-29 16:36:51100 if (base::ThreadPoolInstance::Get())
101 base::ThreadPoolInstance::Get()->Shutdown();
Eric Roman3e3c14a2017-07-07 21:49:10102
michaelbai0c7df61f2015-03-10 17:57:04103 base::android::LibraryLoaderExitHook();
mef2028ab742014-09-12 15:16:43104}
Shenghuai Ji9e1d2ed2018-07-26 00:51:30105#endif
mef2028ab742014-09-12 15:16:43106
Aiden Bennerc99e9052018-11-30 20:50:50107void JNI_CronetLibraryLoader_CronetInitOnInitThread(JNIEnv* env) {
Alex Clarkef7fb8a82019-06-06 15:41:53108 // Initialize SingleThreadTaskExecutor for init thread.
Carlos Caballerob25fe8472020-07-17 10:27:17109 DCHECK(!base::CurrentThread::IsSet());
Alex Clarkef7fb8a82019-06-06 15:41:53110 DCHECK(!g_init_task_executor);
111 g_init_task_executor =
Carlos Caballerodd8bf7b042019-07-30 14:14:15112 new base::SingleThreadTaskExecutor(base::MessagePumpType::JAVA);
Pengchengeaf5ae22018-01-18 01:57:17113
Shenghuai Ji9e1d2ed2018-07-26 00:51:30114// In integrated mode, NetworkChangeNotifier has been initialized by the host.
115#if BUILDFLAG(INTEGRATED_MODE)
Min Qin04545212019-11-06 01:10:49116 CHECK(!net::NetworkChangeNotifier::CreateIfNeeded());
Shenghuai Ji9e1d2ed2018-07-26 00:51:30117#else
118 DCHECK(!g_network_change_notifier);
Pengchengeaf5ae22018-01-18 01:57:17119 if (!net::NetworkChangeNotifier::GetFactory()) {
120 net::NetworkChangeNotifier::SetFactory(
121 new net::NetworkChangeNotifierFactoryAndroid());
122 }
Min Qin04545212019-11-06 01:10:49123 g_network_change_notifier = net::NetworkChangeNotifier::CreateIfNeeded();
124 DCHECK(g_network_change_notifier);
Shenghuai Ji9e1d2ed2018-07-26 00:51:30125#endif
126
Misha Efimovd4ab38302018-01-30 23:56:42127 g_init_thread_init_done.Signal();
mef63643db2015-02-10 02:18:25128}
129
Daniel Bratell7aacf952017-11-21 17:51:25130ScopedJavaLocalRef<jstring> JNI_CronetLibraryLoader_GetCronetVersion(
Aiden Bennerc99e9052018-11-30 20:50:50131 JNIEnv* env) {
Paul Jensenfccbefe2018-06-25 16:23:44132#if defined(ARCH_CPU_ARM64)
133 // Attempt to avoid crashes on some ARM64 Marshmallow devices by
134 // prompting zlib ARM feature detection early on. https://crbug.com/853725
135 if (base::android::BuildInfo::GetInstance()->sdk_int() ==
136 base::android::SDK_VERSION_MARSHMALLOW) {
137 crc32(0, Z_NULL, 0);
138 }
139#endif
tornef71efb32015-08-26 14:07:32140 return base::android::ConvertUTF8ToJavaString(env, CRONET_VERSION);
xunjieli6f35690c2015-06-04 20:53:23141}
142
Misha Efimovd4ab38302018-01-30 23:56:42143void PostTaskToInitThread(const base::Location& posted_from,
144 base::OnceClosure task) {
145 g_init_thread_init_done.Wait();
Alex Clarkef7fb8a82019-06-06 15:41:53146 g_init_task_executor->task_runner()->PostTask(posted_from, std::move(task));
Misha Efimovd4ab38302018-01-30 23:56:42147}
148
149void EnsureInitialized() {
Alex Clarkef7fb8a82019-06-06 15:41:53150 if (g_init_task_executor) {
Misha Efimovd4ab38302018-01-30 23:56:42151 // Ensure that init is done on the init thread.
152 g_init_thread_init_done.Wait();
153 return;
154 }
155
156 // The initialization can only be done once, so static |s_run_once| variable
157 // is used to do it in the constructor.
158 static class RunOnce {
159 public:
160 RunOnce() {
161 NativeInit();
162 JNIEnv* env = base::android::AttachCurrentThread();
163 // Ensure initialized from Java side to properly create Init thread.
164 cronet::Java_CronetLibraryLoader_ensureInitializedFromNative(env);
165 }
166 } s_run_once;
167}
168
Misha Efimov1770a1b2018-01-11 15:27:27169std::unique_ptr<net::ProxyConfigService> CreateProxyConfigService(
170 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
171 std::unique_ptr<net::ProxyConfigService> service =
Nicolas Arciniegad2013f92020-02-07 23:00:56172 net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService(
173 io_task_runner);
Misha Efimov1770a1b2018-01-11 15:27:27174 // If a PAC URL is present, ignore it and use the address and port of
175 // Android system's local HTTP proxy server. See: crbug.com/432539.
176 // TODO(csharrison) Architect the wrapper better so we don't need to cast for
177 // android ProxyConfigServices.
178 net::ProxyConfigServiceAndroid* android_proxy_config_service =
179 static_cast<net::ProxyConfigServiceAndroid*>(service.get());
180 android_proxy_config_service->set_exclude_pac_url(true);
181 return service;
182}
183
Lily Houghtond567e862018-03-27 16:37:18184// Creates a proxy resolution service appropriate for this platform.
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26185std::unique_ptr<net::ProxyResolutionService> CreateProxyResolutionService(
Misha Efimov1770a1b2018-01-11 15:27:27186 std::unique_ptr<net::ProxyConfigService> proxy_config_service,
187 net::NetLog* net_log) {
188 // Android provides a local HTTP proxy server that handles proxying when a PAC
189 // URL is present. Create a proxy service without a resolver and rely on this
190 // local HTTP proxy. See: crbug.com/432539.
Nicolas Arciniegad2013f92020-02-07 23:00:56191 return net::ConfiguredProxyResolutionService::CreateWithoutProxyResolver(
Misha Efimov1770a1b2018-01-11 15:27:27192 std::move(proxy_config_service), net_log);
193}
194
Misha Efimovd4ab38302018-01-30 23:56:42195// Creates default User-Agent request value, combining optional
196// |partial_user_agent| with system-dependent values.
197std::string CreateDefaultUserAgent(const std::string& partial_user_agent) {
198 // Cronet global state must be initialized to include application info
199 // into default user agent
200 cronet::EnsureInitialized();
201
202 JNIEnv* env = base::android::AttachCurrentThread();
203 std::string user_agent = base::android::ConvertJavaStringToUTF8(
204 cronet::Java_CronetLibraryLoader_getDefaultUserAgent(env));
205 if (!partial_user_agent.empty())
206 user_agent.insert(user_agent.size() - 1, "; " + partial_user_agent);
207 return user_agent;
208}
209
Paul Jensen6a1ea3a2018-08-24 14:46:41210void SetNetworkThreadPriorityOnNetworkThread(double priority) {
211 int priority_int = priority;
212 DCHECK_LE(priority_int, 19);
213 DCHECK_GE(priority_int, -20);
214 if (priority_int >= -20 && priority_int <= 19) {
215 JNIEnv* env = base::android::AttachCurrentThread();
216 cronet::Java_CronetLibraryLoader_setNetworkThreadPriorityOnNetworkThread(
217 env, priority_int);
218 }
219}
220
mef2028ab742014-09-12 15:16:43221} // namespace cronet