Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / child / web_url_loader_impl_unittest.cc
bloba8a23593e6f010b494171fd5db5c62d233575c27
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
3 // found in the LICENSE file.
5 #include "content/child/web_url_loader_impl.h"
7 #include <string.h>
9 #include "base/macros.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/time/time.h"
13 #include "content/child/resource_dispatcher.h"
14 #include "content/public/child/request_peer.h"
15 #include "content/public/common/resource_response_info.h"
16 #include "net/base/net_errors.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_util.h"
19 #include "net/url_request/redirect_info.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/WebKit/public/platform/WebString.h"
22 #include "third_party/WebKit/public/platform/WebURLError.h"
23 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
24 #include "third_party/WebKit/public/platform/WebURLRequest.h"
25 #include "url/gurl.h"
26 #include "webkit/child/resource_loader_bridge.h"
28 namespace content {
29 namespace {
31 const char kTestURL[] = "http://foo";
32 const char kTestData[] = "blah!";
34 const char kFtpDirMimeType[] = "text/vnd.chromium.ftp-dir";
35 // Simple FTP directory listing. Tests are not concerned with correct parsing,
36 // but rather correct cleanup when deleted while parsing. Important details of
37 // this list are that it contains more than one entry that are not "." or "..".
38 const char kFtpDirListing[] =
39 "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 goat\n"
40 "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 hat";
42 const char kMultipartResponseMimeType[] = "multipart/x-mixed-replace";
43 const char kMultipartResponseHeaders[] =
44 "HTTP/1.0 200 Peachy\r\n"
45 "Content-Type: multipart/x-mixed-replace; boundary=boundary\r\n\r\n";
46 // Simple multipart response. Imporant details for the tests are that it
47 // contains multiple chunks, and that it doesn't end with a boundary, so will
48 // send data in OnResponseComplete. Also, it will resolve to kTestData.
49 const char kMultipartResponse[] =
50 "--boundary\n"
51 "Content-type: text/html\n\n"
52 "bl"
53 "--boundary\n"
54 "Content-type: text/html\n\n"
55 "ah!";
57 class TestBridge : public webkit_glue::ResourceLoaderBridge,
58 public base::SupportsWeakPtr<TestBridge> {
59 public:
60 TestBridge() : peer_(NULL), canceled_(false) {}
61 virtual ~TestBridge() {}
63 // ResourceLoaderBridge implementation:
64 virtual void SetRequestBody(ResourceRequestBody* request_body) OVERRIDE {}
66 virtual bool Start(RequestPeer* peer) OVERRIDE {
67 EXPECT_FALSE(peer_);
68 peer_ = peer;
69 return true;
72 virtual void Cancel() OVERRIDE {
73 EXPECT_FALSE(canceled_);
74 canceled_ = true;
77 virtual void SetDefersLoading(bool value) OVERRIDE {}
79 virtual void DidChangePriority(net::RequestPriority new_priority,
80 int intra_priority_value) OVERRIDE {}
82 virtual bool AttachThreadedDataReceiver(
83 blink::WebThreadedDataReceiver* threaded_data_receiver) OVERRIDE {
84 NOTREACHED();
85 return false;
88 virtual void SyncLoad(SyncLoadResponse* response) OVERRIDE {}
90 RequestPeer* peer() { return peer_; }
92 bool canceled() { return canceled_; }
94 private:
95 RequestPeer* peer_;
96 bool canceled_;
98 DISALLOW_COPY_AND_ASSIGN(TestBridge);
101 class TestResourceDispatcher : public ResourceDispatcher {
102 public:
103 TestResourceDispatcher() : ResourceDispatcher(NULL) {}
104 virtual ~TestResourceDispatcher() {}
106 // ResourceDispatcher implementation:
107 virtual webkit_glue::ResourceLoaderBridge* CreateBridge(
108 const RequestInfo& request_info) OVERRIDE {
109 EXPECT_FALSE(bridge_.get());
110 TestBridge* bridge = new TestBridge();
111 bridge_ = bridge->AsWeakPtr();
112 return bridge;
115 TestBridge* bridge() { return bridge_.get(); }
117 private:
118 base::WeakPtr<TestBridge> bridge_;
120 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcher);
123 class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
124 public:
125 TestWebURLLoaderClient(ResourceDispatcher* dispatcher)
126 : loader_(new WebURLLoaderImpl(dispatcher)),
127 expect_multipart_response_(false),
128 delete_on_receive_redirect_(false),
129 delete_on_receive_response_(false),
130 delete_on_receive_data_(false),
131 delete_on_finish_(false),
132 delete_on_fail_(false),
133 did_receive_redirect_(false),
134 did_receive_response_(false),
135 did_finish_(false) {
138 virtual ~TestWebURLLoaderClient() {}
140 // blink::WebURLLoaderClient implementation:
141 virtual void willSendRequest(
142 blink::WebURLLoader* loader,
143 blink::WebURLRequest& newRequest,
144 const blink::WebURLResponse& redirectResponse) OVERRIDE {
145 EXPECT_TRUE(loader_);
146 EXPECT_EQ(loader_.get(), loader);
147 // No test currently simulates mutiple redirects.
148 EXPECT_FALSE(did_receive_redirect_);
149 did_receive_redirect_ = true;
151 if (delete_on_receive_redirect_)
152 loader_.reset();
155 virtual void didSendData(blink::WebURLLoader* loader,
156 unsigned long long bytesSent,
157 unsigned long long totalBytesToBeSent) OVERRIDE {
158 EXPECT_TRUE(loader_);
159 EXPECT_EQ(loader_.get(), loader);
162 virtual void didReceiveResponse(
163 blink::WebURLLoader* loader,
164 const blink::WebURLResponse& response) OVERRIDE {
165 EXPECT_TRUE(loader_);
166 EXPECT_EQ(loader_.get(), loader);
168 // Only multipart requests may receive multiple response headers.
169 EXPECT_TRUE(expect_multipart_response_ || !did_receive_response_);
171 did_receive_response_ = true;
172 if (delete_on_receive_response_)
173 loader_.reset();
176 virtual void didDownloadData(blink::WebURLLoader* loader,
177 int dataLength,
178 int encodedDataLength) OVERRIDE {
179 EXPECT_TRUE(loader_);
180 EXPECT_EQ(loader_.get(), loader);
183 virtual void didReceiveData(blink::WebURLLoader* loader,
184 const char* data,
185 int dataLength,
186 int encodedDataLength) OVERRIDE {
187 EXPECT_TRUE(loader_);
188 EXPECT_EQ(loader_.get(), loader);
189 // The response should have started, but must not have finished, or failed.
190 EXPECT_TRUE(did_receive_response_);
191 EXPECT_FALSE(did_finish_);
192 EXPECT_EQ(net::OK, error_.reason);
193 EXPECT_EQ("", error_.domain.utf8());
195 received_data_.append(data, dataLength);
197 if (delete_on_receive_data_)
198 loader_.reset();
201 virtual void didReceiveCachedMetadata(blink::WebURLLoader* loader,
202 const char* data,
203 int dataLength) OVERRIDE {
204 EXPECT_EQ(loader_.get(), loader);
207 virtual void didFinishLoading(blink::WebURLLoader* loader,
208 double finishTime,
209 int64_t totalEncodedDataLength) OVERRIDE {
210 EXPECT_TRUE(loader_);
211 EXPECT_EQ(loader_.get(), loader);
212 EXPECT_TRUE(did_receive_response_);
213 EXPECT_FALSE(did_finish_);
214 did_finish_ = true;
216 if (delete_on_finish_)
217 loader_.reset();
220 virtual void didFail(blink::WebURLLoader* loader,
221 const blink::WebURLError& error) OVERRIDE {
222 EXPECT_TRUE(loader_);
223 EXPECT_EQ(loader_.get(), loader);
224 EXPECT_FALSE(did_finish_);
225 error_ = error;
227 if (delete_on_fail_)
228 loader_.reset();
231 WebURLLoaderImpl* loader() { return loader_.get(); }
232 void DeleteLoader() {
233 loader_.reset();
236 void set_expect_multipart_response() { expect_multipart_response_ = true; }
238 void set_delete_on_receive_redirect() { delete_on_receive_redirect_ = true; }
239 void set_delete_on_receive_response() { delete_on_receive_response_ = true; }
240 void set_delete_on_receive_data() { delete_on_receive_data_ = true; }
241 void set_delete_on_finish() { delete_on_finish_ = true; }
242 void set_delete_on_fail() { delete_on_fail_ = true; }
244 bool did_receive_redirect() const { return did_receive_redirect_; }
245 bool did_receive_response() const { return did_receive_response_; }
246 const std::string& received_data() const { return received_data_; }
247 bool did_finish() const { return did_finish_; }
248 const blink::WebURLError& error() const { return error_; }
250 private:
251 scoped_ptr<WebURLLoaderImpl> loader_;
253 bool expect_multipart_response_;
255 bool delete_on_receive_redirect_;
256 bool delete_on_receive_response_;
257 bool delete_on_receive_data_;
258 bool delete_on_finish_;
259 bool delete_on_fail_;
261 bool did_receive_redirect_;
262 bool did_receive_response_;
263 std::string received_data_;
264 bool did_finish_;
265 blink::WebURLError error_;
267 DISALLOW_COPY_AND_ASSIGN(TestWebURLLoaderClient);
270 class WebURLLoaderImplTest : public testing::Test {
271 public:
272 explicit WebURLLoaderImplTest() : client_(&dispatcher_) {}
273 virtual ~WebURLLoaderImplTest() {}
275 void DoStartAsyncRequest() {
276 blink::WebURLRequest request;
277 request.initialize();
278 request.setURL(GURL(kTestURL));
279 client()->loader()->loadAsynchronously(request, client());
280 ASSERT_TRUE(bridge());
281 ASSERT_TRUE(peer());
284 void DoReceiveRedirect() {
285 EXPECT_FALSE(client()->did_receive_redirect());
286 net::RedirectInfo redirect_info;
287 redirect_info.status_code = 302;
288 redirect_info.new_method = "GET";
289 redirect_info.new_url = GURL(kTestURL);
290 redirect_info.new_first_party_for_cookies = GURL(kTestURL);
291 peer()->OnReceivedRedirect(redirect_info,
292 content::ResourceResponseInfo());
293 EXPECT_TRUE(client()->did_receive_redirect());
296 void DoReceiveResponse() {
297 EXPECT_FALSE(client()->did_receive_response());
298 peer()->OnReceivedResponse(content::ResourceResponseInfo());
299 EXPECT_TRUE(client()->did_receive_response());
302 // Assumes it is called only once for a request.
303 void DoReceiveData() {
304 EXPECT_EQ("", client()->received_data());
305 peer()->OnReceivedData(kTestData, strlen(kTestData), strlen(kTestData));
306 EXPECT_EQ(kTestData, client()->received_data());
309 void DoCompleteRequest() {
310 EXPECT_FALSE(client()->did_finish());
311 peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
312 strlen(kTestData));
313 EXPECT_TRUE(client()->did_finish());
314 // There should be no error.
315 EXPECT_EQ(net::OK, client()->error().reason);
316 EXPECT_EQ("", client()->error().domain.utf8());
319 void DoFailRequest() {
320 EXPECT_FALSE(client()->did_finish());
321 peer()->OnCompletedRequest(net::ERR_FAILED, false, false, "",
322 base::TimeTicks(), strlen(kTestData));
323 EXPECT_FALSE(client()->did_finish());
324 EXPECT_EQ(net::ERR_FAILED, client()->error().reason);
325 EXPECT_EQ(net::kErrorDomain, client()->error().domain.utf8());
328 void DoReceiveResponseFtp() {
329 EXPECT_FALSE(client()->did_receive_response());
330 content::ResourceResponseInfo response_info;
331 response_info.mime_type = kFtpDirMimeType;
332 peer()->OnReceivedResponse(response_info);
333 EXPECT_TRUE(client()->did_receive_response());
336 void DoReceiveDataFtp() {
337 peer()->OnReceivedData(kFtpDirListing, strlen(kFtpDirListing),
338 strlen(kFtpDirListing));
339 // The FTP delegate should modify the data the client sees.
340 EXPECT_NE(kFtpDirListing, client()->received_data());
343 void DoReceiveResponseMultipart() {
344 EXPECT_FALSE(client()->did_receive_response());
345 content::ResourceResponseInfo response_info;
346 response_info.headers = new net::HttpResponseHeaders(
347 net::HttpUtil::AssembleRawHeaders(kMultipartResponseHeaders,
348 strlen(kMultipartResponseHeaders)));
349 response_info.mime_type = kMultipartResponseMimeType;
350 peer()->OnReceivedResponse(response_info);
351 EXPECT_TRUE(client()->did_receive_response());
354 void DoReceiveDataMultipart() {
355 peer()->OnReceivedData(kMultipartResponse, strlen(kMultipartResponse),
356 strlen(kMultipartResponse));
357 // Multipart delegate should modify the data the client sees.
358 EXPECT_NE(kMultipartResponse, client()->received_data());
361 TestWebURLLoaderClient* client() { return &client_; }
362 TestBridge* bridge() { return dispatcher_.bridge(); }
363 RequestPeer* peer() { return bridge()->peer(); }
364 base::MessageLoop* message_loop() { return &message_loop_; }
366 private:
367 TestResourceDispatcher dispatcher_;
368 TestWebURLLoaderClient client_;
370 base::MessageLoop message_loop_;
373 TEST_F(WebURLLoaderImplTest, Success) {
374 DoStartAsyncRequest();
375 DoReceiveResponse();
376 DoReceiveData();
377 DoCompleteRequest();
378 EXPECT_FALSE(bridge()->canceled());
379 EXPECT_EQ(kTestData, client()->received_data());
382 TEST_F(WebURLLoaderImplTest, Redirect) {
383 DoStartAsyncRequest();
384 DoReceiveRedirect();
385 DoReceiveResponse();
386 DoReceiveData();
387 DoCompleteRequest();
388 EXPECT_FALSE(bridge()->canceled());
389 EXPECT_EQ(kTestData, client()->received_data());
392 TEST_F(WebURLLoaderImplTest, Failure) {
393 DoStartAsyncRequest();
394 DoReceiveResponse();
395 DoReceiveData();
396 DoFailRequest();
397 EXPECT_FALSE(bridge()->canceled());
400 // The client may delete the WebURLLoader during any callback from the loader.
401 // These tests make sure that doesn't result in a crash.
402 TEST_F(WebURLLoaderImplTest, DeleteOnReceiveRedirect) {
403 client()->set_delete_on_receive_redirect();
404 DoStartAsyncRequest();
405 DoReceiveRedirect();
406 EXPECT_FALSE(bridge());
409 TEST_F(WebURLLoaderImplTest, DeleteOnReceiveResponse) {
410 client()->set_delete_on_receive_response();
411 DoStartAsyncRequest();
412 DoReceiveResponse();
413 EXPECT_FALSE(bridge());
416 TEST_F(WebURLLoaderImplTest, DeleteOnReceiveData) {
417 client()->set_delete_on_receive_data();
418 DoStartAsyncRequest();
419 DoReceiveResponse();
420 DoReceiveData();
421 EXPECT_FALSE(bridge());
424 TEST_F(WebURLLoaderImplTest, DeleteOnFinish) {
425 client()->set_delete_on_finish();
426 DoStartAsyncRequest();
427 DoReceiveResponse();
428 DoReceiveData();
429 DoCompleteRequest();
430 EXPECT_FALSE(bridge());
433 TEST_F(WebURLLoaderImplTest, DeleteOnFail) {
434 client()->set_delete_on_fail();
435 DoStartAsyncRequest();
436 DoReceiveResponse();
437 DoReceiveData();
438 DoFailRequest();
439 EXPECT_FALSE(bridge());
442 TEST_F(WebURLLoaderImplTest, DeleteBeforeResponseDataURL) {
443 blink::WebURLRequest request;
444 request.initialize();
445 request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
446 client()->loader()->loadAsynchronously(request, client());
447 client()->DeleteLoader();
448 message_loop()->RunUntilIdle();
449 EXPECT_FALSE(client()->did_receive_response());
450 EXPECT_FALSE(bridge());
453 // Data URL tests.
455 TEST_F(WebURLLoaderImplTest, DataURL) {
456 blink::WebURLRequest request;
457 request.initialize();
458 request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
459 client()->loader()->loadAsynchronously(request, client());
460 message_loop()->RunUntilIdle();
461 EXPECT_EQ("blah!", client()->received_data());
462 EXPECT_TRUE(client()->did_finish());
463 EXPECT_EQ(net::OK, client()->error().reason);
464 EXPECT_EQ("", client()->error().domain.utf8());
467 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveResponse) {
468 blink::WebURLRequest request;
469 request.initialize();
470 request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
471 client()->set_delete_on_receive_response();
472 client()->loader()->loadAsynchronously(request, client());
473 message_loop()->RunUntilIdle();
474 EXPECT_TRUE(client()->did_receive_response());
475 EXPECT_EQ("", client()->received_data());
476 EXPECT_FALSE(client()->did_finish());
477 EXPECT_FALSE(bridge());
480 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveData) {
481 blink::WebURLRequest request;
482 request.initialize();
483 request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
484 client()->set_delete_on_receive_data();
485 client()->loader()->loadAsynchronously(request, client());
486 message_loop()->RunUntilIdle();
487 EXPECT_TRUE(client()->did_receive_response());
488 EXPECT_EQ("blah!", client()->received_data());
489 EXPECT_FALSE(client()->did_finish());
490 EXPECT_FALSE(bridge());
493 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnFinisha) {
494 blink::WebURLRequest request;
495 request.initialize();
496 request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
497 client()->set_delete_on_finish();
498 client()->loader()->loadAsynchronously(request, client());
499 message_loop()->RunUntilIdle();
500 EXPECT_TRUE(client()->did_receive_response());
501 EXPECT_EQ("blah!", client()->received_data());
502 EXPECT_TRUE(client()->did_finish());
503 EXPECT_FALSE(bridge());
506 // FTP integration tests. These are focused more on safe deletion than correct
507 // parsing of FTP responses.
509 TEST_F(WebURLLoaderImplTest, Ftp) {
510 DoStartAsyncRequest();
511 DoReceiveResponseFtp();
512 DoReceiveDataFtp();
513 DoCompleteRequest();
514 EXPECT_FALSE(bridge()->canceled());
517 TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveResponse) {
518 client()->set_delete_on_receive_response();
519 DoStartAsyncRequest();
520 DoReceiveResponseFtp();
522 // No data should have been received.
523 EXPECT_EQ("", client()->received_data());
524 EXPECT_FALSE(bridge());
527 TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveFirstData) {
528 client()->set_delete_on_receive_data();
529 DoStartAsyncRequest();
530 // Some data is sent in ReceiveResponse for FTP requests, so the bridge should
531 // be deleted here.
532 DoReceiveResponseFtp();
534 EXPECT_NE("", client()->received_data());
535 EXPECT_FALSE(bridge());
538 TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveMoreData) {
539 DoStartAsyncRequest();
540 DoReceiveResponseFtp();
541 DoReceiveDataFtp();
543 // Directory listings are only parsed once the request completes, so this will
544 // cancel in DoReceiveDataFtp, before the request finishes.
545 client()->set_delete_on_receive_data();
546 peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
547 strlen(kTestData));
548 EXPECT_FALSE(client()->did_finish());
550 EXPECT_FALSE(bridge());
553 TEST_F(WebURLLoaderImplTest, FtpDeleteOnFinish) {
554 client()->set_delete_on_finish();
555 DoStartAsyncRequest();
556 DoReceiveResponseFtp();
557 DoReceiveDataFtp();
558 DoCompleteRequest();
559 EXPECT_FALSE(bridge());
562 TEST_F(WebURLLoaderImplTest, FtpDeleteOnFail) {
563 client()->set_delete_on_fail();
564 DoStartAsyncRequest();
565 DoReceiveResponseFtp();
566 DoReceiveDataFtp();
567 DoFailRequest();
568 EXPECT_FALSE(bridge());
571 // Multipart integration tests. These are focused more on safe deletion than
572 // correct parsing of Multipart responses.
574 TEST_F(WebURLLoaderImplTest, Multipart) {
575 client()->set_expect_multipart_response();
576 DoStartAsyncRequest();
577 DoReceiveResponseMultipart();
578 DoReceiveDataMultipart();
579 DoCompleteRequest();
580 EXPECT_EQ(kTestData, client()->received_data());
581 EXPECT_FALSE(bridge()->canceled());
584 TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstResponse) {
585 client()->set_expect_multipart_response();
586 client()->set_delete_on_receive_response();
587 DoStartAsyncRequest();
588 DoReceiveResponseMultipart();
589 EXPECT_EQ("", client()->received_data());
590 EXPECT_FALSE(bridge());
593 TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveSecondResponse) {
594 client()->set_expect_multipart_response();
595 DoStartAsyncRequest();
596 DoReceiveResponseMultipart();
597 client()->set_delete_on_receive_response();
598 DoReceiveDataMultipart();
599 EXPECT_EQ("", client()->received_data());
600 EXPECT_FALSE(bridge());
603 TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstData) {
604 client()->set_expect_multipart_response();
605 client()->set_delete_on_receive_data();
606 DoStartAsyncRequest();
607 DoReceiveResponseMultipart();
608 DoReceiveDataMultipart();
609 EXPECT_EQ("bl", client()->received_data());
610 EXPECT_FALSE(bridge());
613 TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveMoreData) {
614 client()->set_expect_multipart_response();
615 DoStartAsyncRequest();
616 DoReceiveResponseMultipart();
617 DoReceiveDataMultipart();
618 // For multipart responses, the delegate may send some data when notified
619 // of a request completing.
620 client()->set_delete_on_receive_data();
621 peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
622 strlen(kTestData));
623 EXPECT_FALSE(client()->did_finish());
624 EXPECT_EQ(kTestData, client()->received_data());
625 EXPECT_FALSE(bridge());
628 TEST_F(WebURLLoaderImplTest, MultipartDeleteFinish) {
629 client()->set_expect_multipart_response();
630 client()->set_delete_on_finish();
631 DoStartAsyncRequest();
632 DoReceiveResponseMultipart();
633 DoReceiveDataMultipart();
634 DoCompleteRequest();
635 EXPECT_EQ(kTestData, client()->received_data());
636 EXPECT_FALSE(bridge());
639 TEST_F(WebURLLoaderImplTest, MultipartDeleteFail) {
640 client()->set_expect_multipart_response();
641 client()->set_delete_on_fail();
642 DoStartAsyncRequest();
643 DoReceiveResponseMultipart();
644 DoReceiveDataMultipart();
645 DoFailRequest();
646 EXPECT_FALSE(bridge());
649 } // namespace
650 } // namespace content