1 // Copyright 2014 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 "base/android/jni_android.h"
6 #include "base/android/jni_string.h"
7 #include "base/functional/bind.h"
8 #include "base/memory/raw_ptr.h"
9 #include "components/cronet/android/cronet_test_apk_jni/MockUrlRequestJobFactory_jni.h"
10 #include "components/cronet/android/test/cronet_test_util.h"
11 #include "components/cronet/android/test/url_request_intercepting_job_factory.h"
12 #include "net/test/url_request/ssl_certificate_error_job.h"
13 #include "net/test/url_request/url_request_failed_job.h"
14 #include "net/test/url_request/url_request_hanging_read_job.h"
15 #include "net/test/url_request/url_request_mock_data_job.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_filter.h"
18 #include "url/gurl.h"
19
20 using base::android::JavaParamRef;
21 using base::android::ScopedJavaLocalRef;
22
23 namespace cronet {
24
25 // Intercept URLRequestJob creation using URLRequestFilter from
26 // libcronet_tests.so
27 class UrlInterceptorJobFactoryHandle {
28 public:
29 // |jcontext_adapter| points to a URLRequestContextAdapater.
UrlInterceptorJobFactoryHandle(jlong jcontext_adapter)30 UrlInterceptorJobFactoryHandle(jlong jcontext_adapter)
31 : jcontext_adapter_(jcontext_adapter) {
32 TestUtil::RunAfterContextInit(
33 jcontext_adapter,
34 base::BindOnce(&UrlInterceptorJobFactoryHandle::InitOnNetworkThread,
35 base::Unretained(this)));
36 }
37 // Should only be called on network thread; other threads should use
38 // ShutDown().
~UrlInterceptorJobFactoryHandle()39 ~UrlInterceptorJobFactoryHandle() {
40 DCHECK(
41 TestUtil::GetTaskRunner(jcontext_adapter_)->BelongsToCurrentThread());
42 TestUtil::GetURLRequestContext(jcontext_adapter_)
43 ->SetJobFactoryForTesting(old_job_factory_); // IN-TEST
44 }
45
ShutDown()46 void ShutDown() {
47 TestUtil::RunAfterContextInit(
48 jcontext_adapter_,
49 base::BindOnce(&UrlInterceptorJobFactoryHandle::ShutdownOnNetworkThread,
50 base::Unretained(this)));
51 }
52
53 private:
InitOnNetworkThread()54 void InitOnNetworkThread() {
55 net::URLRequestContext* request_context =
56 TestUtil::GetURLRequestContext(jcontext_adapter_);
57 old_job_factory_ = request_context->job_factory();
58 new_job_factory_.reset(new URLRequestInterceptingJobFactory(
59 const_cast<net::URLRequestJobFactory*>(old_job_factory_.get()),
60 net::URLRequestFilter::GetInstance()));
61 request_context->SetJobFactoryForTesting( // IN-TEST
62 new_job_factory_.get());
63 }
64
ShutdownOnNetworkThread()65 void ShutdownOnNetworkThread() { delete this; }
66
67 // The URLRequestContextAdapater this object intercepts from.
68 const jlong jcontext_adapter_;
69 // URLRequestJobFactory previously used in URLRequestContext.
70 raw_ptr<const net::URLRequestJobFactory> old_job_factory_;
71 // URLRequestJobFactory inserted during tests to intercept URLRequests with
72 // libcronet's URLRequestFilter.
73 std::unique_ptr<URLRequestInterceptingJobFactory> new_job_factory_;
74 };
75
76 // URL interceptors are registered with the URLRequestFilter in
77 // libcronet_tests.so. However tests are run on libcronet.so. Use the
78 // URLRequestFilter in libcronet_tests.so with the URLRequestContext in
79 // libcronet.so by installing a URLRequestInterceptingJobFactory
80 // that calls into libcronet_tests.so's URLRequestFilter.
JNI_MockUrlRequestJobFactory_AddUrlInterceptors(JNIEnv * env,jlong jcontext_adapter)81 jlong JNI_MockUrlRequestJobFactory_AddUrlInterceptors(
82 JNIEnv* env,
83 jlong jcontext_adapter) {
84 net::URLRequestMockDataJob::AddUrlHandler();
85 net::URLRequestFailedJob::AddUrlHandler();
86 net::URLRequestHangingReadJob::AddUrlHandler();
87 net::SSLCertificateErrorJob::AddUrlHandler();
88 return reinterpret_cast<jlong>(
89 new UrlInterceptorJobFactoryHandle(jcontext_adapter));
90 }
91
92 // Put back the old URLRequestJobFactory into the URLRequestContext.
JNI_MockUrlRequestJobFactory_RemoveUrlInterceptorJobFactory(JNIEnv * env,jlong jinterceptor_handle)93 void JNI_MockUrlRequestJobFactory_RemoveUrlInterceptorJobFactory(
94 JNIEnv* env,
95 jlong jinterceptor_handle) {
96 reinterpret_cast<UrlInterceptorJobFactoryHandle*>(jinterceptor_handle)
97 ->ShutDown();
98 }
99
JNI_MockUrlRequestJobFactory_GetMockUrlWithFailure(JNIEnv * jenv,jint jphase,jint jnet_error)100 ScopedJavaLocalRef<jstring> JNI_MockUrlRequestJobFactory_GetMockUrlWithFailure(
101 JNIEnv* jenv,
102 jint jphase,
103 jint jnet_error) {
104 GURL url(net::URLRequestFailedJob::GetMockHttpUrlWithFailurePhase(
105 static_cast<net::URLRequestFailedJob::FailurePhase>(jphase),
106 static_cast<int>(jnet_error)));
107 return base::android::ConvertUTF8ToJavaString(jenv, url.spec());
108 }
109
JNI_MockUrlRequestJobFactory_GetMockUrlForData(JNIEnv * jenv,const JavaParamRef<jstring> & jdata,jint jdata_repeat_count)110 ScopedJavaLocalRef<jstring> JNI_MockUrlRequestJobFactory_GetMockUrlForData(
111 JNIEnv* jenv,
112 const JavaParamRef<jstring>& jdata,
113 jint jdata_repeat_count) {
114 std::string data(base::android::ConvertJavaStringToUTF8(jenv, jdata));
115 GURL url(net::URLRequestMockDataJob::GetMockHttpUrl(data,
116 jdata_repeat_count));
117 return base::android::ConvertUTF8ToJavaString(jenv, url.spec());
118 }
119
120 ScopedJavaLocalRef<jstring>
JNI_MockUrlRequestJobFactory_GetMockUrlForSSLCertificateError(JNIEnv * jenv)121 JNI_MockUrlRequestJobFactory_GetMockUrlForSSLCertificateError(JNIEnv* jenv) {
122 GURL url(net::SSLCertificateErrorJob::GetMockUrl());
123 return base::android::ConvertUTF8ToJavaString(jenv, url.spec());
124 }
125
126 ScopedJavaLocalRef<jstring>
JNI_MockUrlRequestJobFactory_GetMockUrlForClientCertificateRequest(JNIEnv * jenv)127 JNI_MockUrlRequestJobFactory_GetMockUrlForClientCertificateRequest(
128 JNIEnv* jenv) {
129 GURL url(net::URLRequestMockDataJob::GetMockUrlForClientCertificateRequest());
130 return base::android::ConvertUTF8ToJavaString(jenv, url.spec());
131 }
132
133 ScopedJavaLocalRef<jstring>
JNI_MockUrlRequestJobFactory_GetMockUrlForHangingRead(JNIEnv * jenv)134 JNI_MockUrlRequestJobFactory_GetMockUrlForHangingRead(JNIEnv* jenv) {
135 GURL url(net::URLRequestHangingReadJob::GetMockHttpUrl());
136 return base::android::ConvertUTF8ToJavaString(jenv, url.spec());
137 }
138
139 } // namespace cronet
140