Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc

Issue 6532073: Move core pieces of browser\renderer_host to src\content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <vector>
6
7 #include "base/file_path.h"
8 #include "base/message_loop.h"
9 #include "base/process_util.h"
10 #include "chrome/browser/browser_thread.h"
11 #include "chrome/browser/child_process_security_policy.h"
12 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
13 #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
14 #include "chrome/browser/renderer_host/resource_handler.h"
15 #include "chrome/browser/renderer_host/resource_message_filter.h"
16 #include "chrome/common/chrome_plugin_lib.h"
17 #include "chrome/common/render_messages.h"
18 #include "chrome/common/render_messages_params.h"
19 #include "chrome/common/resource_response.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/upload_data.h"
22 #include "net/http/http_util.h"
23 #include "net/url_request/url_request.h"
24 #include "net/url_request/url_request_job.h"
25 #include "net/url_request/url_request_test_job.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "webkit/appcache/appcache_interfaces.h"
28
29 // TODO(eroman): Write unit tests for SafeBrowsing that exercise
30 // SafeBrowsingResourceHandler.
31
32 namespace {
33
34 // Returns the resource response header structure for this request.
35 void GetResponseHead(const std::vector<IPC::Message>& messages,
36 ResourceResponseHead* response_head) {
37 ASSERT_GE(messages.size(), 2U);
38
39 // The first messages should be received response.
40 ASSERT_EQ(ViewMsg_Resource_ReceivedResponse::ID, messages[0].type());
41
42 void* iter = NULL;
43 int request_id;
44 ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, &request_id));
45 ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, response_head));
46 }
47
48 } // namespace
49
50 static int RequestIDForMessage(const IPC::Message& msg) {
51 int request_id = -1;
52 switch (msg.type()) {
53 case ViewMsg_Resource_UploadProgress::ID:
54 case ViewMsg_Resource_ReceivedResponse::ID:
55 case ViewMsg_Resource_ReceivedRedirect::ID:
56 case ViewMsg_Resource_DataReceived::ID:
57 case ViewMsg_Resource_RequestComplete::ID:
58 request_id = IPC::MessageIterator(msg).NextInt();
59 break;
60 }
61 return request_id;
62 }
63
64 static ViewHostMsg_Resource_Request CreateResourceRequest(
65 const char* method,
66 ResourceType::Type type,
67 const GURL& url) {
68 ViewHostMsg_Resource_Request request;
69 request.method = std::string(method);
70 request.url = url;
71 request.first_party_for_cookies = url; // bypass third-party cookie blocking
72 request.load_flags = 0;
73 request.origin_pid = 0;
74 request.resource_type = type;
75 request.request_context = 0;
76 request.appcache_host_id = appcache::kNoHostId;
77 request.download_to_file = false;
78 request.host_renderer_id = -1;
79 request.host_render_view_id = -1;
80 return request;
81 }
82
83 // Spin up the message loop to kick off the request.
84 static void KickOffRequest() {
85 MessageLoop::current()->RunAllPending();
86 }
87
88 // We may want to move this to a shared space if it is useful for something else
89 class ResourceIPCAccumulator {
90 public:
91 void AddMessage(const IPC::Message& msg) {
92 messages_.push_back(msg);
93 }
94
95 // This groups the messages by their request ID. The groups will be in order
96 // that the first message for each request ID was received, and the messages
97 // within the groups will be in the order that they appeared.
98 // Note that this clears messages_.
99 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages;
100 void GetClassifiedMessages(ClassifiedMessages* msgs);
101
102 std::vector<IPC::Message> messages_;
103 };
104
105 // This is very inefficient as a result of repeatedly extracting the ID, use
106 // only for tests!
107 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
108 while (!messages_.empty()) {
109 std::vector<IPC::Message> cur_requests;
110 cur_requests.push_back(messages_[0]);
111 int cur_id = RequestIDForMessage(messages_[0]);
112
113 // find all other messages with this ID
114 for (int i = 1; i < static_cast<int>(messages_.size()); i++) {
115 int id = RequestIDForMessage(messages_[i]);
116 if (id == cur_id) {
117 cur_requests.push_back(messages_[i]);
118 messages_.erase(messages_.begin() + i);
119 i--;
120 }
121 }
122 messages_.erase(messages_.begin());
123 msgs->push_back(cur_requests);
124 }
125 }
126
127 // This class forwards the incoming messages to the ResourceDispatcherHostTest.
128 // This is used to emulate different sub-processes, since this filter will
129 // have a different ID than the original. For the test, we want all the incoming
130 // messages to go to the same place, which is why this forwards.
131 class ForwardingFilter : public ResourceMessageFilter {
132 public:
133 explicit ForwardingFilter(IPC::Message::Sender* dest)
134 : ResourceMessageFilter(ChildProcessInfo::GenerateChildProcessUniqueId(),
135 ChildProcessInfo::RENDER_PROCESS,
136 NULL),
137 dest_(dest) {
138 OnChannelConnected(base::GetCurrentProcId());
139 }
140
141 // ResourceMessageFilter override
142 virtual bool Send(IPC::Message* msg) {
143 if (!dest_)
144 return false;
145 return dest_->Send(msg);
146 }
147
148 private:
149 IPC::Message::Sender* dest_;
150
151 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter);
152 };
153
154 class ResourceDispatcherHostTest : public testing::Test,
155 public IPC::Message::Sender {
156 public:
157 ResourceDispatcherHostTest()
158 : ALLOW_THIS_IN_INITIALIZER_LIST(filter_(new ForwardingFilter(this))),
159 ui_thread_(BrowserThread::UI, &message_loop_),
160 io_thread_(BrowserThread::IO, &message_loop_),
161 old_factory_(NULL),
162 resource_type_(ResourceType::SUB_RESOURCE) {
163 }
164 // IPC::Message::Sender implementation
165 virtual bool Send(IPC::Message* msg) {
166 accum_.AddMessage(*msg);
167 delete msg;
168 return true;
169 }
170
171 protected:
172 // testing::Test
173 virtual void SetUp() {
174 DCHECK(!test_fixture_);
175 test_fixture_ = this;
176 ChildProcessSecurityPolicy::GetInstance()->Add(0);
177 net::URLRequest::RegisterProtocolFactory(
178 "test",
179 &ResourceDispatcherHostTest::Factory);
180 EnsureTestSchemeIsAllowed();
181 }
182
183 virtual void TearDown() {
184 net::URLRequest::RegisterProtocolFactory("test", NULL);
185 if (!scheme_.empty())
186 net::URLRequest::RegisterProtocolFactory(scheme_, old_factory_);
187
188 DCHECK(test_fixture_ == this);
189 test_fixture_ = NULL;
190
191 host_.Shutdown();
192
193 ChildProcessSecurityPolicy::GetInstance()->Remove(0);
194
195 // The plugin lib is automatically loaded during these test
196 // and we want a clean environment for other tests.
197 ChromePluginLib::UnloadAllPlugins();
198
199 // Flush the message loop to make Purify happy.
200 message_loop_.RunAllPending();
201 }
202
203 // Creates a request using the current test object as the filter.
204 void MakeTestRequest(int render_view_id,
205 int request_id,
206 const GURL& url);
207
208 // Generates a request using the given filter. This will probably be a
209 // ForwardingFilter.
210 void MakeTestRequest(ResourceMessageFilter* filter,
211 int render_view_id,
212 int request_id,
213 const GURL& url);
214
215 void MakeCancelRequest(int request_id);
216
217 void EnsureTestSchemeIsAllowed() {
218 static bool have_white_listed_test_scheme = false;
219
220 if (!have_white_listed_test_scheme) {
221 ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme("test");
222 have_white_listed_test_scheme = true;
223 }
224 }
225
226 // Sets a particular response for any request from now on. To switch back to
227 // the default bahavior, pass an empty |headers|. |headers| should be raw-
228 // formatted (NULLs instead of EOLs).
229 void SetResponse(const std::string& headers, const std::string& data) {
230 response_headers_ = headers;
231 response_data_ = data;
232 }
233
234 // Sets a particular resource type for any request from now on.
235 void SetResourceType(ResourceType::Type type) {
236 resource_type_ = type;
237 }
238
239 // Intercepts requests for the given protocol.
240 void HandleScheme(const std::string& scheme) {
241 DCHECK(scheme_.empty());
242 DCHECK(!old_factory_);
243 scheme_ = scheme;
244 old_factory_ = net::URLRequest::RegisterProtocolFactory(
245 scheme_, &ResourceDispatcherHostTest::Factory);
246 }
247
248 // Our own net::URLRequestJob factory.
249 static net::URLRequestJob* Factory(net::URLRequest* request,
250 const std::string& scheme) {
251 if (test_fixture_->response_headers_.empty()) {
252 return new net::URLRequestTestJob(request);
253 } else {
254 return new net::URLRequestTestJob(request,
255 test_fixture_->response_headers_,
256 test_fixture_->response_data_,
257 false);
258 }
259 }
260
261 scoped_refptr<ForwardingFilter> filter_;
262 MessageLoopForIO message_loop_;
263 BrowserThread ui_thread_;
264 BrowserThread io_thread_;
265 ResourceDispatcherHost host_;
266 ResourceIPCAccumulator accum_;
267 std::string response_headers_;
268 std::string response_data_;
269 std::string scheme_;
270 net::URLRequest::ProtocolFactory* old_factory_;
271 ResourceType::Type resource_type_;
272 static ResourceDispatcherHostTest* test_fixture_;
273 };
274 // Static.
275 ResourceDispatcherHostTest* ResourceDispatcherHostTest::test_fixture_ = NULL;
276
277 void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
278 int request_id,
279 const GURL& url) {
280 MakeTestRequest(filter_.get(), render_view_id, request_id, url);
281 }
282
283 void ResourceDispatcherHostTest::MakeTestRequest(
284 ResourceMessageFilter* filter,
285 int render_view_id,
286 int request_id,
287 const GURL& url) {
288 ViewHostMsg_Resource_Request request =
289 CreateResourceRequest("GET", resource_type_, url);
290 ViewHostMsg_RequestResource msg(render_view_id, request_id, request);
291 bool msg_was_ok;
292 host_.OnMessageReceived(msg, filter, &msg_was_ok);
293 KickOffRequest();
294 }
295
296 void ResourceDispatcherHostTest::MakeCancelRequest(int request_id) {
297 host_.CancelRequest(filter_->child_id(), request_id, false);
298 }
299
300 void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
301 const std::string& reference_data) {
302 // A successful request will have received 4 messages:
303 // ReceivedResponse (indicates headers received)
304 // DataReceived (data)
305 // XXX DataReceived (0 bytes remaining from a read)
306 // RequestComplete (request is done)
307 //
308 // This function verifies that we received 4 messages and that they
309 // are appropriate.
310 ASSERT_EQ(3U, messages.size());
311
312 // The first messages should be received response
313 ASSERT_EQ(ViewMsg_Resource_ReceivedResponse::ID, messages[0].type());
314
315 // followed by the data, currently we only do the data in one chunk, but
316 // should probably test multiple chunks later
317 ASSERT_EQ(ViewMsg_Resource_DataReceived::ID, messages[1].type());
318
319 void* iter = NULL;
320 int request_id;
321 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &request_id));
322 base::SharedMemoryHandle shm_handle;
323 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &shm_handle));
324 uint32 data_len;
325 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &data_len));
326
327 ASSERT_EQ(reference_data.size(), data_len);
328 base::SharedMemory shared_mem(shm_handle, true); // read only
329 shared_mem.Map(data_len);
330 const char* data = static_cast<char*>(shared_mem.memory());
331 ASSERT_EQ(0, memcmp(reference_data.c_str(), data, data_len));
332
333 // followed by a 0-byte read
334 //ASSERT_EQ(ViewMsg_Resource_DataReceived::ID, messages[2].type());
335
336 // the last message should be all data received
337 ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, messages[2].type());
338 }
339
340 // Tests whether many messages get dispatched properly.
341 TEST_F(ResourceDispatcherHostTest, TestMany) {
342 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
343
344 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
345 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
346 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
347
348 // flush all the pending requests
349 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
350
351 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
352
353 // sorts out all the messages we saw by request
354 ResourceIPCAccumulator::ClassifiedMessages msgs;
355 accum_.GetClassifiedMessages(&msgs);
356
357 // there are three requests, so we should have gotten them classified as such
358 ASSERT_EQ(3U, msgs.size());
359
360 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
361 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_2());
362 CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
363 }
364
365 // Tests whether messages get canceled properly. We issue three requests,
366 // cancel one of them, and make sure that each sent the proper notifications.
367 TEST_F(ResourceDispatcherHostTest, Cancel) {
368 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
369
370 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
371 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
372 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
373 MakeCancelRequest(2);
374
375 // flush all the pending requests
376 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
377 MessageLoop::current()->RunAllPending();
378
379 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
380
381 ResourceIPCAccumulator::ClassifiedMessages msgs;
382 accum_.GetClassifiedMessages(&msgs);
383
384 // there are three requests, so we should have gotten them classified as such
385 ASSERT_EQ(3U, msgs.size());
386
387 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
388 CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
389
390 // Check that request 2 got canceled.
391 ASSERT_EQ(2U, msgs[1].size());
392 ASSERT_EQ(ViewMsg_Resource_ReceivedResponse::ID, msgs[1][0].type());
393 ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][1].type());
394
395 int request_id;
396 net::URLRequestStatus status;
397
398 void* iter = NULL;
399 ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &request_id));
400 ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &status));
401
402 EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
403 }
404
405 // The host delegate acts as a second one so we can have some requests
406 // pending and some canceled.
407 class TestFilter : public ForwardingFilter {
408 public:
409 TestFilter()
410 : ForwardingFilter(NULL),
411 has_canceled_(false),
412 received_after_canceled_(0) {
413 }
414
415 // ForwardingFilter override
416 virtual bool Send(IPC::Message* msg) {
417 // no messages should be received when the process has been canceled
418 if (has_canceled_)
419 received_after_canceled_++;
420 delete msg;
421 return true;
422 }
423 bool has_canceled_;
424 int received_after_canceled_;
425 };
426
427 // Tests CancelRequestsForProcess
428 TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
429 scoped_refptr<TestFilter> test_filter = new TestFilter();
430
431 // request 1 goes to the test delegate
432 ViewHostMsg_Resource_Request request = CreateResourceRequest(
433 "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
434
435 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
436
437 MakeTestRequest(test_filter.get(), 0, 1,
438 net::URLRequestTestJob::test_url_1());
439
440 // request 2 goes to us
441 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
442
443 // request 3 goes to the test delegate
444 MakeTestRequest(test_filter.get(), 0, 3,
445 net::URLRequestTestJob::test_url_3());
446
447 // TODO(mbelshe):
448 // Now that the async IO path is in place, the IO always completes on the
449 // initial call; so the requests have already completed. This basically
450 // breaks the whole test.
451 //EXPECT_EQ(3, host_.pending_requests());
452
453 // Process each request for one level so one callback is called.
454 for (int i = 0; i < 3; i++)
455 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
456
457 // Cancel the requests to the test process.
458 host_.CancelRequestsForProcess(filter_->child_id());
459 test_filter->has_canceled_ = true;
460
461 // Flush all the pending requests.
462 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
463
464 EXPECT_EQ(0, host_.pending_requests());
465 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
466
467 // The test delegate should not have gotten any messages after being canceled.
468 ASSERT_EQ(0, test_filter->received_after_canceled_);
469
470 // We should have gotten exactly one result.
471 ResourceIPCAccumulator::ClassifiedMessages msgs;
472 accum_.GetClassifiedMessages(&msgs);
473 ASSERT_EQ(1U, msgs.size());
474 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
475 }
476
477 // Tests blocking and resuming requests.
478 TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
479 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
480
481 host_.BlockRequestsForRoute(filter_->child_id(), 1);
482 host_.BlockRequestsForRoute(filter_->child_id(), 2);
483 host_.BlockRequestsForRoute(filter_->child_id(), 3);
484
485 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
486 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
487 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
488 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
489 MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
490 MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
491
492 // Flush all the pending requests
493 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
494
495 // Sort out all the messages we saw by request
496 ResourceIPCAccumulator::ClassifiedMessages msgs;
497 accum_.GetClassifiedMessages(&msgs);
498
499 // All requests but the 2 for the RVH 0 should have been blocked.
500 ASSERT_EQ(2U, msgs.size());
501
502 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
503 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
504
505 // Resume requests for RVH 1 and flush pending requests.
506 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 1);
507 KickOffRequest();
508 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
509
510 msgs.clear();
511 accum_.GetClassifiedMessages(&msgs);
512 ASSERT_EQ(2U, msgs.size());
513 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
514 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_1());
515
516 // Test that new requests are not blocked for RVH 1.
517 MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
518 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
519 msgs.clear();
520 accum_.GetClassifiedMessages(&msgs);
521 ASSERT_EQ(1U, msgs.size());
522 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
523
524 // Now resumes requests for all RVH (2 and 3).
525 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 2);
526 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 3);
527 KickOffRequest();
528 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
529
530 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
531
532 msgs.clear();
533 accum_.GetClassifiedMessages(&msgs);
534 ASSERT_EQ(2U, msgs.size());
535 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
536 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
537 }
538
539 // Tests blocking and canceling requests.
540 TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
541 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
542
543 host_.BlockRequestsForRoute(filter_->child_id(), 1);
544
545 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
546 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
547 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
548 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
549
550 // Flush all the pending requests.
551 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
552
553 // Sort out all the messages we saw by request.
554 ResourceIPCAccumulator::ClassifiedMessages msgs;
555 accum_.GetClassifiedMessages(&msgs);
556
557 // The 2 requests for the RVH 0 should have been processed.
558 ASSERT_EQ(2U, msgs.size());
559
560 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
561 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
562
563 // Cancel requests for RVH 1.
564 host_.CancelBlockedRequestsForRoute(filter_->child_id(), 1);
565 KickOffRequest();
566 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
567
568 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
569
570 msgs.clear();
571 accum_.GetClassifiedMessages(&msgs);
572 ASSERT_EQ(0U, msgs.size());
573 }
574
575 // Tests that blocked requests are canceled if their associated process dies.
576 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
577 // This second filter is used to emulate a second process.
578 scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(this);
579
580 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
581 EXPECT_EQ(0,
582 host_.GetOutstandingRequestsMemoryCost(second_filter->child_id()));
583
584 host_.BlockRequestsForRoute(second_filter->child_id(), 0);
585
586 MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
587 MakeTestRequest(second_filter.get(), 0, 2,
588 net::URLRequestTestJob::test_url_2());
589 MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
590 MakeTestRequest(second_filter.get(), 0, 4,
591 net::URLRequestTestJob::test_url_1());
592
593 // Simulate process death.
594 host_.CancelRequestsForProcess(second_filter->child_id());
595
596 // Flush all the pending requests.
597 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
598
599 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
600 EXPECT_EQ(0,
601 host_.GetOutstandingRequestsMemoryCost(second_filter->child_id()));
602
603 // Sort out all the messages we saw by request.
604 ResourceIPCAccumulator::ClassifiedMessages msgs;
605 accum_.GetClassifiedMessages(&msgs);
606
607 // The 2 requests for the RVH 0 should have been processed.
608 ASSERT_EQ(2U, msgs.size());
609
610 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
611 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
612
613 EXPECT_TRUE(host_.blocked_requests_map_.empty());
614 }
615
616 // Tests that blocked requests don't leak when the ResourceDispatcherHost goes
617 // away. Note that we rely on Purify for finding the leaks if any.
618 // If this test turns the Purify bot red, check the ResourceDispatcherHost
619 // destructor to make sure the blocked requests are deleted.
620 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
621 // This second filter is used to emulate a second process.
622 scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(this);
623
624 host_.BlockRequestsForRoute(filter_->child_id(), 1);
625 host_.BlockRequestsForRoute(filter_->child_id(), 2);
626 host_.BlockRequestsForRoute(second_filter->child_id(), 1);
627
628 MakeTestRequest(filter_.get(), 0, 1, net::URLRequestTestJob::test_url_1());
629 MakeTestRequest(filter_.get(), 1, 2, net::URLRequestTestJob::test_url_2());
630 MakeTestRequest(filter_.get(), 0, 3, net::URLRequestTestJob::test_url_3());
631 MakeTestRequest(second_filter.get(), 1, 4,
632 net::URLRequestTestJob::test_url_1());
633 MakeTestRequest(filter_.get(), 2, 5, net::URLRequestTestJob::test_url_2());
634 MakeTestRequest(filter_.get(), 2, 6, net::URLRequestTestJob::test_url_3());
635
636 // Flush all the pending requests.
637 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
638 }
639
640 // Test the private helper method "CalculateApproximateMemoryCost()".
641 TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
642 net::URLRequest req(GURL("http://www.google.com"), NULL);
643 EXPECT_EQ(4427, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
644
645 // Add 9 bytes of referrer.
646 req.set_referrer("123456789");
647 EXPECT_EQ(4436, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
648
649 // Add 33 bytes of upload content.
650 std::string upload_content;
651 upload_content.resize(33);
652 std::fill(upload_content.begin(), upload_content.end(), 'x');
653 req.AppendBytesToUpload(upload_content.data(), upload_content.size());
654
655 // Since the upload throttling is disabled, this has no effect on the cost.
656 EXPECT_EQ(4436, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
657
658 // Add a file upload -- should have no effect.
659 req.AppendFileToUpload(FilePath(FILE_PATH_LITERAL("does-not-exist.png")));
660 EXPECT_EQ(4436, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
661 }
662
663 // Test the private helper method "IncrementOutstandingRequestsMemoryCost()".
664 TEST_F(ResourceDispatcherHostTest, IncrementOutstandingRequestsMemoryCost) {
665 // Add some counts for render_process_host=7
666 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(7));
667 EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(1, 7));
668 EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(1, 7));
669 EXPECT_EQ(3, host_.IncrementOutstandingRequestsMemoryCost(1, 7));
670
671 // Add some counts for render_process_host=3
672 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(3));
673 EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(1, 3));
674 EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(1, 3));
675
676 // Remove all the counts for render_process_host=7
677 EXPECT_EQ(3, host_.GetOutstandingRequestsMemoryCost(7));
678 EXPECT_EQ(2, host_.IncrementOutstandingRequestsMemoryCost(-1, 7));
679 EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(-1, 7));
680 EXPECT_EQ(0, host_.IncrementOutstandingRequestsMemoryCost(-1, 7));
681 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(7));
682
683 // Remove all the counts for render_process_host=3
684 EXPECT_EQ(2, host_.GetOutstandingRequestsMemoryCost(3));
685 EXPECT_EQ(1, host_.IncrementOutstandingRequestsMemoryCost(-1, 3));
686 EXPECT_EQ(0, host_.IncrementOutstandingRequestsMemoryCost(-1, 3));
687 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(3));
688
689 // When an entry reaches 0, it should be deleted.
690 EXPECT_TRUE(host_.outstanding_requests_memory_cost_map_.end() ==
691 host_.outstanding_requests_memory_cost_map_.find(7));
692 EXPECT_TRUE(host_.outstanding_requests_memory_cost_map_.end() ==
693 host_.outstanding_requests_memory_cost_map_.find(3));
694 }
695
696 // Test that when too many requests are outstanding for a particular
697 // render_process_host_id, any subsequent request from it fails.
698 TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
699 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
700
701 // Expected cost of each request as measured by
702 // ResourceDispatcherHost::CalculateApproximateMemoryCost().
703 int kMemoryCostOfTest2Req =
704 ResourceDispatcherHost::kAvgBytesPerOutstandingRequest +
705 std::string("GET").size() +
706 net::URLRequestTestJob::test_url_2().spec().size();
707
708 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
709 int kMaxCostPerProcess = 440000;
710 host_.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess);
711
712 // Determine how many instance of test_url_2() we can request before
713 // throttling kicks in.
714 size_t kMaxRequests = kMaxCostPerProcess / kMemoryCostOfTest2Req;
715
716 // This second filter is used to emulate a second process.
717 scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(this);
718
719 // Saturate the number of outstanding requests for our process.
720 for (size_t i = 0; i < kMaxRequests; ++i) {
721 MakeTestRequest(filter_.get(), 0, i + 1,
722 net::URLRequestTestJob::test_url_2());
723 }
724
725 // Issue two more requests for our process -- these should fail immediately.
726 MakeTestRequest(filter_.get(), 0, kMaxRequests + 1,
727 net::URLRequestTestJob::test_url_2());
728 MakeTestRequest(filter_.get(), 0, kMaxRequests + 2,
729 net::URLRequestTestJob::test_url_2());
730
731 // Issue two requests for the second process -- these should succeed since
732 // it is just process 0 that is saturated.
733 MakeTestRequest(second_filter.get(), 0, kMaxRequests + 3,
734 net::URLRequestTestJob::test_url_2());
735 MakeTestRequest(second_filter.get(), 0, kMaxRequests + 4,
736 net::URLRequestTestJob::test_url_2());
737
738 // Flush all the pending requests.
739 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
740 MessageLoop::current()->RunAllPending();
741
742 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
743
744 // Sorts out all the messages we saw by request.
745 ResourceIPCAccumulator::ClassifiedMessages msgs;
746 accum_.GetClassifiedMessages(&msgs);
747
748 // We issued (kMaxRequests + 4) total requests.
749 ASSERT_EQ(kMaxRequests + 4, msgs.size());
750
751 // Check that the first kMaxRequests succeeded.
752 for (size_t i = 0; i < kMaxRequests; ++i)
753 CheckSuccessfulRequest(msgs[i], net::URLRequestTestJob::test_data_2());
754
755 // Check that the subsequent two requests (kMaxRequests + 1) and
756 // (kMaxRequests + 2) were failed, since the per-process bound was reached.
757 for (int i = 0; i < 2; ++i) {
758 // Should have sent a single RequestComplete message.
759 int index = kMaxRequests + i;
760 EXPECT_EQ(1U, msgs[index].size());
761 EXPECT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[index][0].type());
762
763 // The RequestComplete message should have had status
764 // (CANCELLED, ERR_INSUFFICIENT_RESOURCES).
765 int request_id;
766 net::URLRequestStatus status;
767
768 void* iter = NULL;
769 EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &request_id));
770 EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &status));
771
772 EXPECT_EQ(index + 1, request_id);
773 EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
774 EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, status.os_error());
775 }
776
777 // The final 2 requests should have succeeded.
778 CheckSuccessfulRequest(msgs[kMaxRequests + 2],
779 net::URLRequestTestJob::test_data_2());
780 CheckSuccessfulRequest(msgs[kMaxRequests + 3],
781 net::URLRequestTestJob::test_data_2());
782 }
783
784 // Tests that we sniff the mime type for a simple request.
785 TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
786 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
787
788 std::string response("HTTP/1.1 200 OK\n\n");
789 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
790 response.size()));
791 std::string response_data("<html><title>Test One</title></html>");
792 SetResponse(raw_headers, response_data);
793
794 HandleScheme("http");
795 MakeTestRequest(0, 1, GURL("http:bla"));
796
797 // Flush all pending requests.
798 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
799
800 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
801
802 // Sorts out all the messages we saw by request.
803 ResourceIPCAccumulator::ClassifiedMessages msgs;
804 accum_.GetClassifiedMessages(&msgs);
805 ASSERT_EQ(1U, msgs.size());
806
807 ResourceResponseHead response_head;
808 GetResponseHead(msgs[0], &response_head);
809 ASSERT_EQ("text/html", response_head.mime_type);
810 }
811
812 // Tests that we don't sniff the mime type when the server provides one.
813 TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
814 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
815
816 std::string response("HTTP/1.1 200 OK\n"
817 "Content-type: image/jpeg\n\n");
818 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
819 response.size()));
820 std::string response_data("<html><title>Test One</title></html>");
821 SetResponse(raw_headers, response_data);
822
823 HandleScheme("http");
824 MakeTestRequest(0, 1, GURL("http:bla"));
825
826 // Flush all pending requests.
827 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
828
829 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
830
831 // Sorts out all the messages we saw by request.
832 ResourceIPCAccumulator::ClassifiedMessages msgs;
833 accum_.GetClassifiedMessages(&msgs);
834 ASSERT_EQ(1U, msgs.size());
835
836 ResourceResponseHead response_head;
837 GetResponseHead(msgs[0], &response_head);
838 ASSERT_EQ("image/jpeg", response_head.mime_type);
839 }
840
841 // Tests that we don't sniff the mime type when there is no message body.
842 TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
843 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
844
845 std::string response("HTTP/1.1 304 Not Modified\n\n");
846 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
847 response.size()));
848 std::string response_data;
849 SetResponse(raw_headers, response_data);
850
851 HandleScheme("http");
852 MakeTestRequest(0, 1, GURL("http:bla"));
853
854 // Flush all pending requests.
855 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
856
857 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
858
859 // Sorts out all the messages we saw by request.
860 ResourceIPCAccumulator::ClassifiedMessages msgs;
861 accum_.GetClassifiedMessages(&msgs);
862 ASSERT_EQ(1U, msgs.size());
863
864 ResourceResponseHead response_head;
865 GetResponseHead(msgs[0], &response_head);
866 ASSERT_EQ("", response_head.mime_type);
867 }
868
869 TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
870 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
871
872 std::string response("HTTP/1.1 204 No Content\n\n");
873 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
874 response.size()));
875 std::string response_data;
876 SetResponse(raw_headers, response_data);
877
878 HandleScheme("http");
879 MakeTestRequest(0, 1, GURL("http:bla"));
880
881 // Flush all pending requests.
882 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
883
884 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
885
886 // Sorts out all the messages we saw by request.
887 ResourceIPCAccumulator::ClassifiedMessages msgs;
888 accum_.GetClassifiedMessages(&msgs);
889 ASSERT_EQ(1U, msgs.size());
890
891 ResourceResponseHead response_head;
892 GetResponseHead(msgs[0], &response_head);
893 ASSERT_EQ("text/plain", response_head.mime_type);
894 }
895
896 // Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
897 TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
898 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
899
900 std::string response("HTTP/1.1 403 Forbidden\n"
901 "Content-disposition: attachment; filename=blah\n"
902 "Content-type: application/octet-stream\n\n");
903 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
904 response.size()));
905 std::string response_data("<html><title>Test One</title></html>");
906 SetResponse(raw_headers, response_data);
907
908 // Only MAIN_FRAMEs can trigger a download.
909 SetResourceType(ResourceType::MAIN_FRAME);
910
911 HandleScheme("http");
912 MakeTestRequest(0, 1, GURL("http:bla"));
913
914 // Flush all pending requests.
915 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
916
917 EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
918
919 // Sorts out all the messages we saw by request.
920 ResourceIPCAccumulator::ClassifiedMessages msgs;
921 accum_.GetClassifiedMessages(&msgs);
922
923 // We should have gotten one RequestComplete message.
924 ASSERT_EQ(1U, msgs[0].size());
925 EXPECT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[0][0].type());
926
927 // The RequestComplete message should have had status
928 // (CANCELED, ERR_FILE_NOT_FOUND).
929 int request_id;
930 net::URLRequestStatus status;
931
932 void* iter = NULL;
933 EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &request_id));
934 EXPECT_TRUE(IPC::ReadParam(&msgs[0][0], &iter, &status));
935
936 EXPECT_EQ(1, request_id);
937 EXPECT_EQ(net::URLRequestStatus::CANCELED, status.status());
938 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, status.os_error());
939 }
940
941 class DummyResourceHandler : public ResourceHandler {
942 public:
943 DummyResourceHandler() {}
944
945 // Called as upload progress is made.
946 bool OnUploadProgress(int request_id, uint64 position, uint64 size) {
947 return true;
948 }
949
950 bool OnRequestRedirected(int request_id, const GURL& url,
951 ResourceResponse* response, bool* defer) {
952 return true;
953 }
954
955 bool OnResponseStarted(int request_id, ResourceResponse* response) {
956 return true;
957 }
958
959 bool OnWillStart(int request_id, const GURL& url, bool* defer) {
960 return true;
961 }
962
963 bool OnWillRead(
964 int request_id, net::IOBuffer** buf, int* buf_size, int min_size) {
965 return true;
966 }
967
968 bool OnReadCompleted(int request_id, int* bytes_read) { return true; }
969
970 bool OnResponseCompleted(
971 int request_id,
972 const net::URLRequestStatus& status,
973 const std::string& info) {
974 return true;
975 }
976
977 void OnRequestClosed() {}
978
979 private:
980 DISALLOW_COPY_AND_ASSIGN(DummyResourceHandler);
981 };
982
983 class ApplyExtensionLocalizationFilterTest : public testing::Test {
984 protected:
985 void SetUp() {
986 url_.reset(new GURL(
987 "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/popup.html"));
988 resource_type_ = ResourceType::STYLESHEET;
989 resource_handler_.reset(new DummyResourceHandler());
990 request_info_.reset(CreateNewResourceRequestInfo());
991 }
992
993 ResourceDispatcherHostRequestInfo* CreateNewResourceRequestInfo() {
994 return new ResourceDispatcherHostRequestInfo(
995 resource_handler_.get(), ChildProcessInfo::RENDER_PROCESS, 0, 0, 0,
996 ResourceType::STYLESHEET, 0U, false, false, false, -1, -1);
997 }
998
999 scoped_ptr<GURL> url_;
1000 ResourceType::Type resource_type_;
1001 scoped_ptr<DummyResourceHandler> resource_handler_;
1002 scoped_ptr<ResourceDispatcherHostRequestInfo> request_info_;
1003 };
1004
1005 TEST_F(ApplyExtensionLocalizationFilterTest, WrongScheme) {
1006 url_.reset(new GURL("html://behllobkkfkfnphdnhnkndlbkcpglgmj/popup.html"));
1007 ResourceDispatcherHost::ApplyExtensionLocalizationFilter(*url_,
1008 resource_type_, request_info_.get());
1009
1010 EXPECT_FALSE(request_info_->replace_extension_localization_templates());
1011 }
1012
1013 TEST_F(ApplyExtensionLocalizationFilterTest, GoodScheme) {
1014 ResourceDispatcherHost::ApplyExtensionLocalizationFilter(*url_,
1015 resource_type_, request_info_.get());
1016
1017 EXPECT_TRUE(request_info_->replace_extension_localization_templates());
1018 }
1019
1020 TEST_F(ApplyExtensionLocalizationFilterTest, GoodSchemeWrongResourceType) {
1021 resource_type_ = ResourceType::MAIN_FRAME;
1022 ResourceDispatcherHost::ApplyExtensionLocalizationFilter(*url_,
1023 resource_type_, request_info_.get());
1024
1025 EXPECT_FALSE(request_info_->replace_extension_localization_templates());
1026 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698