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], &params)) {
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