blob: 3e427ca3356b47352d0bca41c759fabd135d6014 [file] [log] [blame]
[email protected]80744782012-05-04 01:47:001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include <string>
6#include <vector>
7
[email protected]0a0e2c7b2014-06-16 19:10:148#include "base/macros.h"
[email protected]3b63f8f42011-03-28 01:54:159#include "base/memory/scoped_ptr.h"
[email protected]0a0e2c7b2014-06-16 19:10:1410#include "base/memory/shared_memory.h"
[email protected]e55f5642013-07-18 00:22:5411#include "base/message_loop/message_loop.h"
[email protected]54724e22013-07-25 13:02:1512#include "base/process/process.h"
13#include "base/process/process_handle.h"
[email protected]2a1a06d2014-06-04 12:24:3614#include "base/run_loop.h"
[email protected]0a0e2c7b2014-06-16 19:10:1415#include "base/stl_util.h"
[email protected]541b7b02013-06-07 00:59:3416#include "content/child/request_extra_data.h"
[email protected]abfd92e2014-03-24 02:34:4617#include "content/child/request_info.h"
[email protected]10208ea2013-06-06 20:08:0318#include "content/child/resource_dispatcher.h"
[email protected]98d6d4562014-06-25 20:57:5519#include "content/common/appcache_interfaces.h"
[email protected]94dc971d2011-03-05 19:08:3220#include "content/common/resource_messages.h"
[email protected]fa07f6572014-03-06 13:10:1021#include "content/common/service_worker/service_worker_types.h"
[email protected]ddf55bb2014-04-03 08:24:4722#include "content/public/child/request_peer.h"
[email protected]2336ffe2011-11-24 01:23:3423#include "content/public/common/resource_response.h"
[email protected]2756a8e2012-09-07 18:24:2924#include "net/base/net_errors.h"
[email protected]7a4de7a62010-08-17 18:38:2425#include "net/http/http_response_headers.h"
initial.commit09911bf2008-07-26 23:55:2926#include "testing/gtest/include/gtest/gtest.h"
[email protected]2a4b6ea2014-05-03 01:57:1027#include "webkit/child/resource_loader_bridge.h"
initial.commit09911bf2008-07-26 23:55:2928
[email protected]2a4b6ea2014-05-03 01:57:1029using webkit_glue::ResourceLoaderBridge;
initial.commit09911bf2008-07-26 23:55:2930
[email protected]be7b41e82012-07-04 09:46:5131namespace content {
32
[email protected]0a0e2c7b2014-06-16 19:10:1433static const char kTestPageUrl[] = "http://www.google.com/";
34static const char kTestPageHeaders[] =
initial.commit09911bf2008-07-26 23:55:2935 "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
[email protected]0a0e2c7b2014-06-16 19:10:1436static const char kTestPageMimeType[] = "text/html";
37static const char kTestPageCharset[] = "";
38static const char kTestPageContents[] =
initial.commit09911bf2008-07-26 23:55:2939 "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
[email protected]0a0e2c7b2014-06-16 19:10:1440static const char kTestRedirectHeaders[] =
41 "HTTP/1.1 302 Found\nLocation:http://www.google.com/\n\n";
initial.commit09911bf2008-07-26 23:55:2942
43// Listens for request response data and stores it so that it can be compared
44// to the reference data.
[email protected]0a0e2c7b2014-06-16 19:10:1445class TestRequestPeer : public RequestPeer {
initial.commit09911bf2008-07-26 23:55:2946 public:
[email protected]0a0e2c7b2014-06-16 19:10:1447 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) {
initial.commit09911bf2008-07-26 23:55:2957 }
58
[email protected]04f6f982012-08-03 01:02:1559 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
[email protected]bb551622010-07-22 20:52:4960 }
61
[email protected]b97fc382014-05-14 20:06:3462 virtual bool OnReceivedRedirect(const GURL& new_url,
63 const GURL& new_first_party_for_cookies,
64 const ResourceResponseInfo& info) OVERRIDE {
[email protected]0a0e2c7b2014-06-16 19:10:1465 ++seen_redirects_;
66 if (defer_on_redirect_)
67 bridge_->SetDefersLoading(true);
68 return follow_redirects_;
initial.commit09911bf2008-07-26 23:55:2969 }
70
[email protected]04f6f982012-08-03 01:02:1571 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
[email protected]0a0e2c7b2014-06-16 19:10:1472 EXPECT_FALSE(received_response_);
73 received_response_ = true;
74 if (cancel_on_receive_response_)
75 bridge_->Cancel();
initial.commit09911bf2008-07-26 23:55:2976 }
77
[email protected]ad554bc2013-09-03 21:18:4778 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
[email protected]0a0e2c7b2014-06-16 19:10:1479 total_downloaded_data_length_ += len;
80 total_encoded_data_length_ += encoded_data_length;
[email protected]bb551622010-07-22 20:52:4981 }
82
[email protected]8bd0de72011-04-08 18:52:1083 virtual void OnReceivedData(const char* data,
84 int data_length,
[email protected]04f6f982012-08-03 01:02:1585 int encoded_data_length) OVERRIDE {
[email protected]0a0e2c7b2014-06-16 19:10:1486 EXPECT_TRUE(received_response_);
initial.commit09911bf2008-07-26 23:55:2987 EXPECT_FALSE(complete_);
[email protected]8bd0de72011-04-08 18:52:1088 data_.append(data, data_length);
[email protected]dfd682172011-04-13 19:57:2589 total_encoded_data_length_ += encoded_data_length;
initial.commit09911bf2008-07-26 23:55:2990 }
91
[email protected]04f6f982012-08-03 01:02:1592 virtual void OnCompletedRequest(
[email protected]2756a8e2012-09-07 18:24:2993 int error_code,
94 bool was_ignored_by_handler,
[email protected]dcbe3df2014-02-06 23:08:3795 bool stale_copy_in_cache,
[email protected]04f6f982012-08-03 01:02:1596 const std::string& security_info,
[email protected]c8c567582014-02-10 12:54:5797 const base::TimeTicks& completion_time,
98 int64 total_transfer_size) OVERRIDE {
[email protected]0a0e2c7b2014-06-16 19:10:1499 EXPECT_TRUE(received_response_);
initial.commit09911bf2008-07-26 23:55:29100 EXPECT_FALSE(complete_);
101 complete_ = true;
102 }
103
[email protected]0a0e2c7b2014-06-16 19:10:14104 void set_follow_redirects(bool follow_redirects) {
105 follow_redirects_ = follow_redirects;
[email protected]8bd0de72011-04-08 18:52:10106 }
[email protected]0a0e2c7b2014-06-16 19:10:14107
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
initial.commit09911bf2008-07-26 23:55:29120 const std::string& data() const {
121 return data_;
122 }
[email protected]dfd682172011-04-13 19:57:25123 int total_encoded_data_length() const {
124 return total_encoded_data_length_;
initial.commit09911bf2008-07-26 23:55:29125 }
[email protected]0a0e2c7b2014-06-16 19:10:14126 int total_downloaded_data_length() const {
127 return total_downloaded_data_length_;
128 }
129
130 bool complete() const { return complete_; }
initial.commit09911bf2008-07-26 23:55:29131
132 private:
[email protected]0a0e2c7b2014-06-16 19:10:14133 // 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.
initial.commit09911bf2008-07-26 23:55:29144 std::string data_;
[email protected]0a0e2c7b2014-06-16 19:10:14145 // Total encoded data length, regardless of whether downloading to a file or
146 // not.
[email protected]dfd682172011-04-13 19:57:25147 int total_encoded_data_length_;
[email protected]0a0e2c7b2014-06-16 19:10:14148 // 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);
initial.commit09911bf2008-07-26 23:55:29156};
157
[email protected]0a0e2c7b2014-06-16 19:10:14158// Sets up the message sender override for the unit test.
[email protected]d84effeb2012-06-25 17:03:10159class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
initial.commit09911bf2008-07-26 23:55:29160 public:
[email protected]0a0e2c7b2014-06-16 19:10:14161 ResourceDispatcherTest() : dispatcher_(this) {}
162
163 virtual ~ResourceDispatcherTest() {
164 STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
165 shared_memory_map_.end());
166 }
167
[email protected]d84effeb2012-06-25 17:03:10168 // Emulates IPC send operations (IPC::Sender) by adding
initial.commit09911bf2008-07-26 23:55:29169 // pending messages to the queue.
[email protected]c3e35892013-02-12 02:08:01170 virtual bool Send(IPC::Message* msg) OVERRIDE {
initial.commit09911bf2008-07-26 23:55:29171 message_queue_.push_back(IPC::Message(*msg));
172 delete msg;
173 return true;
174 }
175
[email protected]0a0e2c7b2014-06-16 19:10:14176 size_t queued_messages() const { return message_queue_.size(); }
initial.commit09911bf2008-07-26 23:55:29177
[email protected]0a0e2c7b2014-06-16 19:10:14178 // 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;
initial.commit09911bf2008-07-26 23:55:29184 }
[email protected]0a0e2c7b2014-06-16 19:10:14185
186 ResourceHostMsg_RequestResource::Param params;
187 if (ResourceHostMsg_RequestResource::ID != message_queue_[0].type() ||
188 !ResourceHostMsg_RequestResource::Read(&message_queue_[0], &params)) {
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;
initial.commit09911bf2008-07-26 23:55:29196 }
197
[email protected]0a0e2c7b2014-06-16 19:10:14198 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());
initial.commit09911bf2008-07-26 23:55:29206 }
[email protected]0a0e2c7b2014-06-16 19:10:14207
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)));
initial.commit09911bf2008-07-26 23:55:29311 }
312
[email protected]2a4b6ea2014-05-03 01:57:10313 ResourceLoaderBridge* CreateBridge() {
[email protected]0a0e2c7b2014-06-16 19:10:14314 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) {
[email protected]2a4b6ea2014-05-03 01:57:10325 RequestInfo request_info;
326 request_info.method = "GET";
[email protected]0a0e2c7b2014-06-16 19:10:14327 request_info.url = GURL(kTestPageUrl);
328 request_info.first_party_for_cookies = GURL(kTestPageUrl);
[email protected]2a4b6ea2014-05-03 01:57:10329 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;
[email protected]98d6d4562014-06-25 20:57:55334 request_info.appcache_host_id = kAppCacheNoHostId;
[email protected]2a4b6ea2014-05-03 01:57:10335 request_info.routing_id = 0;
[email protected]0a0e2c7b2014-06-16 19:10:14336 request_info.download_to_file = download_to_file;
[email protected]2a4b6ea2014-05-03 01:57:10337 RequestExtraData extra_data;
338 request_info.extra_data = &extra_data;
[email protected]46b0d4a2009-12-19 00:46:33339
[email protected]0a0e2c7b2014-06-16 19:10:14340 return dispatcher_.CreateBridge(request_info);
[email protected]2602087e2009-08-24 23:12:16341 }
342
[email protected]0a0e2c7b2014-06-16 19:10:14343 // Map of request IDs to shared memory.
344 std::map<int, base::SharedMemory*> shared_memory_map_;
345
initial.commit09911bf2008-07-26 23:55:29346 std::vector<IPC::Message> message_queue_;
[email protected]0a0e2c7b2014-06-16 19:10:14347 ResourceDispatcher dispatcher_;
348 base::MessageLoop message_loop_;
initial.commit09911bf2008-07-26 23:55:29349};
350
[email protected]0a0e2c7b2014-06-16 19:10:14351// Does a simple request and tests that the correct data is received. Simulates
352// two reads.
initial.commit09911bf2008-07-26 23:55:29353TEST_F(ResourceDispatcherTest, RoundTrip) {
[email protected]0a0e2c7b2014-06-16 19:10:14354 // Number of bytes received in the first read.
355 const size_t kFirstReceiveSize = 2;
356 ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
357
[email protected]2a1a06d2014-06-04 12:24:36358 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
[email protected]0a0e2c7b2014-06-16 19:10:14359 TestRequestPeer peer(bridge.get());
initial.commit09911bf2008-07-26 23:55:29360
[email protected]0a0e2c7b2014-06-16 19:10:14361 EXPECT_TRUE(bridge->Start(&peer));
362 int id = ConsumeRequestResource();
363 EXPECT_EQ(0u, queued_messages());
initial.commit09911bf2008-07-26 23:55:29364
[email protected]0a0e2c7b2014-06-16 19:10:14365 NotifyReceivedResponse(id);
366 EXPECT_EQ(0u, queued_messages());
367 EXPECT_TRUE(peer.received_response());
initial.commit09911bf2008-07-26 23:55:29368
[email protected]0a0e2c7b2014-06-16 19:10:14369 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());
initial.commit09911bf2008-07-26 23:55:29382}
383
[email protected]0a0e2c7b2014-06-16 19:10:14384// Tests that the request IDs are straight when there are two interleaving
385// requests.
initial.commit09911bf2008-07-26 23:55:29386TEST_F(ResourceDispatcherTest, MultipleRequests) {
[email protected]0a0e2c7b2014-06-16 19:10:14387 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());
initial.commit09911bf2008-07-26 23:55:29425}
426
[email protected]0a0e2c7b2014-06-16 19:10:14427// Tests that the cancel method prevents other messages from being received.
initial.commit09911bf2008-07-26 23:55:29428TEST_F(ResourceDispatcherTest, Cancel) {
[email protected]0a0e2c7b2014-06-16 19:10:14429 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.
453TEST_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.
478TEST_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.
509TEST_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.
539TEST_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.
573TEST_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.
612TEST_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
635TEST_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.
675TEST_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());
initial.commit09911bf2008-07-26 23:55:29695}
696
697TEST_F(ResourceDispatcherTest, Cookies) {
698 // FIXME
699}
700
701TEST_F(ResourceDispatcherTest, SerializedPostData) {
702 // FIXME
703}
[email protected]2602087e2009-08-24 23:12:16704
[email protected]04f6f982012-08-03 01:02:15705class TimeConversionTest : public ResourceDispatcherTest,
[email protected]ddf55bb2014-04-03 08:24:47706 public RequestPeer {
[email protected]04f6f982012-08-03 01:02:15707 public:
708 virtual bool Send(IPC::Message* msg) OVERRIDE {
709 delete msg;
710 return true;
711 }
712
713 void PerformTest(const ResourceResponseHead& response_head) {
[email protected]2a4b6ea2014-05-03 01:57:10714 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
715 bridge->Start(this);
[email protected]04f6f982012-08-03 01:02:15716
[email protected]0a0e2c7b2014-06-16 19:10:14717 dispatcher()->OnMessageReceived(
[email protected]f4653192013-09-06 19:24:05718 ResourceMsg_ReceivedResponse(0, response_head));
[email protected]04f6f982012-08-03 01:02:15719 }
720
[email protected]ddf55bb2014-04-03 08:24:47721 // RequestPeer methods.
[email protected]04f6f982012-08-03 01:02:15722 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
723 }
724
[email protected]b97fc382014-05-14 20:06:34725 virtual bool OnReceivedRedirect(const GURL& new_url,
726 const GURL& new_first_party_for_cookies,
727 const ResourceResponseInfo& info) OVERRIDE {
[email protected]04f6f982012-08-03 01:02:15728 return true;
729 }
730
731 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
732 response_info_ = info;
733 }
734
[email protected]ad554bc2013-09-03 21:18:47735 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
[email protected]04f6f982012-08-03 01:02:15736 }
737
738 virtual void OnReceivedData(const char* data,
739 int data_length,
740 int encoded_data_length) OVERRIDE {
741 }
742
743 virtual void OnCompletedRequest(
[email protected]2756a8e2012-09-07 18:24:29744 int error_code,
745 bool was_ignored_by_handler,
[email protected]dcbe3df2014-02-06 23:08:37746 bool stale_copy_in_cache,
[email protected]04f6f982012-08-03 01:02:15747 const std::string& security_info,
[email protected]c8c567582014-02-10 12:54:57748 const base::TimeTicks& completion_time,
749 int64 total_transfer_size) OVERRIDE {
[email protected]04f6f982012-08-03 01:02:15750 }
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.
759TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
760 ResourceResponseHead response_head;
[email protected]2756a8e2012-09-07 18:24:29761 response_head.error_code = net::OK;
[email protected]04f6f982012-08-03 01:02:15762 response_head.request_start = base::TimeTicks::FromInternalValue(5);
763 response_head.response_start = base::TimeTicks::FromInternalValue(15);
[email protected]ec298802013-03-27 16:45:07764 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);
[email protected]04f6f982012-08-03 01:02:15769
770 PerformTest(response_head);
771
[email protected]ec298802013-03-27 16:45:07772 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);
[email protected]04f6f982012-08-03 01:02:15777}
778
779TEST_F(TimeConversionTest, PartiallyInitialized) {
780 ResourceResponseHead response_head;
[email protected]2756a8e2012-09-07 18:24:29781 response_head.error_code = net::OK;
[email protected]04f6f982012-08-03 01:02:15782 response_head.request_start = base::TimeTicks::FromInternalValue(5);
783 response_head.response_start = base::TimeTicks::FromInternalValue(15);
784
785 PerformTest(response_head);
786
[email protected]ec298802013-03-27 16:45:07787 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
788 EXPECT_EQ(base::TimeTicks(),
789 response_info().load_timing.connect_timing.dns_start);
[email protected]04f6f982012-08-03 01:02:15790}
791
792TEST_F(TimeConversionTest, NotInitialized) {
793 ResourceResponseHead response_head;
[email protected]2756a8e2012-09-07 18:24:29794 response_head.error_code = net::OK;
[email protected]04f6f982012-08-03 01:02:15795
796 PerformTest(response_head);
797
[email protected]ec298802013-03-27 16:45:07798 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
799 EXPECT_EQ(base::TimeTicks(),
800 response_info().load_timing.connect_timing.dns_start);
[email protected]04f6f982012-08-03 01:02:15801}
802
[email protected]be7b41e82012-07-04 09:46:51803} // namespace content