1 // Copyright (c) 2012 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 <string> 6 #include <vector> 7 8 #include "base/macros.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/shared_memory.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/process/process.h" 13 #include "base/process/process_handle.h" 14 #include "base/run_loop.h" 15 #include "base/stl_util.h" 16 #include "content/child/request_extra_data.h" 17 #include "content/child/request_info.h" 18 #include "content/child/resource_dispatcher.h" 19 #include "content/common/resource_messages.h" 20 #include "content/common/service_worker/service_worker_types.h" 21 #include "content/public/child/request_peer.h" 22 #include "content/public/common/resource_response.h" 23 #include "net/base/net_errors.h" 24 #include "net/http/http_response_headers.h" 25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "webkit/child/resource_loader_bridge.h" 27 #include "webkit/common/appcache/appcache_interfaces.h" 28 29 using webkit_glue::ResourceLoaderBridge; 30 31 namespace content { 32 33 static const char kTestPageUrl[] = "http://www.google.com/"; 34 static const char kTestPageHeaders[] = 35 "HTTP/1.1 200 OK\nContent-Type:text/html\n\n"; 36 static const char kTestPageMimeType[] = "text/html"; 37 static const char kTestPageCharset[] = ""; 38 static const char kTestPageContents[] = 39 "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>"; 40 static const char kTestRedirectHeaders[] = 41 "HTTP/1.1 302 Found\nLocation:http://www.google.com/\n\n"; 42 43 // Listens for request response data and stores it so that it can be compared 44 // to the reference data. 45 class TestRequestPeer : public RequestPeer { 46 public: 47 TestRequestPeer(ResourceLoaderBridge* bridge) 48 : follow_redirects_(true), 49 defer_on_redirect_(false), 50 seen_redirects_(0), 51 cancel_on_receive_response_(false), 52 received_response_(false), 53 total_encoded_data_length_(0), 54 total_downloaded_data_length_(0), 55 complete_(false), 56 bridge_(bridge) { 57 } 58 59 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE { 60 } 61 62 virtual bool OnReceivedRedirect(const GURL& new_url, 63 const GURL& new_first_party_for_cookies, 64 const ResourceResponseInfo& info) OVERRIDE { 65 ++seen_redirects_; 66 if (defer_on_redirect_) 67 bridge_->SetDefersLoading(true); 68 return follow_redirects_; 69 } 70 71 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE { 72 EXPECT_FALSE(received_response_); 73 received_response_ = true; 74 if (cancel_on_receive_response_) 75 bridge_->Cancel(); 76 } 77 78 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE { 79 total_downloaded_data_length_ += len; 80 total_encoded_data_length_ += encoded_data_length; 81 } 82 83 virtual void OnReceivedData(const char* data, 84 int data_length, 85 int encoded_data_length) OVERRIDE { 86 EXPECT_TRUE(received_response_); 87 EXPECT_FALSE(complete_); 88 data_.append(data, data_length); 89 total_encoded_data_length_ += encoded_data_length; 90 } 91 92 virtual void OnCompletedRequest( 93 int error_code, 94 bool was_ignored_by_handler, 95 bool stale_copy_in_cache, 96 const std::string& security_info, 97 const base::TimeTicks& completion_time, 98 int64 total_transfer_size) OVERRIDE { 99 EXPECT_TRUE(received_response_); 100 EXPECT_FALSE(complete_); 101 complete_ = true; 102 } 103 104 void set_follow_redirects(bool follow_redirects) { 105 follow_redirects_ = follow_redirects; 106 } 107 108 void set_defer_on_redirect(bool defer_on_redirect) { 109 defer_on_redirect_ = defer_on_redirect; 110 } 111 112 void set_cancel_on_receive_response(bool cancel_on_receive_response) { 113 cancel_on_receive_response_ = cancel_on_receive_response; 114 } 115 116 int seen_redirects() const { return seen_redirects_; } 117 118 bool received_response() const { return received_response_; } 119 120 const std::string& data() const { 121 return data_; 122 } 123 int total_encoded_data_length() const { 124 return total_encoded_data_length_; 125 } 126 int total_downloaded_data_length() const { 127 return total_downloaded_data_length_; 128 } 129 130 bool complete() const { return complete_; } 131 132 private: 133 // True if should follow redirects, false if should cancel them. 134 bool follow_redirects_; 135 // True if the request should be deferred on redirects. 136 bool defer_on_redirect_; 137 // Number of total redirects seen. 138 int seen_redirects_; 139 140 bool cancel_on_receive_response_; 141 bool received_response_; 142 143 // Data received. If downloading to file, remains empty. 144 std::string data_; 145 // Total encoded data length, regardless of whether downloading to a file or 146 // not. 147 int total_encoded_data_length_; 148 // Total length when downloading to a file. 149 int total_downloaded_data_length_; 150 151 bool complete_; 152 153 ResourceLoaderBridge* bridge_; 154 155 DISALLOW_COPY_AND_ASSIGN(TestRequestPeer); 156 }; 157 158 // Sets up the message sender override for the unit test. 159 class ResourceDispatcherTest : public testing::Test, public IPC::Sender { 160 public: 161 ResourceDispatcherTest() : dispatcher_(this) {} 162 163 virtual ~ResourceDispatcherTest() { 164 STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(), 165 shared_memory_map_.end()); 166 } 167 168 // Emulates IPC send operations (IPC::Sender) by adding 169 // pending messages to the queue. 170 virtual bool Send(IPC::Message* msg) OVERRIDE { 171 message_queue_.push_back(IPC::Message(*msg)); 172 delete msg; 173 return true; 174 } 175 176 size_t queued_messages() const { return message_queue_.size(); } 177 178 // Returns the ID of the consumed request. Can't make assumptions about the 179 // ID, because numbering is based on a global. 180 int ConsumeRequestResource() { 181 if (message_queue_.empty()) { 182 ADD_FAILURE() << "Missing resource request message"; 183 return -1; 184 } 185 186 ResourceHostMsg_RequestResource::Param params; 187 if (ResourceHostMsg_RequestResource::ID != message_queue_[0].type() || 188 !ResourceHostMsg_RequestResource::Read(&message_queue_[0], ¶ms)) { 189 ADD_FAILURE() << "Expected ResourceHostMsg_RequestResource message"; 190 return -1; 191 } 192 ResourceHostMsg_Request request = params.c; 193 EXPECT_EQ(kTestPageUrl, request.url.spec()); 194 message_queue_.erase(message_queue_.begin()); 195 return params.b; 196 } 197 198 void ConsumeFollowRedirect(int expected_request_id) { 199 ASSERT_FALSE(message_queue_.empty()); 200 Tuple1<int> args; 201 ASSERT_EQ(ResourceHostMsg_FollowRedirect::ID, message_queue_[0].type()); 202 ASSERT_TRUE(ResourceHostMsg_FollowRedirect::Read( 203 &message_queue_[0], &args)); 204 EXPECT_EQ(expected_request_id, args.a); 205 message_queue_.erase(message_queue_.begin()); 206 } 207 208 void ConsumeDataReceived_ACK(int expected_request_id) { 209 ASSERT_FALSE(message_queue_.empty()); 210 Tuple1<int> args; 211 ASSERT_EQ(ResourceHostMsg_DataReceived_ACK::ID, message_queue_[0].type()); 212 ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read( 213 &message_queue_[0], &args)); 214 EXPECT_EQ(expected_request_id, args.a); 215 message_queue_.erase(message_queue_.begin()); 216 } 217 218 void ConsumeDataDownloaded_ACK(int expected_request_id) { 219 ASSERT_FALSE(message_queue_.empty()); 220 Tuple1<int> args; 221 ASSERT_EQ(ResourceHostMsg_DataDownloaded_ACK::ID, message_queue_[0].type()); 222 ASSERT_TRUE(ResourceHostMsg_DataDownloaded_ACK::Read( 223 &message_queue_[0], &args)); 224 EXPECT_EQ(expected_request_id, args.a); 225 message_queue_.erase(message_queue_.begin()); 226 } 227 228 void ConsumeReleaseDownloadedFile(int expected_request_id) { 229 ASSERT_FALSE(message_queue_.empty()); 230 Tuple1<int> args; 231 ASSERT_EQ(ResourceHostMsg_ReleaseDownloadedFile::ID, 232 message_queue_[0].type()); 233 ASSERT_TRUE(ResourceHostMsg_ReleaseDownloadedFile::Read( 234 &message_queue_[0], &args)); 235 EXPECT_EQ(expected_request_id, args.a); 236 message_queue_.erase(message_queue_.begin()); 237 } 238 239 void ConsumeCancelRequest(int expected_request_id) { 240 ASSERT_FALSE(message_queue_.empty()); 241 Tuple1<int> args; 242 ASSERT_EQ(ResourceHostMsg_CancelRequest::ID, message_queue_[0].type()); 243 ASSERT_TRUE(ResourceHostMsg_CancelRequest::Read( 244 &message_queue_[0], &args)); 245 EXPECT_EQ(expected_request_id, args.a); 246 message_queue_.erase(message_queue_.begin()); 247 } 248 249 void NotifyReceivedRedirect(int request_id) { 250 ResourceResponseHead head; 251 std::string raw_headers(kTestRedirectHeaders); 252 std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0'); 253 head.headers = new net::HttpResponseHeaders(raw_headers); 254 head.error_code = net::OK; 255 EXPECT_EQ(true, dispatcher_.OnMessageReceived( 256 ResourceMsg_ReceivedRedirect(request_id, GURL(kTestPageUrl), 257 GURL(kTestPageUrl), head))); 258 } 259 260 void NotifyReceivedResponse(int request_id) { 261 ResourceResponseHead head; 262 std::string raw_headers(kTestPageHeaders); 263 std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0'); 264 head.headers = new net::HttpResponseHeaders(raw_headers); 265 head.mime_type = kTestPageMimeType; 266 head.charset = kTestPageCharset; 267 head.error_code = net::OK; 268 EXPECT_EQ(true, 269 dispatcher_.OnMessageReceived( 270 ResourceMsg_ReceivedResponse(request_id, head))); 271 } 272 273 void NotifySetDataBuffer(int request_id, size_t buffer_size) { 274 base::SharedMemory* shared_memory = new base::SharedMemory(); 275 ASSERT_FALSE(shared_memory_map_[request_id]); 276 shared_memory_map_[request_id] = shared_memory; 277 EXPECT_TRUE(shared_memory->CreateAndMapAnonymous(buffer_size)); 278 279 base::SharedMemoryHandle duplicate_handle; 280 EXPECT_TRUE(shared_memory->ShareToProcess( 281 base::Process::Current().handle(), &duplicate_handle)); 282 EXPECT_TRUE(dispatcher_.OnMessageReceived( 283 ResourceMsg_SetDataBuffer(request_id, duplicate_handle, 284 shared_memory->requested_size(), 0))); 285 } 286 287 void NotifyDataReceived(int request_id, std::string data) { 288 ASSERT_LE(data.length(), shared_memory_map_[request_id]->requested_size()); 289 memcpy(shared_memory_map_[request_id]->memory(), data.c_str(), 290 data.length()); 291 292 EXPECT_TRUE(dispatcher_.OnMessageReceived( 293 ResourceMsg_DataReceived(request_id, 0, data.length(), data.length()))); 294 } 295 296 void NotifyDataDownloaded(int request_id, int decoded_length, 297 int encoded_length) { 298 EXPECT_TRUE(dispatcher_.OnMessageReceived( 299 ResourceMsg_DataDownloaded(request_id, decoded_length, 300 encoded_length))); 301 } 302 303 void NotifyRequestComplete(int request_id, size_t total_size) { 304 ResourceMsg_RequestCompleteData request_complete_data; 305 request_complete_data.error_code = net::OK; 306 request_complete_data.was_ignored_by_handler = false; 307 request_complete_data.exists_in_cache = false; 308 request_complete_data.encoded_data_length = total_size; 309 EXPECT_TRUE(dispatcher_.OnMessageReceived( 310 ResourceMsg_RequestComplete(request_id, request_complete_data))); 311 } 312 313 ResourceLoaderBridge* CreateBridge() { 314 return CreateBridgeInternal(false); 315 } 316 317 ResourceLoaderBridge* CreateBridgeForDownloadToFile() { 318 return CreateBridgeInternal(true); 319 } 320 321 ResourceDispatcher* dispatcher() { return &dispatcher_; } 322 323 private: 324 ResourceLoaderBridge* CreateBridgeInternal(bool download_to_file) { 325 RequestInfo request_info; 326 request_info.method = "GET"; 327 request_info.url = GURL(kTestPageUrl); 328 request_info.first_party_for_cookies = GURL(kTestPageUrl); 329 request_info.referrer = GURL(); 330 request_info.headers = std::string(); 331 request_info.load_flags = 0; 332 request_info.requestor_pid = 0; 333 request_info.request_type = ResourceType::SUB_RESOURCE; 334 request_info.appcache_host_id = appcache::kAppCacheNoHostId; 335 request_info.routing_id = 0; 336 request_info.download_to_file = download_to_file; 337 RequestExtraData extra_data; 338 request_info.extra_data = &extra_data; 339 340 return dispatcher_.CreateBridge(request_info); 341 } 342 343 // Map of request IDs to shared memory. 344 std::map<int, base::SharedMemory*> shared_memory_map_; 345 346 std::vector<IPC::Message> message_queue_; 347 ResourceDispatcher dispatcher_; 348 base::MessageLoop message_loop_; 349 }; 350 351 // Does a simple request and tests that the correct data is received. Simulates 352 // two reads. 353 TEST_F(ResourceDispatcherTest, RoundTrip) { 354 // Number of bytes received in the first read. 355 const size_t kFirstReceiveSize = 2; 356 ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents)); 357 358 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 359 TestRequestPeer peer(bridge.get()); 360 361 EXPECT_TRUE(bridge->Start(&peer)); 362 int id = ConsumeRequestResource(); 363 EXPECT_EQ(0u, queued_messages()); 364 365 NotifyReceivedResponse(id); 366 EXPECT_EQ(0u, queued_messages()); 367 EXPECT_TRUE(peer.received_response()); 368 369 NotifySetDataBuffer(id, strlen(kTestPageContents)); 370 NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize)); 371 ConsumeDataReceived_ACK(id); 372 EXPECT_EQ(0u, queued_messages()); 373 374 NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize); 375 ConsumeDataReceived_ACK(id); 376 EXPECT_EQ(0u, queued_messages()); 377 378 NotifyRequestComplete(id, strlen(kTestPageContents)); 379 EXPECT_EQ(kTestPageContents, peer.data()); 380 EXPECT_TRUE(peer.complete()); 381 EXPECT_EQ(0u, queued_messages()); 382 } 383 384 // Tests that the request IDs are straight when there are two interleaving 385 // requests. 386 TEST_F(ResourceDispatcherTest, MultipleRequests) { 387 const char kTestPageContents2[] = "Not kTestPageContents"; 388 389 scoped_ptr<ResourceLoaderBridge> bridge1(CreateBridge()); 390 TestRequestPeer peer1(bridge1.get()); 391 scoped_ptr<ResourceLoaderBridge> bridge2(CreateBridge()); 392 TestRequestPeer peer2(bridge2.get()); 393 394 EXPECT_TRUE(bridge1->Start(&peer1)); 395 int id1 = ConsumeRequestResource(); 396 EXPECT_TRUE(bridge2->Start(&peer2)); 397 int id2 = ConsumeRequestResource(); 398 EXPECT_EQ(0u, queued_messages()); 399 400 NotifyReceivedResponse(id1); 401 EXPECT_TRUE(peer1.received_response()); 402 EXPECT_FALSE(peer2.received_response()); 403 NotifyReceivedResponse(id2); 404 EXPECT_TRUE(peer2.received_response()); 405 EXPECT_EQ(0u, queued_messages()); 406 407 NotifySetDataBuffer(id2, strlen(kTestPageContents2)); 408 NotifyDataReceived(id2, kTestPageContents2); 409 ConsumeDataReceived_ACK(id2); 410 NotifySetDataBuffer(id1, strlen(kTestPageContents)); 411 NotifyDataReceived(id1, kTestPageContents); 412 ConsumeDataReceived_ACK(id1); 413 EXPECT_EQ(0u, queued_messages()); 414 415 NotifyRequestComplete(id1, strlen(kTestPageContents)); 416 EXPECT_EQ(kTestPageContents, peer1.data()); 417 EXPECT_TRUE(peer1.complete()); 418 EXPECT_FALSE(peer2.complete()); 419 420 NotifyRequestComplete(id2, strlen(kTestPageContents2)); 421 EXPECT_EQ(kTestPageContents2, peer2.data()); 422 EXPECT_TRUE(peer2.complete()); 423 424 EXPECT_EQ(0u, queued_messages()); 425 } 426 427 // Tests that the cancel method prevents other messages from being received. 428 TEST_F(ResourceDispatcherTest, Cancel) { 429 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 430 TestRequestPeer peer(bridge.get()); 431 432 EXPECT_TRUE(bridge->Start(&peer)); 433 int id = ConsumeRequestResource(); 434 EXPECT_EQ(0u, queued_messages()); 435 436 // Cancel the request. 437 bridge->Cancel(); 438 ConsumeCancelRequest(id); 439 440 // Any future messages related to the request should be ignored. 441 NotifyReceivedResponse(id); 442 NotifySetDataBuffer(id, strlen(kTestPageContents)); 443 NotifyDataReceived(id, kTestPageContents); 444 NotifyRequestComplete(id, strlen(kTestPageContents)); 445 446 EXPECT_EQ(0u, queued_messages()); 447 EXPECT_EQ("", peer.data()); 448 EXPECT_FALSE(peer.received_response()); 449 EXPECT_FALSE(peer.complete()); 450 } 451 452 // Tests that calling cancel during a callback works as expected. 453 TEST_F(ResourceDispatcherTest, CancelDuringCallback) { 454 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 455 TestRequestPeer peer(bridge.get()); 456 peer.set_cancel_on_receive_response(true); 457 458 EXPECT_TRUE(bridge->Start(&peer)); 459 int id = ConsumeRequestResource(); 460 EXPECT_EQ(0u, queued_messages()); 461 462 NotifyReceivedResponse(id); 463 EXPECT_TRUE(peer.received_response()); 464 // Request should have been cancelled. 465 ConsumeCancelRequest(id); 466 467 // Any future messages related to the request should be ignored. 468 NotifySetDataBuffer(id, strlen(kTestPageContents)); 469 NotifyDataReceived(id, kTestPageContents); 470 NotifyRequestComplete(id, strlen(kTestPageContents)); 471 472 EXPECT_EQ(0u, queued_messages()); 473 EXPECT_EQ("", peer.data()); 474 EXPECT_FALSE(peer.complete()); 475 } 476 477 // Checks that redirects work as expected. 478 TEST_F(ResourceDispatcherTest, Redirect) { 479 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 480 TestRequestPeer peer(bridge.get()); 481 482 EXPECT_TRUE(bridge->Start(&peer)); 483 int id = ConsumeRequestResource(); 484 485 NotifyReceivedRedirect(id); 486 ConsumeFollowRedirect(id); 487 EXPECT_EQ(1, peer.seen_redirects()); 488 489 NotifyReceivedRedirect(id); 490 ConsumeFollowRedirect(id); 491 EXPECT_EQ(2, peer.seen_redirects()); 492 493 NotifyReceivedResponse(id); 494 EXPECT_TRUE(peer.received_response()); 495 496 NotifySetDataBuffer(id, strlen(kTestPageContents)); 497 NotifyDataReceived(id, kTestPageContents); 498 ConsumeDataReceived_ACK(id); 499 500 NotifyRequestComplete(id, strlen(kTestPageContents)); 501 EXPECT_EQ(kTestPageContents, peer.data()); 502 EXPECT_TRUE(peer.complete()); 503 EXPECT_EQ(0u, queued_messages()); 504 EXPECT_EQ(2, peer.seen_redirects()); 505 } 506 507 // Tests that that cancelling during a redirect method prevents other messages 508 // from being received. 509 TEST_F(ResourceDispatcherTest, CancelDuringRedirect) { 510 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 511 TestRequestPeer peer(bridge.get()); 512 peer.set_follow_redirects(false); 513 514 EXPECT_TRUE(bridge->Start(&peer)); 515 int id = ConsumeRequestResource(); 516 EXPECT_EQ(0u, queued_messages()); 517 518 // Redirect the request, which triggers a cancellation. 519 NotifyReceivedRedirect(id); 520 ConsumeCancelRequest(id); 521 EXPECT_EQ(1, peer.seen_redirects()); 522 EXPECT_EQ(0u, queued_messages()); 523 524 // Any future messages related to the request should be ignored. In practice, 525 // only the NotifyRequestComplete should be received after this point. 526 NotifyReceivedRedirect(id); 527 NotifyReceivedResponse(id); 528 NotifySetDataBuffer(id, strlen(kTestPageContents)); 529 NotifyDataReceived(id, kTestPageContents); 530 NotifyRequestComplete(id, strlen(kTestPageContents)); 531 532 EXPECT_EQ(0u, queued_messages()); 533 EXPECT_EQ("", peer.data()); 534 EXPECT_FALSE(peer.complete()); 535 EXPECT_EQ(1, peer.seen_redirects()); 536 } 537 538 // Checks that deferring a request delays messages until it's resumed. 539 TEST_F(ResourceDispatcherTest, Defer) { 540 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 541 TestRequestPeer peer(bridge.get()); 542 543 EXPECT_TRUE(bridge->Start(&peer)); 544 int id = ConsumeRequestResource(); 545 EXPECT_EQ(0u, queued_messages()); 546 547 bridge->SetDefersLoading(true); 548 NotifyReceivedResponse(id); 549 NotifySetDataBuffer(id, strlen(kTestPageContents)); 550 NotifyDataReceived(id, kTestPageContents); 551 NotifyRequestComplete(id, strlen(kTestPageContents)); 552 553 // None of the messages should have been processed yet, so no queued messages 554 // to the browser process, and no data received by the peer. 555 EXPECT_EQ(0u, queued_messages()); 556 EXPECT_EQ("", peer.data()); 557 EXPECT_FALSE(peer.complete()); 558 EXPECT_EQ(0, peer.seen_redirects()); 559 560 // Resuming the request should asynchronously unleash the deferred messages. 561 bridge->SetDefersLoading(false); 562 base::RunLoop().RunUntilIdle(); 563 564 ConsumeDataReceived_ACK(id); 565 EXPECT_EQ(0u, queued_messages()); 566 EXPECT_TRUE(peer.received_response()); 567 EXPECT_EQ(kTestPageContents, peer.data()); 568 EXPECT_TRUE(peer.complete()); 569 } 570 571 // Checks that deferring a request during a redirect delays messages until it's 572 // resumed. 573 TEST_F(ResourceDispatcherTest, DeferOnRedirect) { 574 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 575 TestRequestPeer peer(bridge.get()); 576 peer.set_defer_on_redirect(true); 577 578 EXPECT_TRUE(bridge->Start(&peer)); 579 int id = ConsumeRequestResource(); 580 EXPECT_EQ(0u, queued_messages()); 581 582 // The request should be deferred during the redirect, including the message 583 // to follow the redirect. 584 NotifyReceivedRedirect(id); 585 NotifyReceivedResponse(id); 586 NotifySetDataBuffer(id, strlen(kTestPageContents)); 587 NotifyDataReceived(id, kTestPageContents); 588 NotifyRequestComplete(id, strlen(kTestPageContents)); 589 590 // None of the messages should have been processed yet, so no queued messages 591 // to the browser process, and no data received by the peer. 592 EXPECT_EQ(0u, queued_messages()); 593 EXPECT_EQ("", peer.data()); 594 EXPECT_FALSE(peer.complete()); 595 EXPECT_EQ(1, peer.seen_redirects()); 596 597 // Resuming the request should asynchronously unleash the deferred messages. 598 bridge->SetDefersLoading(false); 599 base::RunLoop().RunUntilIdle(); 600 601 ConsumeFollowRedirect(id); 602 ConsumeDataReceived_ACK(id); 603 604 EXPECT_EQ(0u, queued_messages()); 605 EXPECT_TRUE(peer.received_response()); 606 EXPECT_EQ(kTestPageContents, peer.data()); 607 EXPECT_TRUE(peer.complete()); 608 EXPECT_EQ(1, peer.seen_redirects()); 609 } 610 611 // Checks that a deferred request that's cancelled doesn't receive any messages. 612 TEST_F(ResourceDispatcherTest, CancelDeferredRequest) { 613 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 614 TestRequestPeer peer(bridge.get()); 615 616 EXPECT_TRUE(bridge->Start(&peer)); 617 int id = ConsumeRequestResource(); 618 EXPECT_EQ(0u, queued_messages()); 619 620 bridge->SetDefersLoading(true); 621 NotifyReceivedRedirect(id); 622 bridge->Cancel(); 623 ConsumeCancelRequest(id); 624 625 NotifyRequestComplete(id, 0); 626 base::RunLoop().RunUntilIdle(); 627 628 // None of the messages should have been processed. 629 EXPECT_EQ(0u, queued_messages()); 630 EXPECT_EQ("", peer.data()); 631 EXPECT_FALSE(peer.complete()); 632 EXPECT_EQ(0, peer.seen_redirects()); 633 } 634 635 TEST_F(ResourceDispatcherTest, DownloadToFile) { 636 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridgeForDownloadToFile()); 637 TestRequestPeer peer(bridge.get()); 638 const int kDownloadedIncrement = 100; 639 const int kEncodedIncrement = 50; 640 641 EXPECT_TRUE(bridge->Start(&peer)); 642 int id = ConsumeRequestResource(); 643 EXPECT_EQ(0u, queued_messages()); 644 645 NotifyReceivedResponse(id); 646 EXPECT_EQ(0u, queued_messages()); 647 EXPECT_TRUE(peer.received_response()); 648 649 int expected_total_downloaded_length = 0; 650 int expected_total_encoded_length = 0; 651 for (int i = 0; i < 10; ++i) { 652 NotifyDataDownloaded(id, kDownloadedIncrement, kEncodedIncrement); 653 ConsumeDataDownloaded_ACK(id); 654 expected_total_downloaded_length += kDownloadedIncrement; 655 expected_total_encoded_length += kEncodedIncrement; 656 EXPECT_EQ(expected_total_downloaded_length, 657 peer.total_downloaded_data_length()); 658 EXPECT_EQ(expected_total_encoded_length, peer.total_encoded_data_length()); 659 } 660 661 NotifyRequestComplete(id, strlen(kTestPageContents)); 662 EXPECT_EQ("", peer.data()); 663 EXPECT_TRUE(peer.complete()); 664 EXPECT_EQ(0u, queued_messages()); 665 666 bridge.reset(); 667 ConsumeReleaseDownloadedFile(id); 668 EXPECT_EQ(0u, queued_messages()); 669 EXPECT_EQ(expected_total_downloaded_length, 670 peer.total_downloaded_data_length()); 671 EXPECT_EQ(expected_total_encoded_length, peer.total_encoded_data_length()); 672 } 673 674 // Make sure that when a download to file is cancelled, the file is destroyed. 675 TEST_F(ResourceDispatcherTest, CancelDownloadToFile) { 676 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridgeForDownloadToFile()); 677 TestRequestPeer peer(bridge.get()); 678 679 EXPECT_TRUE(bridge->Start(&peer)); 680 int id = ConsumeRequestResource(); 681 EXPECT_EQ(0u, queued_messages()); 682 683 NotifyReceivedResponse(id); 684 EXPECT_EQ(0u, queued_messages()); 685 EXPECT_TRUE(peer.received_response()); 686 687 // Cancelling the request deletes the file. 688 bridge->Cancel(); 689 ConsumeCancelRequest(id); 690 ConsumeReleaseDownloadedFile(id); 691 692 // Deleting the bridge shouldn't send another message to delete the file. 693 bridge.reset(); 694 EXPECT_EQ(0u, queued_messages()); 695 } 696 697 TEST_F(ResourceDispatcherTest, Cookies) { 698 // FIXME 699 } 700 701 TEST_F(ResourceDispatcherTest, SerializedPostData) { 702 // FIXME 703 } 704 705 class TimeConversionTest : public ResourceDispatcherTest, 706 public RequestPeer { 707 public: 708 virtual bool Send(IPC::Message* msg) OVERRIDE { 709 delete msg; 710 return true; 711 } 712 713 void PerformTest(const ResourceResponseHead& response_head) { 714 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); 715 bridge->Start(this); 716 717 dispatcher()->OnMessageReceived( 718 ResourceMsg_ReceivedResponse(0, response_head)); 719 } 720 721 // RequestPeer methods. 722 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE { 723 } 724 725 virtual bool OnReceivedRedirect(const GURL& new_url, 726 const GURL& new_first_party_for_cookies, 727 const ResourceResponseInfo& info) OVERRIDE { 728 return true; 729 } 730 731 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE { 732 response_info_ = info; 733 } 734 735 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE { 736 } 737 738 virtual void OnReceivedData(const char* data, 739 int data_length, 740 int encoded_data_length) OVERRIDE { 741 } 742 743 virtual void OnCompletedRequest( 744 int error_code, 745 bool was_ignored_by_handler, 746 bool stale_copy_in_cache, 747 const std::string& security_info, 748 const base::TimeTicks& completion_time, 749 int64 total_transfer_size) OVERRIDE { 750 } 751 752 const ResourceResponseInfo& response_info() const { return response_info_; } 753 754 private: 755 ResourceResponseInfo response_info_; 756 }; 757 758 // TODO(simonjam): Enable this when 10829031 lands. 759 TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) { 760 ResourceResponseHead response_head; 761 response_head.error_code = net::OK; 762 response_head.request_start = base::TimeTicks::FromInternalValue(5); 763 response_head.response_start = base::TimeTicks::FromInternalValue(15); 764 response_head.load_timing.request_start_time = base::Time::Now(); 765 response_head.load_timing.request_start = 766 base::TimeTicks::FromInternalValue(10); 767 response_head.load_timing.connect_timing.connect_start = 768 base::TimeTicks::FromInternalValue(13); 769 770 PerformTest(response_head); 771 772 EXPECT_LT(base::TimeTicks(), response_info().load_timing.request_start); 773 EXPECT_EQ(base::TimeTicks(), 774 response_info().load_timing.connect_timing.dns_start); 775 EXPECT_LE(response_head.load_timing.request_start, 776 response_info().load_timing.connect_timing.connect_start); 777 } 778 779 TEST_F(TimeConversionTest, PartiallyInitialized) { 780 ResourceResponseHead response_head; 781 response_head.error_code = net::OK; 782 response_head.request_start = base::TimeTicks::FromInternalValue(5); 783 response_head.response_start = base::TimeTicks::FromInternalValue(15); 784 785 PerformTest(response_head); 786 787 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start); 788 EXPECT_EQ(base::TimeTicks(), 789 response_info().load_timing.connect_timing.dns_start); 790 } 791 792 TEST_F(TimeConversionTest, NotInitialized) { 793 ResourceResponseHead response_head; 794 response_head.error_code = net::OK; 795 796 PerformTest(response_head); 797 798 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start); 799 EXPECT_EQ(base::TimeTicks(), 800 response_info().load_timing.connect_timing.dns_start); 801 } 802 803 } // namespace content 804