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