OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "native_test_server.h" | 5 #include "native_test_server.h" |
6 | 6 |
7 #include <string> | |
8 | |
7 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
8 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
9 #include "base/bind.h" | 11 #include "base/bind.h" |
10 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
11 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
12 #include "base/path_service.h" | 14 #include "base/path_service.h" |
13 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/strings/stringprintf.h" | |
17 #include "components/cronet/android/cronet_url_request_context_adapter.h" | |
18 #include "components/cronet/android/url_request_context_adapter.h" | |
14 #include "jni/NativeTestServer_jni.h" | 19 #include "jni/NativeTestServer_jni.h" |
20 #include "net/base/ip_endpoint.h" | |
21 #include "net/base/net_errors.h" | |
22 #include "net/dns/host_resolver_impl.h" | |
23 #include "net/dns/host_resolver_proc.h" | |
15 #include "net/http/http_status_code.h" | 24 #include "net/http/http_status_code.h" |
16 #include "net/test/embedded_test_server/embedded_test_server.h" | 25 #include "net/test/embedded_test_server/embedded_test_server.h" |
17 #include "net/test/embedded_test_server/http_request.h" | 26 #include "net/test/embedded_test_server/http_request.h" |
18 #include "net/test/embedded_test_server/http_response.h" | 27 #include "net/test/embedded_test_server/http_response.h" |
19 #include "url/gurl.h" | 28 #include "url/gurl.h" |
20 | 29 |
21 namespace cronet { | 30 namespace cronet { |
22 | 31 |
23 namespace { | 32 namespace { |
24 | 33 |
25 const char echo_body_path[] = "/echo_body"; | 34 const char echo_body_path[] = "/echo_body"; |
26 const char echo_header_path[] = "/echo_header"; | 35 const char echo_header_path[] = "/echo_header"; |
27 const char echo_all_headers_path[] = "/echo_all_headers"; | 36 const char echo_all_headers_path[] = "/echo_all_headers"; |
28 const char echo_method_path[] = "/echo_method"; | 37 const char echo_method_path[] = "/echo_method"; |
29 const char redirect_to_echo_body_path[] = "/redirect_to_echo_body"; | 38 const char redirect_to_echo_body_path[] = "/redirect_to_echo_body"; |
39 const char fake_sdch_domain[] = "fake.sdch.domain"; | |
40 // Path that advertises a dictionary if client supports Sdch encoding. | |
41 const char sdch_path[] = "/sdch"; | |
42 // Path that returns encoded response if client has the right dictionary. | |
43 const char sdch_test_path[] = "/sdch/test"; | |
30 | 44 |
31 net::test_server::EmbeddedTestServer* g_test_server = nullptr; | 45 net::test_server::EmbeddedTestServer* g_test_server = nullptr; |
32 | 46 |
33 scoped_ptr<net::test_server::HttpResponse> UploadServerRequestHandler( | 47 // HostResolverProc that binds |fake_sdch_domain| to localhost |
48 class LocalHostResolverProc : public net::HostResolverProc { | |
Elly Fong-Jones
2015/04/16 18:43:00
I think you want RuleBasedHostResolverProc here, t
xunjieli
2015/04/16 19:36:57
Done. Thanks! That's convenient :)
| |
49 public: | |
50 LocalHostResolverProc() : HostResolverProc(NULL) {} | |
51 | |
52 int Resolve(const std::string& host, | |
53 net::AddressFamily address_family, | |
54 net::HostResolverFlags host_resolver_flags, | |
55 net::AddressList* addrlist, | |
56 int* os_error) override { | |
57 DCHECK(g_test_server); | |
58 if (host == fake_sdch_domain) { | |
59 *addrlist = net::AddressList(); | |
60 net::IPAddressNumber localhost; | |
61 net::ParseIPLiteralToNumber("127.0.0.1", &localhost); | |
62 addrlist->push_back(net::IPEndPoint(localhost, 0)); | |
63 return net::OK; | |
64 } | |
65 return ResolveUsingPrevious(host, address_family, host_resolver_flags, | |
66 addrlist, os_error); | |
67 } | |
68 | |
69 private: | |
70 ~LocalHostResolverProc() override {} | |
71 }; | |
72 | |
73 scoped_ptr<net::test_server::HttpResponse> NativeTestServerRequestHandler( | |
34 const net::test_server::HttpRequest& request) { | 74 const net::test_server::HttpRequest& request) { |
35 DCHECK(g_test_server); | 75 DCHECK(g_test_server); |
36 scoped_ptr<net::test_server::BasicHttpResponse> response( | 76 scoped_ptr<net::test_server::BasicHttpResponse> response( |
37 new net::test_server::BasicHttpResponse()); | 77 new net::test_server::BasicHttpResponse()); |
38 response->set_content_type("text/plain"); | 78 response->set_content_type("text/plain"); |
39 | 79 |
40 if (request.relative_url == echo_body_path) { | 80 if (request.relative_url == echo_body_path) { |
41 if (request.has_content) { | 81 if (request.has_content) { |
42 response->set_content(request.content); | 82 response->set_content(request.content); |
43 } else { | 83 } else { |
(...skipping 22 matching lines...) Expand all Loading... | |
66 response->set_content(request.method_string); | 106 response->set_content(request.method_string); |
67 return response.Pass(); | 107 return response.Pass(); |
68 } | 108 } |
69 | 109 |
70 if (request.relative_url == redirect_to_echo_body_path) { | 110 if (request.relative_url == redirect_to_echo_body_path) { |
71 response->set_code(net::HTTP_TEMPORARY_REDIRECT); | 111 response->set_code(net::HTTP_TEMPORARY_REDIRECT); |
72 response->AddCustomHeader("Location", echo_body_path); | 112 response->AddCustomHeader("Location", echo_body_path); |
73 return response.Pass(); | 113 return response.Pass(); |
74 } | 114 } |
75 | 115 |
116 if (request.relative_url == sdch_path) { | |
117 auto it = request.headers.find("Accept-Encoding"); | |
118 if (it != request.headers.end()) { | |
119 if (it->second.find("sdch") != std::string::npos) | |
120 response->AddCustomHeader("Get-Dictionary", "/sdch/dict/LeQxM80O"); | |
mef
2015/04/16 16:04:20
Is it required by the spec to add 'Get-Dictionary'
xunjieli
2015/04/16 19:36:58
Yes, I believe so :) It reads "A compatible server
| |
121 } | |
122 response->set_content("The quick brown fox jumps over the lazy dog.\n"); | |
mef
2015/04/16 16:04:20
Could this be an explicit test data like 'sdch_pla
xunjieli
2015/04/16 19:36:58
Done. I named it index since it can be potentially
| |
123 return response.Pass(); | |
124 } | |
125 | |
126 if (StartsWithASCII(request.relative_url, sdch_test_path, true)) { | |
127 auto it = request.headers.find("Avail-Dictionary"); | |
128 if (it != request.headers.end()) { | |
mef
2015/04/16 16:04:20
Could this be just an explicit test data like 'sdc
xunjieli
2015/04/16 19:36:57
Done.
| |
129 if (it->second == "LeQxM80O") { | |
130 response->AddCustomHeader("Content-Encoding", "sdch"); | |
131 const unsigned char rawData[33] = { | |
132 0x59, 0x42, 0x36, 0x44, 0x58, 0x45, 0x2D, 0x68, 0x00, 0xD6, 0xC3, | |
133 0xC4, 0x53, 0x00, 0x05, 0x2E, 0x00, 0x0F, 0x2D, 0x00, 0x00, 0x05, | |
134 0x00, 0x87, 0xDE, 0xA4, 0xA0, 0x11, 0x73, 0x2C, 0x00, 0x02, 0x0A, | |
135 }; | |
136 std::string data(rawData, rawData + 33); | |
137 response->set_content(data); | |
138 } | |
139 } else { | |
140 response->set_content("Sdch is not used.\n"); | |
141 } | |
142 return response.Pass(); | |
143 } | |
144 | |
76 // Unhandled requests result in the Embedded test server sending a 404. | 145 // Unhandled requests result in the Embedded test server sending a 404. |
77 return scoped_ptr<net::test_server::BasicHttpResponse>(); | 146 return scoped_ptr<net::test_server::BasicHttpResponse>(); |
78 } | 147 } |
79 | 148 |
149 void RegisterHostResolverProcHelper( | |
150 net::URLRequestContext* url_request_context, | |
151 base::android::ScopedJavaGlobalRef<jobject>* callback) { | |
152 net::HostResolverImpl* resolver = | |
153 static_cast<net::HostResolverImpl*>(url_request_context->host_resolver()); | |
154 resolver->set_proc_params_for_test( | |
155 net::HostResolverImpl::ProcTaskParams(new LocalHostResolverProc(), 1u)); | |
156 JNIEnv* env = base::android::AttachCurrentThread(); | |
157 Java_NativeTestServer_onHostResolverProcRegistered(env, callback->obj()); | |
158 } | |
159 | |
160 void RegisterHostResolverProcOnNetworkThread( | |
161 CronetURLRequestContextAdapter* context_adapter, | |
162 base::android::ScopedJavaGlobalRef<jobject>* callback) { | |
163 net::URLRequestContext* context = context_adapter->GetURLRequestContext(); | |
164 RegisterHostResolverProcHelper(context, callback); | |
165 } | |
166 | |
167 void RegisterHostResolverProcOnNetworkThreadLegacyAPI( | |
mef
2015/04/16 16:04:20
maybe add TODO to remove this when we remove legac
xunjieli
2015/04/16 19:36:58
Done.
| |
168 URLRequestContextAdapter* context_adapter, | |
169 base::android::ScopedJavaGlobalRef<jobject>* callback) { | |
170 net::URLRequestContext* context = context_adapter->GetURLRequestContext(); | |
171 RegisterHostResolverProcHelper(context, callback); | |
172 } | |
173 | |
80 } // namespace | 174 } // namespace |
81 | 175 |
82 jboolean StartNativeTestServer(JNIEnv* env, | 176 jboolean StartNativeTestServer(JNIEnv* env, |
83 jclass jcaller, | 177 jclass jcaller, |
84 jstring jtest_files_root) { | 178 jstring jtest_files_root) { |
85 // Shouldn't happen. | 179 // Shouldn't happen. |
86 if (g_test_server) | 180 if (g_test_server) |
87 return false; | 181 return false; |
88 g_test_server = new net::test_server::EmbeddedTestServer(); | 182 g_test_server = new net::test_server::EmbeddedTestServer(); |
89 g_test_server->RegisterRequestHandler( | 183 g_test_server->RegisterRequestHandler( |
90 base::Bind(&UploadServerRequestHandler)); | 184 base::Bind(&NativeTestServerRequestHandler)); |
91 // Add a second handler for paths that UploadServerRequestHandler does not | 185 // Add a second handler for paths that NativeTestServerRequestHandler does not |
92 // handle. | 186 // handle. |
93 base::FilePath test_files_root( | 187 base::FilePath test_files_root( |
94 base::android::ConvertJavaStringToUTF8(env, jtest_files_root)); | 188 base::android::ConvertJavaStringToUTF8(env, jtest_files_root)); |
95 g_test_server->ServeFilesFromDirectory(test_files_root); | 189 g_test_server->ServeFilesFromDirectory(test_files_root); |
96 return g_test_server->InitializeAndWaitUntilReady(); | 190 return g_test_server->InitializeAndWaitUntilReady(); |
97 } | 191 } |
98 | 192 |
193 void RegisterHostResolverProc(JNIEnv* env, | |
194 jclass jcaller, | |
195 jlong jadapter, | |
196 jboolean jlegacy_api) { | |
197 DCHECK(!g_test_server); | |
198 base::android::ScopedJavaGlobalRef<jobject>* callback = | |
199 new base::android::ScopedJavaGlobalRef<jobject>(); | |
200 callback->Reset(env, jcaller); | |
201 if (jlegacy_api == JNI_TRUE) { | |
202 URLRequestContextAdapter* context_adapter = | |
203 reinterpret_cast<URLRequestContextAdapter*>(jadapter); | |
204 context_adapter->PostTaskToNetworkThread( | |
205 FROM_HERE, | |
206 base::Bind(&RegisterHostResolverProcOnNetworkThreadLegacyAPI, | |
207 base::Unretained(context_adapter), base::Owned(callback))); | |
208 } else { | |
209 CronetURLRequestContextAdapter* context_adapter = | |
210 reinterpret_cast<CronetURLRequestContextAdapter*>(jadapter); | |
211 context_adapter->PostTaskToNetworkThread( | |
212 FROM_HERE, | |
213 base::Bind(&RegisterHostResolverProcOnNetworkThread, | |
214 base::Unretained(context_adapter), base::Owned(callback))); | |
215 } | |
216 } | |
217 | |
99 void ShutdownNativeTestServer(JNIEnv* env, jclass jcaller) { | 218 void ShutdownNativeTestServer(JNIEnv* env, jclass jcaller) { |
100 if (!g_test_server) | 219 if (!g_test_server) |
101 return; | 220 return; |
102 delete g_test_server; | 221 delete g_test_server; |
103 g_test_server = NULL; | 222 g_test_server = NULL; |
104 } | 223 } |
105 | 224 |
106 jstring GetEchoBodyURL(JNIEnv* env, jclass jcaller) { | 225 jstring GetEchoBodyURL(JNIEnv* env, jclass jcaller) { |
107 DCHECK(g_test_server); | 226 DCHECK(g_test_server); |
108 GURL url = g_test_server->GetURL(echo_body_path); | 227 GURL url = g_test_server->GetURL(echo_body_path); |
(...skipping 28 matching lines...) Expand all Loading... | |
137 return base::android::ConvertUTF8ToJavaString(env, url.spec()).Release(); | 256 return base::android::ConvertUTF8ToJavaString(env, url.spec()).Release(); |
138 } | 257 } |
139 | 258 |
140 jstring GetFileURL(JNIEnv* env, jclass jcaller, jstring jfile_path) { | 259 jstring GetFileURL(JNIEnv* env, jclass jcaller, jstring jfile_path) { |
141 DCHECK(g_test_server); | 260 DCHECK(g_test_server); |
142 std::string file = base::android::ConvertJavaStringToUTF8(env, jfile_path); | 261 std::string file = base::android::ConvertJavaStringToUTF8(env, jfile_path); |
143 GURL url = g_test_server->GetURL(file); | 262 GURL url = g_test_server->GetURL(file); |
144 return base::android::ConvertUTF8ToJavaString(env, url.spec()).Release(); | 263 return base::android::ConvertUTF8ToJavaString(env, url.spec()).Release(); |
145 } | 264 } |
146 | 265 |
266 jstring GetSdchURL(JNIEnv* env, jclass jcaller) { | |
267 DCHECK(g_test_server); | |
268 std::string url(base::StringPrintf("http://%s:%d", fake_sdch_domain, | |
269 g_test_server->port())); | |
270 return base::android::ConvertUTF8ToJavaString(env, url).Release(); | |
271 } | |
272 | |
147 bool RegisterNativeTestServer(JNIEnv* env) { | 273 bool RegisterNativeTestServer(JNIEnv* env) { |
148 return RegisterNativesImpl(env); | 274 return RegisterNativesImpl(env); |
149 } | 275 } |
150 | 276 |
151 } // namespace cronet | 277 } // namespace cronet |
OLD | NEW |