| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/cronet/android/test/cronet_test_util.h" |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_array.h" |
| #include "base/android/jni_string.h" |
| #include "base/check.h" |
| #include "base/functional/bind.h" |
| #include "base/message_loop/message_pump.h" |
| #include "base/message_loop/message_pump_type.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "base/task/sequence_manager/sequence_manager.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/test/bind.h" |
| #include "components/cronet/android/cronet_context_adapter.h" |
| #include "components/cronet/android/cronet_url_request_adapter.h" |
| #include "components/cronet/cronet_context.h" |
| #include "components/cronet/cronet_url_request.h" |
| #include "net/http/http_server_properties.h" |
| #include "net/quic/quic_context.h" |
| #include "net/socket/socket_test_util.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_context.h" |
| |
| // Must come after all headers that specialize FromJniType() / ToJniType(). |
| #include "components/cronet/android/cronet_test_apk_jni/CronetTestUtil_jni.h" |
| #include "net/third_party/quiche/src/quiche/quic/core/quic_tag.h" |
| |
| namespace cronet { |
| namespace { |
| |
| using ::base::MessagePump; |
| using ::base::MessagePumpType; |
| using ::base::android::JavaParamRef; |
| using ::base::sequence_manager::SequenceManager; |
| |
| SequenceManager* g_sequence_manager = nullptr; |
| |
| } // namespace |
| |
| jint JNI_CronetTestUtil_GetLoadFlags(JNIEnv* env, |
| const jlong jurl_request_adapter) { |
| return TestUtil::GetURLRequest(jurl_request_adapter)->load_flags(); |
| } |
| |
| jboolean JNI_CronetTestUtil_URLRequestContextExistsForTesting( |
| JNIEnv* env, |
| jlong jcontext_adapter, |
| jlong jnetwork_handle) { |
| return TestUtil::GetURLRequestContexts(jcontext_adapter) |
| ->contains(jnetwork_handle); |
| } |
| |
| jni_zero::ScopedJavaLocalRef<jobjectArray> |
| JNI_CronetTestUtil_GetClientConnectionOptions(JNIEnv* env, |
| jlong jcontext_adapter) { |
| std::vector<std::string> quic_tags; |
| for (auto tag : TestUtil::GetDefaultURLRequestQuicParams(jcontext_adapter) |
| .client_connection_options) { |
| quic_tags.push_back(quic::QuicTagToString(tag)); |
| } |
| return base::android::ToJavaArrayOfStrings(env, std::move(quic_tags)); |
| } |
| |
| jni_zero::ScopedJavaLocalRef<jobjectArray> |
| JNI_CronetTestUtil_GetConnectionOptions(JNIEnv* env, jlong jcontext_adapter) { |
| std::vector<std::string> quic_tags; |
| for (auto tag : TestUtil::GetDefaultURLRequestQuicParams(jcontext_adapter) |
| .connection_options) { |
| quic_tags.push_back(quic::QuicTagToString(tag)); |
| } |
| return base::android::ToJavaArrayOfStrings(env, std::move(quic_tags)); |
| } |
| |
| // static |
| base::flat_map<net::handles::NetworkHandle, |
| std::unique_ptr<net::URLRequestContext>>* |
| TestUtil::GetURLRequestContexts(jlong jcontext_adapter) { |
| CronetContextAdapter* context_adapter = |
| reinterpret_cast<CronetContextAdapter*>(jcontext_adapter); |
| return &context_adapter->context_->network_tasks_->contexts_; |
| } |
| |
| // static |
| scoped_refptr<base::SingleThreadTaskRunner> TestUtil::GetTaskRunner( |
| jlong jcontext_adapter) { |
| CronetContextAdapter* context_adapter = |
| reinterpret_cast<CronetContextAdapter*>(jcontext_adapter); |
| return context_adapter->context_->network_task_runner_; |
| } |
| |
| // static |
| net::URLRequestContext* TestUtil::GetURLRequestContext(jlong jcontext_adapter) { |
| CronetContextAdapter* context_adapter = |
| reinterpret_cast<CronetContextAdapter*>(jcontext_adapter); |
| return context_adapter->context_->network_tasks_->default_context_; |
| } |
| |
| net::QuicParams& TestUtil::GetDefaultURLRequestQuicParams( |
| jlong jcontext_adapter) { |
| net::URLRequestContext* context; |
| base::WaitableEvent callback_executed; |
| CronetContextAdapter& context_adapter = |
| *reinterpret_cast<CronetContextAdapter*>(jcontext_adapter); |
| RunAfterContextInit(jcontext_adapter, base::BindLambdaForTesting([&] { |
| context = |
| context_adapter.context_->GetURLRequestContext( |
| net::handles::kInvalidNetworkHandle); |
| callback_executed.Signal(); |
| })); |
| callback_executed.Wait(); |
| CHECK(context); |
| return *context->quic_context()->params(); |
| } |
| |
| // static |
| void TestUtil::RunAfterContextInitOnNetworkThread(jlong jcontext_adapter, |
| base::OnceClosure task) { |
| CronetContextAdapter* context_adapter = |
| reinterpret_cast<CronetContextAdapter*>(jcontext_adapter); |
| if (context_adapter->context_->network_tasks_ |
| ->is_default_context_initialized_) { |
| std::move(task).Run(); |
| } else { |
| context_adapter->context_->network_tasks_->tasks_waiting_for_context_.push( |
| std::move(task)); |
| } |
| } |
| |
| // static |
| void TestUtil::RunAfterContextInit(jlong jcontext_adapter, |
| base::OnceClosure task) { |
| GetTaskRunner(jcontext_adapter) |
| ->PostTask(FROM_HERE, |
| base::BindOnce(&TestUtil::RunAfterContextInitOnNetworkThread, |
| jcontext_adapter, std::move(task))); |
| } |
| |
| // static |
| net::URLRequest* TestUtil::GetURLRequest(jlong jrequest_adapter) { |
| CronetURLRequestAdapter* request_adapter = |
| reinterpret_cast<CronetURLRequestAdapter*>(jrequest_adapter); |
| return request_adapter->request_->network_tasks_.url_request_.get(); |
| } |
| |
| static void PrepareNetworkThreadOnNetworkThread(jlong jcontext_adapter) { |
| g_sequence_manager = |
| base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump( |
| MessagePump::Create(MessagePumpType::IO), |
| SequenceManager::Settings::Builder() |
| .SetMessagePumpType(MessagePumpType::IO) |
| .Build()) |
| .release(); |
| g_sequence_manager->SetDefaultTaskRunner( |
| TestUtil::GetTaskRunner(jcontext_adapter)); |
| } |
| |
| // Tests need to call into libcronet.so code on libcronet.so threads. |
| // libcronet.so's threads are registered with static tables for MessageLoops |
| // and SingleThreadTaskRunners in libcronet.so, so libcronet_test.so |
| // functions that try and access these tables will find missing entries in |
| // the corresponding static tables in libcronet_test.so. Fix this by |
| // initializing a MessageLoop and SingleThreadTaskRunner in libcronet_test.so |
| // for these threads. Called from Java CronetTestUtil class. |
| void JNI_CronetTestUtil_PrepareNetworkThread(JNIEnv* env, |
| jlong jcontext_adapter) { |
| TestUtil::GetTaskRunner(jcontext_adapter) |
| ->PostTask(FROM_HERE, base::BindOnce(&PrepareNetworkThreadOnNetworkThread, |
| jcontext_adapter)); |
| } |
| |
| static void CleanupNetworkThreadOnNetworkThread() { |
| DCHECK(g_sequence_manager); |
| delete g_sequence_manager; |
| g_sequence_manager = nullptr; |
| } |
| |
| // Called from Java CronetTestUtil class. |
| void JNI_CronetTestUtil_CleanupNetworkThread(JNIEnv* env, |
| jlong jcontext_adapter) { |
| TestUtil::RunAfterContextInit( |
| jcontext_adapter, base::BindOnce(&CleanupNetworkThreadOnNetworkThread)); |
| } |
| |
| jboolean JNI_CronetTestUtil_CanGetTaggedBytes(JNIEnv* env) { |
| return net::CanGetTaggedBytes(); |
| } |
| |
| jlong JNI_CronetTestUtil_GetTaggedBytes(JNIEnv* env, jint jexpected_tag) { |
| return net::GetTaggedBytes(jexpected_tag); |
| } |
| |
| } // namespace cronet |