OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 | |
5 #include "content/child/url_loader_client_impl.h" | |
6 | |
7 #include "base/memory/ptr_util.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "base/run_loop.h" | |
10 #include "content/child/resource_dispatcher.h" | |
11 #include "content/child/test_request_peer.h" | |
12 #include "content/common/url_loader_factory.mojom.h" | |
13 #include "ipc/ipc_sender.h" | |
14 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" | |
15 #include "mojo/public/cpp/bindings/binding.h" | |
16 #include "net/url_request/redirect_info.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 namespace content { | |
20 | |
21 class URLLoaderClientImplTest : public ::testing::Test, | |
22 IPC::Sender, | |
23 mojom::URLLoaderFactory { | |
24 protected: | |
25 URLLoaderClientImplTest() | |
26 : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())), | |
27 mojo_binding_(this) { | |
28 url_loader_factory_proxy_ = mojo_binding_.CreateInterfacePtrAndBind(); | |
29 | |
30 request_id_ = dispatcher_->StartAsync( | |
31 base::MakeUnique<ResourceRequest>(), 0, nullptr, url::Origin(), | |
32 base::MakeUnique<TestRequestPeer>(dispatcher_.get(), | |
33 &request_peer_context_), | |
34 blink::WebURLRequest::LoadingIPCType::Mojo, | |
35 url_loader_factory_proxy_.get(), | |
36 url_loader_factory_proxy_.associated_group()); | |
37 request_peer_context_.request_id = request_id_; | |
38 | |
39 base::RunLoop().RunUntilIdle(); | |
40 EXPECT_TRUE(url_loader_client_); | |
41 } | |
42 | |
43 void TearDown() override { | |
44 url_loader_client_ = nullptr; | |
45 url_loader_factory_proxy_ = nullptr; | |
46 } | |
47 | |
48 bool Send(IPC::Message* message) override { | |
49 ADD_FAILURE() << "IPC::Sneder::Send should not be called."; | |
kinuko
2016/12/22 07:54:48
Sneder -> Sender
yhirano
2016/12/22 08:03:32
Done.
| |
50 return false; | |
51 } | |
52 | |
53 void CreateLoaderAndStart( | |
54 mojom::URLLoaderAssociatedRequest request, | |
55 int32_t routing_id, | |
56 int32_t request_id, | |
57 const ResourceRequest& url_request, | |
58 mojom::URLLoaderClientAssociatedPtrInfo client_ptr_info) override { | |
59 url_loader_client_.Bind(std::move(client_ptr_info)); | |
60 } | |
61 | |
62 void SyncLoad(int32_t routing_id, | |
63 int32_t request_id, | |
64 const ResourceRequest& request, | |
65 const SyncLoadCallback& callback) override { | |
66 NOTREACHED(); | |
67 } | |
68 | |
69 static MojoCreateDataPipeOptions dataPipeOptions() { | |
kinuko
2016/12/22 07:54:48
DataPipeOptions()
yhirano
2016/12/22 08:03:32
Done.
| |
70 MojoCreateDataPipeOptions options; | |
71 options.struct_size = sizeof(MojoCreateDataPipeOptions); | |
72 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
73 options.element_num_bytes = 1; | |
74 options.capacity_num_bytes = 4096; | |
75 return options; | |
76 } | |
77 | |
78 base::MessageLoop message_loop_; | |
79 std::unique_ptr<ResourceDispatcher> dispatcher_; | |
80 TestRequestPeer::Context request_peer_context_; | |
81 int request_id_ = 0; | |
82 mojom::URLLoaderClientAssociatedPtr url_loader_client_; | |
83 mojom::URLLoaderFactoryPtr url_loader_factory_proxy_; | |
84 mojo::Binding<mojom::URLLoaderFactory> mojo_binding_; | |
85 }; | |
86 | |
87 TEST_F(URLLoaderClientImplTest, OnReceiveResponse) { | |
88 ResourceResponseHead response_head; | |
89 | |
90 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
91 | |
92 EXPECT_FALSE(request_peer_context_.received_response); | |
93 base::RunLoop().RunUntilIdle(); | |
94 EXPECT_TRUE(request_peer_context_.received_response); | |
95 } | |
96 | |
97 TEST_F(URLLoaderClientImplTest, ResponseBody) { | |
98 ResourceResponseHead response_head; | |
99 | |
100 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
101 | |
102 EXPECT_FALSE(request_peer_context_.received_response); | |
103 base::RunLoop().RunUntilIdle(); | |
104 EXPECT_TRUE(request_peer_context_.received_response); | |
105 | |
106 mojo::DataPipe data_pipe(dataPipeOptions()); | |
107 url_loader_client_->OnStartLoadingResponseBody( | |
108 std::move(data_pipe.consumer_handle)); | |
109 uint32_t size = 5; | |
110 MojoResult result = | |
111 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
112 MOJO_WRITE_DATA_FLAG_NONE); | |
113 ASSERT_EQ(MOJO_RESULT_OK, result); | |
114 EXPECT_EQ(5u, size); | |
115 | |
116 base::RunLoop().RunUntilIdle(); | |
117 EXPECT_EQ("hello", request_peer_context_.data); | |
118 } | |
119 | |
120 // OnStartLoadingResponseBody can be called before OnReceiveResponse. Because | |
121 // of the lack of the ordering guarantee between the message channel and the | |
122 // data pipe, bytes can arrive before OnReceiveResponse. URLLoaderClientImpl | |
123 // should restore the order. | |
124 TEST_F(URLLoaderClientImplTest, ResponseBodyShouldComeAfterResponse) { | |
125 ResourceResponseHead response_head; | |
126 | |
127 mojo::DataPipe data_pipe(dataPipeOptions()); | |
128 url_loader_client_->OnStartLoadingResponseBody( | |
129 std::move(data_pipe.consumer_handle)); | |
130 uint32_t size = 5; | |
131 MojoResult result = | |
132 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
133 MOJO_WRITE_DATA_FLAG_NONE); | |
134 ASSERT_EQ(MOJO_RESULT_OK, result); | |
135 EXPECT_EQ(5u, size); | |
136 | |
137 base::RunLoop().RunUntilIdle(); | |
138 EXPECT_EQ("", request_peer_context_.data); | |
139 | |
140 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
141 | |
142 EXPECT_FALSE(request_peer_context_.received_response); | |
143 EXPECT_EQ("", request_peer_context_.data); | |
144 base::RunLoop().RunUntilIdle(); | |
145 EXPECT_TRUE(request_peer_context_.received_response); | |
146 EXPECT_EQ("hello", request_peer_context_.data); | |
147 } | |
148 | |
149 TEST_F(URLLoaderClientImplTest, OnReceiveRedirect) { | |
150 ResourceResponseHead response_head; | |
151 net::RedirectInfo redirect_info; | |
152 | |
153 url_loader_client_->OnReceiveRedirect(redirect_info, response_head); | |
154 | |
155 EXPECT_EQ(0, request_peer_context_.seen_redirects); | |
156 base::RunLoop().RunUntilIdle(); | |
157 EXPECT_EQ(1, request_peer_context_.seen_redirects); | |
158 } | |
159 | |
160 TEST_F(URLLoaderClientImplTest, OnDataDownloaded) { | |
161 ResourceResponseHead response_head; | |
162 | |
163 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
164 url_loader_client_->OnDataDownloaded(8, 13); | |
165 url_loader_client_->OnDataDownloaded(2, 1); | |
166 | |
167 EXPECT_FALSE(request_peer_context_.received_response); | |
168 EXPECT_EQ(0, request_peer_context_.total_downloaded_data_length); | |
169 EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); | |
170 base::RunLoop().RunUntilIdle(); | |
171 EXPECT_TRUE(request_peer_context_.received_response); | |
172 EXPECT_EQ(10, request_peer_context_.total_downloaded_data_length); | |
173 EXPECT_EQ(14, request_peer_context_.total_encoded_data_length); | |
174 } | |
175 | |
176 TEST_F(URLLoaderClientImplTest, OnTransferSizeUpdated) { | |
177 ResourceResponseHead response_head; | |
178 | |
179 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
180 url_loader_client_->OnTransferSizeUpdated(4); | |
181 url_loader_client_->OnTransferSizeUpdated(4); | |
182 | |
183 EXPECT_FALSE(request_peer_context_.received_response); | |
184 EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); | |
185 base::RunLoop().RunUntilIdle(); | |
186 EXPECT_TRUE(request_peer_context_.received_response); | |
187 EXPECT_EQ(8, request_peer_context_.total_encoded_data_length); | |
188 } | |
189 | |
190 TEST_F(URLLoaderClientImplTest, OnCompleteWithoutResponseBody) { | |
191 ResourceResponseHead response_head; | |
192 ResourceRequestCompletionStatus completion_status; | |
193 | |
194 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
195 url_loader_client_->OnComplete(completion_status); | |
196 | |
197 EXPECT_FALSE(request_peer_context_.received_response); | |
198 EXPECT_FALSE(request_peer_context_.complete); | |
199 base::RunLoop().RunUntilIdle(); | |
200 EXPECT_TRUE(request_peer_context_.received_response); | |
201 EXPECT_TRUE(request_peer_context_.complete); | |
202 } | |
203 | |
204 TEST_F(URLLoaderClientImplTest, OnCompleteWithResponseBody) { | |
205 ResourceResponseHead response_head; | |
206 ResourceRequestCompletionStatus completion_status; | |
207 | |
208 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
209 mojo::DataPipe data_pipe(dataPipeOptions()); | |
210 url_loader_client_->OnStartLoadingResponseBody( | |
211 std::move(data_pipe.consumer_handle)); | |
212 uint32_t size = 5; | |
213 MojoResult result = | |
214 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
215 MOJO_WRITE_DATA_FLAG_NONE); | |
216 ASSERT_EQ(MOJO_RESULT_OK, result); | |
217 EXPECT_EQ(5u, size); | |
218 data_pipe.producer_handle.reset(); | |
219 | |
220 EXPECT_FALSE(request_peer_context_.received_response); | |
221 EXPECT_EQ("", request_peer_context_.data); | |
222 base::RunLoop().RunUntilIdle(); | |
223 EXPECT_TRUE(request_peer_context_.received_response); | |
224 EXPECT_EQ("hello", request_peer_context_.data); | |
225 | |
226 url_loader_client_->OnComplete(completion_status); | |
227 | |
228 EXPECT_FALSE(request_peer_context_.complete); | |
229 base::RunLoop().RunUntilIdle(); | |
230 | |
231 EXPECT_TRUE(request_peer_context_.received_response); | |
232 EXPECT_EQ("hello", request_peer_context_.data); | |
233 EXPECT_TRUE(request_peer_context_.complete); | |
234 } | |
235 | |
236 // Due to the lack of ordering guarantee, it is possible that the response body | |
237 // bytes arrives after the completion message. URLLoaderClientImpl should | |
238 // restore the order. | |
239 TEST_F(URLLoaderClientImplTest, OnCompleteShouldBeTheLastMessage) { | |
240 ResourceResponseHead response_head; | |
241 ResourceRequestCompletionStatus completion_status; | |
242 | |
243 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
244 mojo::DataPipe data_pipe(dataPipeOptions()); | |
245 url_loader_client_->OnStartLoadingResponseBody( | |
246 std::move(data_pipe.consumer_handle)); | |
247 url_loader_client_->OnComplete(completion_status); | |
248 | |
249 base::RunLoop().RunUntilIdle(); | |
250 EXPECT_TRUE(request_peer_context_.received_response); | |
251 EXPECT_FALSE(request_peer_context_.complete); | |
252 | |
253 uint32_t size = 5; | |
254 MojoResult result = | |
255 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
256 MOJO_WRITE_DATA_FLAG_NONE); | |
257 ASSERT_EQ(MOJO_RESULT_OK, result); | |
258 EXPECT_EQ(5u, size); | |
259 | |
260 base::RunLoop().RunUntilIdle(); | |
261 EXPECT_EQ("hello", request_peer_context_.data); | |
262 EXPECT_FALSE(request_peer_context_.complete); | |
263 | |
264 data_pipe.producer_handle.reset(); | |
265 base::RunLoop().RunUntilIdle(); | |
266 EXPECT_EQ("hello", request_peer_context_.data); | |
267 EXPECT_TRUE(request_peer_context_.complete); | |
268 } | |
269 | |
270 // Cancelling a request in a client method should be handled correctly. | |
271 TEST_F(URLLoaderClientImplTest, Cancel1) { | |
272 request_peer_context_.cancel_on_receive_response = true; | |
273 | |
274 ResourceResponseHead response_head; | |
275 ResourceRequestCompletionStatus completion_status; | |
276 | |
277 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
278 mojo::DataPipe data_pipe(dataPipeOptions()); | |
279 url_loader_client_->OnStartLoadingResponseBody( | |
280 std::move(data_pipe.consumer_handle)); | |
281 url_loader_client_->OnComplete(completion_status); | |
282 | |
283 EXPECT_FALSE(request_peer_context_.received_response); | |
284 EXPECT_FALSE(request_peer_context_.complete); | |
285 EXPECT_FALSE(request_peer_context_.cancelled); | |
286 | |
287 base::RunLoop().RunUntilIdle(); | |
288 EXPECT_TRUE(request_peer_context_.received_response); | |
289 EXPECT_FALSE(request_peer_context_.complete); | |
290 EXPECT_TRUE(request_peer_context_.cancelled); | |
291 } | |
292 | |
293 // Cancelling a request in a client method should be handled correctly. | |
294 TEST_F(URLLoaderClientImplTest, Cancel2) { | |
kinuko
2016/12/22 07:54:48
Could Cancel1, Cancel2, Cancel3 be given slightly
yhirano
2016/12/22 08:03:32
Done.
| |
295 request_peer_context_.cancel_on_receive_response = true; | |
296 | |
297 ResourceResponseHead response_head; | |
298 ResourceRequestCompletionStatus completion_status; | |
299 | |
300 mojo::DataPipe data_pipe(dataPipeOptions()); | |
301 uint32_t size = 5; | |
302 MojoResult result = | |
303 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
304 MOJO_WRITE_DATA_FLAG_NONE); | |
305 ASSERT_EQ(MOJO_RESULT_OK, result); | |
306 EXPECT_EQ(5u, size); | |
307 | |
308 url_loader_client_->OnStartLoadingResponseBody( | |
309 std::move(data_pipe.consumer_handle)); | |
310 base::RunLoop().RunUntilIdle(); | |
311 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
312 url_loader_client_->OnComplete(completion_status); | |
313 | |
314 EXPECT_FALSE(request_peer_context_.received_response); | |
315 EXPECT_FALSE(request_peer_context_.complete); | |
316 EXPECT_FALSE(request_peer_context_.cancelled); | |
317 | |
318 base::RunLoop().RunUntilIdle(); | |
319 EXPECT_TRUE(request_peer_context_.received_response); | |
320 EXPECT_FALSE(request_peer_context_.complete); | |
321 EXPECT_TRUE(request_peer_context_.cancelled); | |
322 } | |
323 | |
324 // Cancelling a request in a client method should be handled correctly. | |
325 TEST_F(URLLoaderClientImplTest, Cancel3) { | |
326 request_peer_context_.cancel_on_receive_data = true; | |
327 | |
328 ResourceResponseHead response_head; | |
329 ResourceRequestCompletionStatus completion_status; | |
330 | |
331 mojo::DataPipe data_pipe(dataPipeOptions()); | |
332 uint32_t size = 5; | |
333 MojoResult result = | |
334 mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, | |
335 MOJO_WRITE_DATA_FLAG_NONE); | |
336 ASSERT_EQ(MOJO_RESULT_OK, result); | |
337 EXPECT_EQ(5u, size); | |
338 | |
339 url_loader_client_->OnStartLoadingResponseBody( | |
340 std::move(data_pipe.consumer_handle)); | |
341 base::RunLoop().RunUntilIdle(); | |
342 url_loader_client_->OnReceiveResponse(response_head, nullptr); | |
343 url_loader_client_->OnComplete(completion_status); | |
344 | |
345 EXPECT_FALSE(request_peer_context_.received_response); | |
346 EXPECT_EQ("", request_peer_context_.data); | |
347 EXPECT_FALSE(request_peer_context_.complete); | |
348 EXPECT_FALSE(request_peer_context_.cancelled); | |
349 | |
350 base::RunLoop().RunUntilIdle(); | |
351 EXPECT_TRUE(request_peer_context_.received_response); | |
352 EXPECT_EQ("hello", request_peer_context_.data); | |
353 EXPECT_FALSE(request_peer_context_.complete); | |
354 EXPECT_TRUE(request_peer_context_.cancelled); | |
355 } | |
356 | |
357 } // namespace content | |
OLD | NEW |