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.
8 #include "base/files/file_path.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/pickle.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "content/browser/browser_thread_impl.h"
16 #include "content/browser/child_process_security_policy_impl.h"
17 #include "content/browser/loader/detachable_resource_handler.h"
18 #include "content/browser/loader/resource_dispatcher_host_impl.h"
19 #include "content/browser/loader/resource_loader.h"
20 #include "content/browser/loader/resource_message_filter.h"
21 #include "content/browser/loader/resource_request_info_impl.h"
22 #include "content/browser/worker_host/worker_service_impl.h"
23 #include "content/common/child_process_host_impl.h"
24 #include "content/common/resource_messages.h"
25 #include "content/common/view_messages.h"
26 #include "content/public/browser/global_request_id.h"
27 #include "content/public/browser/resource_context.h"
28 #include "content/public/browser/resource_dispatcher_host_delegate.h"
29 #include "content/public/browser/resource_request_info.h"
30 #include "content/public/browser/resource_throttle.h"
31 #include "content/public/common/process_type.h"
32 #include "content/public/common/resource_response.h"
33 #include "content/public/test/test_browser_context.h"
34 #include "content/test/test_content_browser_client.h"
35 #include "net/base/net_errors.h"
36 #include "net/base/request_priority.h"
37 #include "net/base/upload_bytes_element_reader.h"
38 #include "net/base/upload_data_stream.h"
39 #include "net/http/http_util.h"
40 #include "net/url_request/url_request.h"
41 #include "net/url_request/url_request_context.h"
42 #include "net/url_request/url_request_job.h"
43 #include "net/url_request/url_request_simple_job.h"
44 #include "net/url_request/url_request_test_job.h"
45 #include "net/url_request/url_request_test_util.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 #include "webkit/common/appcache/appcache_interfaces.h"
49 // TODO(eroman): Write unit tests for SafeBrowsing that exercise
50 // SafeBrowsingResourceHandler.
56 // Returns the resource response header structure for this request.
57 void GetResponseHead(const std::vector
<IPC::Message
>& messages
,
58 ResourceResponseHead
* response_head
) {
59 ASSERT_GE(messages
.size(), 2U);
61 // The first messages should be received response.
62 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
64 PickleIterator
iter(messages
[0]);
66 ASSERT_TRUE(IPC::ReadParam(&messages
[0], &iter
, &request_id
));
67 ASSERT_TRUE(IPC::ReadParam(&messages
[0], &iter
, response_head
));
70 void GenerateIPCMessage(
71 scoped_refptr
<ResourceMessageFilter
> filter
,
72 scoped_ptr
<IPC::Message
> message
) {
74 ResourceDispatcherHostImpl::Get()->OnMessageReceived(
75 *message
, filter
.get(), &msg_is_ok
);
80 static int RequestIDForMessage(const IPC::Message
& msg
) {
83 case ResourceMsg_UploadProgress::ID
:
84 case ResourceMsg_ReceivedResponse::ID
:
85 case ResourceMsg_ReceivedRedirect::ID
:
86 case ResourceMsg_SetDataBuffer::ID
:
87 case ResourceMsg_DataReceived::ID
:
88 case ResourceMsg_RequestComplete::ID
: {
89 bool result
= PickleIterator(msg
).ReadInt(&request_id
);
97 static ResourceHostMsg_Request
CreateResourceRequest(
99 ResourceType::Type type
,
101 ResourceHostMsg_Request request
;
102 request
.method
= std::string(method
);
104 request
.first_party_for_cookies
= url
; // bypass third-party cookie blocking
105 request
.referrer_policy
= blink::WebReferrerPolicyDefault
;
106 request
.load_flags
= 0;
107 request
.origin_pid
= 0;
108 request
.resource_type
= type
;
109 request
.request_context
= 0;
110 request
.appcache_host_id
= appcache::kNoHostId
;
111 request
.download_to_file
= false;
112 request
.is_main_frame
= true;
113 request
.frame_id
= 0;
114 request
.parent_is_main_frame
= false;
115 request
.parent_frame_id
= -1;
116 request
.transition_type
= PAGE_TRANSITION_LINK
;
117 request
.allow_download
= true;
121 // Spin up the message loop to kick off the request.
122 static void KickOffRequest() {
123 base::MessageLoop::current()->RunUntilIdle();
126 // We may want to move this to a shared space if it is useful for something else
127 class ResourceIPCAccumulator
{
129 void AddMessage(const IPC::Message
& msg
) {
130 messages_
.push_back(msg
);
133 // This groups the messages by their request ID. The groups will be in order
134 // that the first message for each request ID was received, and the messages
135 // within the groups will be in the order that they appeared.
136 // Note that this clears messages_.
137 typedef std::vector
< std::vector
<IPC::Message
> > ClassifiedMessages
;
138 void GetClassifiedMessages(ClassifiedMessages
* msgs
);
141 std::vector
<IPC::Message
> messages_
;
144 // This is very inefficient as a result of repeatedly extracting the ID, use
146 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages
* msgs
) {
147 while (!messages_
.empty()) {
148 // Ignore unknown message types as it is valid for code to generated other
149 // IPCs as side-effects that we are not testing here.
150 int cur_id
= RequestIDForMessage(messages_
[0]);
152 std::vector
<IPC::Message
> cur_requests
;
153 cur_requests
.push_back(messages_
[0]);
154 // find all other messages with this ID
155 for (int i
= 1; i
< static_cast<int>(messages_
.size()); i
++) {
156 int id
= RequestIDForMessage(messages_
[i
]);
158 cur_requests
.push_back(messages_
[i
]);
159 messages_
.erase(messages_
.begin() + i
);
163 msgs
->push_back(cur_requests
);
165 messages_
.erase(messages_
.begin());
169 // This class forwards the incoming messages to the ResourceDispatcherHostTest.
170 // This is used to emulate different sub-processes, since this filter will
171 // have a different ID than the original. For the test, we want all the incoming
172 // messages to go to the same place, which is why this forwards.
173 class ForwardingFilter
: public ResourceMessageFilter
{
175 explicit ForwardingFilter(IPC::Sender
* dest
,
176 ResourceContext
* resource_context
)
177 : ResourceMessageFilter(
178 ChildProcessHostImpl::GenerateChildProcessUniqueId(),
179 PROCESS_TYPE_RENDERER
, NULL
, NULL
, NULL
,
180 base::Bind(&ForwardingFilter::GetContexts
,
181 base::Unretained(this))),
183 resource_context_(resource_context
) {
184 set_peer_pid_for_testing(base::GetCurrentProcId());
187 // ResourceMessageFilter override
188 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
191 return dest_
->Send(msg
);
194 ResourceContext
* resource_context() { return resource_context_
; }
197 virtual ~ForwardingFilter() {}
200 void GetContexts(const ResourceHostMsg_Request
& request
,
201 ResourceContext
** resource_context
,
202 net::URLRequestContext
** request_context
) {
203 *resource_context
= resource_context_
;
204 *request_context
= resource_context_
->GetRequestContext();
208 ResourceContext
* resource_context_
;
210 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter
);
213 // This class is a variation on URLRequestTestJob that will call
214 // URLRequest::OnBeforeNetworkStart before starting.
215 class URLRequestTestDelayedNetworkJob
: public net::URLRequestTestJob
{
217 URLRequestTestDelayedNetworkJob(net::URLRequest
* request
,
218 net::NetworkDelegate
* network_delegate
)
219 : net::URLRequestTestJob(request
, network_delegate
) {}
221 // Only start if not deferred for network start.
222 virtual void Start() OVERRIDE
{
224 NotifyBeforeNetworkStart(&defer
);
227 net::URLRequestTestJob::Start();
230 virtual void ResumeNetworkStart() OVERRIDE
{
231 net::URLRequestTestJob::StartAsync();
235 virtual ~URLRequestTestDelayedNetworkJob() {}
237 DISALLOW_COPY_AND_ASSIGN(URLRequestTestDelayedNetworkJob
);
240 // This class is a variation on URLRequestTestJob in that it does
241 // not complete start upon entry, only when specifically told to.
242 class URLRequestTestDelayedStartJob
: public net::URLRequestTestJob
{
244 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
245 net::NetworkDelegate
* network_delegate
)
246 : net::URLRequestTestJob(request
, network_delegate
) {
249 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
250 net::NetworkDelegate
* network_delegate
,
252 : net::URLRequestTestJob(request
, network_delegate
, auto_advance
) {
255 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
256 net::NetworkDelegate
* network_delegate
,
257 const std::string
& response_headers
,
258 const std::string
& response_data
,
260 : net::URLRequestTestJob(request
,
268 // Do nothing until you're told to.
269 virtual void Start() OVERRIDE
{}
271 // Finish starting a URL request whose job is an instance of
272 // URLRequestTestDelayedStartJob. It is illegal to call this routine
273 // with a URLRequest that does not use URLRequestTestDelayedStartJob.
274 static void CompleteStart(net::URLRequest
* request
) {
275 for (URLRequestTestDelayedStartJob
* job
= list_head_
;
278 if (job
->request() == request
) {
279 job
->net::URLRequestTestJob::Start();
286 static bool DelayedStartQueueEmpty() {
290 static void ClearQueue() {
293 << "Unreleased entries on URLRequestTestDelayedStartJob delay queue"
294 << "; may result in leaks.";
300 virtual ~URLRequestTestDelayedStartJob() {
301 for (URLRequestTestDelayedStartJob
** job
= &list_head_
; *job
;
302 job
= &(*job
)->next_
) {
304 *job
= (*job
)->next_
;
317 static URLRequestTestDelayedStartJob
* list_head_
;
318 URLRequestTestDelayedStartJob
* next_
;
321 URLRequestTestDelayedStartJob
*
322 URLRequestTestDelayedStartJob::list_head_
= NULL
;
324 // This class is a variation on URLRequestTestJob in that it
325 // returns IO_pending errors before every read, not just the first one.
326 class URLRequestTestDelayedCompletionJob
: public net::URLRequestTestJob
{
328 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
329 net::NetworkDelegate
* network_delegate
)
330 : net::URLRequestTestJob(request
, network_delegate
) {}
331 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
332 net::NetworkDelegate
* network_delegate
,
334 : net::URLRequestTestJob(request
, network_delegate
, auto_advance
) {}
335 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
336 net::NetworkDelegate
* network_delegate
,
337 const std::string
& response_headers
,
338 const std::string
& response_data
,
340 : net::URLRequestTestJob(request
,
347 virtual ~URLRequestTestDelayedCompletionJob() {}
350 virtual bool NextReadAsync() OVERRIDE
{ return true; }
353 class URLRequestBigJob
: public net::URLRequestSimpleJob
{
355 URLRequestBigJob(net::URLRequest
* request
,
356 net::NetworkDelegate
* network_delegate
)
357 : net::URLRequestSimpleJob(request
, network_delegate
) {
360 virtual int GetData(std::string
* mime_type
,
361 std::string
* charset
,
363 const net::CompletionCallback
& callback
) const OVERRIDE
{
364 *mime_type
= "text/plain";
369 if (!ParseURL(request_
->url(), &text
, &count
))
370 return net::ERR_INVALID_URL
;
372 data
->reserve(text
.size() * count
);
373 for (int i
= 0; i
< count
; ++i
)
380 virtual ~URLRequestBigJob() {}
382 // big-job:substring,N
383 static bool ParseURL(const GURL
& url
, std::string
* text
, int* count
) {
384 std::vector
<std::string
> parts
;
385 base::SplitString(url
.path(), ',', &parts
);
387 if (parts
.size() != 2)
391 return base::StringToInt(parts
[1], count
);
395 // Associated with an URLRequest to determine if the URLRequest gets deleted.
396 class TestUserData
: public base::SupportsUserData::Data
{
398 explicit TestUserData(bool* was_deleted
)
399 : was_deleted_(was_deleted
) {
402 virtual ~TestUserData() {
403 *was_deleted_
= true;
410 class TransfersAllNavigationsContentBrowserClient
411 : public TestContentBrowserClient
{
413 virtual bool ShouldSwapProcessesForRedirect(ResourceContext
* resource_context
,
414 const GURL
& current_url
,
415 const GURL
& new_url
) OVERRIDE
{
420 enum GenericResourceThrottleFlags
{
422 DEFER_STARTING_REQUEST
= 1 << 0,
423 DEFER_PROCESSING_RESPONSE
= 1 << 1,
424 CANCEL_BEFORE_START
= 1 << 2,
425 DEFER_NETWORK_START
= 1 << 3
428 // Throttle that tracks the current throttle blocking a request. Only one
429 // can throttle any request at a time.
430 class GenericResourceThrottle
: public ResourceThrottle
{
432 // The value is used to indicate that the throttle should not provide
433 // a error code when cancelling a request. net::OK is used, because this
434 // is not an error code.
435 static const int USE_DEFAULT_CANCEL_ERROR_CODE
= net::OK
;
437 GenericResourceThrottle(int flags
, int code
)
439 error_code_for_cancellation_(code
) {
442 virtual ~GenericResourceThrottle() {
443 if (active_throttle_
== this)
444 active_throttle_
= NULL
;
447 // ResourceThrottle implementation:
448 virtual void WillStartRequest(bool* defer
) OVERRIDE
{
449 ASSERT_EQ(NULL
, active_throttle_
);
450 if (flags_
& DEFER_STARTING_REQUEST
) {
451 active_throttle_
= this;
455 if (flags_
& CANCEL_BEFORE_START
) {
456 if (error_code_for_cancellation_
== USE_DEFAULT_CANCEL_ERROR_CODE
) {
457 controller()->Cancel();
459 controller()->CancelWithError(error_code_for_cancellation_
);
464 virtual void WillProcessResponse(bool* defer
) OVERRIDE
{
465 ASSERT_EQ(NULL
, active_throttle_
);
466 if (flags_
& DEFER_PROCESSING_RESPONSE
) {
467 active_throttle_
= this;
472 virtual void OnBeforeNetworkStart(bool* defer
) OVERRIDE
{
473 ASSERT_EQ(NULL
, active_throttle_
);
475 if (flags_
& DEFER_NETWORK_START
) {
476 active_throttle_
= this;
481 virtual const char* GetNameForLogging() const OVERRIDE
{
482 return "GenericResourceThrottle";
486 ASSERT_TRUE(this == active_throttle_
);
487 active_throttle_
= NULL
;
488 controller()->Resume();
491 static GenericResourceThrottle
* active_throttle() {
492 return active_throttle_
;
496 int flags_
; // bit-wise union of GenericResourceThrottleFlags.
497 int error_code_for_cancellation_
;
499 // The currently active throttle, if any.
500 static GenericResourceThrottle
* active_throttle_
;
503 GenericResourceThrottle
* GenericResourceThrottle::active_throttle_
= NULL
;
505 class TestResourceDispatcherHostDelegate
506 : public ResourceDispatcherHostDelegate
{
508 TestResourceDispatcherHostDelegate()
509 : create_two_throttles_(false),
511 error_code_for_cancellation_(
512 GenericResourceThrottle::USE_DEFAULT_CANCEL_ERROR_CODE
) {
515 void set_url_request_user_data(base::SupportsUserData::Data
* user_data
) {
516 user_data_
.reset(user_data
);
519 void set_flags(int value
) {
523 void set_error_code_for_cancellation(int code
) {
524 error_code_for_cancellation_
= code
;
527 void set_create_two_throttles(bool create_two_throttles
) {
528 create_two_throttles_
= create_two_throttles
;
531 // ResourceDispatcherHostDelegate implementation:
533 virtual void RequestBeginning(
534 net::URLRequest
* request
,
535 ResourceContext
* resource_context
,
536 appcache::AppCacheService
* appcache_service
,
537 ResourceType::Type resource_type
,
540 ScopedVector
<ResourceThrottle
>* throttles
) OVERRIDE
{
542 const void* key
= user_data_
.get();
543 request
->SetUserData(key
, user_data_
.release());
546 if (flags_
!= NONE
) {
547 throttles
->push_back(new GenericResourceThrottle(
548 flags_
, error_code_for_cancellation_
));
549 if (create_two_throttles_
)
550 throttles
->push_back(new GenericResourceThrottle(
551 flags_
, error_code_for_cancellation_
));
556 bool create_two_throttles_
;
558 int error_code_for_cancellation_
;
559 scoped_ptr
<base::SupportsUserData::Data
> user_data_
;
562 class ResourceDispatcherHostTest
: public testing::Test
,
565 ResourceDispatcherHostTest()
566 : ui_thread_(BrowserThread::UI
, &message_loop_
),
567 file_thread_(BrowserThread::FILE_USER_BLOCKING
, &message_loop_
),
568 cache_thread_(BrowserThread::CACHE
, &message_loop_
),
569 io_thread_(BrowserThread::IO
, &message_loop_
),
571 send_data_received_acks_(false) {
572 browser_context_
.reset(new TestBrowserContext());
573 BrowserContext::EnsureResourceContextInitialized(browser_context_
.get());
574 message_loop_
.RunUntilIdle();
575 ResourceContext
* resource_context
= browser_context_
->GetResourceContext();
576 filter_
= new ForwardingFilter(this, resource_context
);
577 resource_context
->GetRequestContext()->set_network_delegate(
581 virtual ~ResourceDispatcherHostTest() {
582 for (std::set
<int>::iterator it
= child_ids_
.begin();
583 it
!= child_ids_
.end(); ++it
) {
584 host_
.CancelRequestsForProcess(*it
);
588 // IPC::Sender implementation
589 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
590 accum_
.AddMessage(*msg
);
592 if (send_data_received_acks_
&&
593 msg
->type() == ResourceMsg_DataReceived::ID
) {
594 GenerateDataReceivedACK(*msg
);
603 virtual void SetUp() {
604 DCHECK(!test_fixture_
);
605 test_fixture_
= this;
606 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0);
607 net::URLRequest::Deprecated::RegisterProtocolFactory(
609 &ResourceDispatcherHostTest::Factory
);
610 EnsureTestSchemeIsAllowed();
611 delay_start_
= false;
612 delay_complete_
= false;
613 network_start_notification_
= false;
614 url_request_jobs_created_count_
= 0;
617 virtual void TearDown() {
618 net::URLRequest::Deprecated::RegisterProtocolFactory("test", NULL
);
619 if (!scheme_
.empty())
620 net::URLRequest::Deprecated::RegisterProtocolFactory(
621 scheme_
, old_factory_
);
623 EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty());
624 URLRequestTestDelayedStartJob::ClearQueue();
626 DCHECK(test_fixture_
== this);
627 test_fixture_
= NULL
;
631 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(0);
633 // Flush the message loop to make application verifiers happy.
634 if (ResourceDispatcherHostImpl::Get())
635 ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(
636 browser_context_
->GetResourceContext());
638 WorkerServiceImpl::GetInstance()->PerformTeardownForTesting();
640 browser_context_
.reset();
641 message_loop_
.RunUntilIdle();
644 // Creates a request using the current test object as the filter and
645 // SubResource as the resource type.
646 void MakeTestRequest(int render_view_id
,
650 // Generates a request using the given filter and resource type.
651 void MakeTestRequestWithResourceType(ResourceMessageFilter
* filter
,
652 int render_view_id
, int request_id
,
654 ResourceType::Type type
);
656 void CancelRequest(int request_id
);
658 void CompleteStartRequest(int request_id
);
659 void CompleteStartRequest(ResourceMessageFilter
* filter
, int request_id
);
661 net::TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
663 void EnsureSchemeIsAllowed(const std::string
& scheme
) {
664 ChildProcessSecurityPolicyImpl
* policy
=
665 ChildProcessSecurityPolicyImpl::GetInstance();
666 if (!policy
->IsWebSafeScheme(scheme
))
667 policy
->RegisterWebSafeScheme(scheme
);
670 void EnsureTestSchemeIsAllowed() {
671 EnsureSchemeIsAllowed("test");
674 // Sets a particular response for any request from now on. To switch back to
675 // the default bahavior, pass an empty |headers|. |headers| should be raw-
676 // formatted (NULLs instead of EOLs).
677 void SetResponse(const std::string
& headers
, const std::string
& data
) {
678 response_headers_
= net::HttpUtil::AssembleRawHeaders(headers
.data(),
680 response_data_
= data
;
682 void SetResponse(const std::string
& headers
) {
683 SetResponse(headers
, std::string());
686 void SendDataReceivedACKs(bool send_acks
) {
687 send_data_received_acks_
= send_acks
;
690 // Intercepts requests for the given protocol.
691 void HandleScheme(const std::string
& scheme
) {
692 DCHECK(scheme_
.empty());
693 DCHECK(!old_factory_
);
695 old_factory_
= net::URLRequest::Deprecated::RegisterProtocolFactory(
696 scheme_
, &ResourceDispatcherHostTest::Factory
);
697 EnsureSchemeIsAllowed(scheme
);
700 // Our own net::URLRequestJob factory.
701 static net::URLRequestJob
* Factory(net::URLRequest
* request
,
702 net::NetworkDelegate
* network_delegate
,
703 const std::string
& scheme
) {
704 url_request_jobs_created_count_
++;
705 if (test_fixture_
->response_headers_
.empty()) {
707 return new URLRequestTestDelayedStartJob(request
, network_delegate
);
708 } else if (delay_complete_
) {
709 return new URLRequestTestDelayedCompletionJob(request
,
711 } else if (network_start_notification_
) {
712 return new URLRequestTestDelayedNetworkJob(request
, network_delegate
);
713 } else if (scheme
== "big-job") {
714 return new URLRequestBigJob(request
, network_delegate
);
716 return new net::URLRequestTestJob(request
, network_delegate
);
720 return new URLRequestTestDelayedStartJob(
721 request
, network_delegate
,
722 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
724 } else if (delay_complete_
) {
725 return new URLRequestTestDelayedCompletionJob(
726 request
, network_delegate
,
727 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
730 return new net::URLRequestTestJob(
731 request
, network_delegate
,
732 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
738 void SetDelayedStartJobGeneration(bool delay_job_start
) {
739 delay_start_
= delay_job_start
;
742 void SetDelayedCompleteJobGeneration(bool delay_job_complete
) {
743 delay_complete_
= delay_job_complete
;
746 void SetNetworkStartNotificationJobGeneration(bool notification
) {
747 network_start_notification_
= notification
;
750 void GenerateDataReceivedACK(const IPC::Message
& msg
) {
751 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msg
.type());
754 bool result
= PickleIterator(msg
).ReadInt(&request_id
);
756 scoped_ptr
<IPC::Message
> ack(
757 new ResourceHostMsg_DataReceived_ACK(request_id
));
759 base::MessageLoop::current()->PostTask(
761 base::Bind(&GenerateIPCMessage
, filter_
, base::Passed(&ack
)));
764 base::MessageLoopForIO message_loop_
;
765 BrowserThreadImpl ui_thread_
;
766 BrowserThreadImpl file_thread_
;
767 BrowserThreadImpl cache_thread_
;
768 BrowserThreadImpl io_thread_
;
769 scoped_ptr
<TestBrowserContext
> browser_context_
;
770 scoped_refptr
<ForwardingFilter
> filter_
;
771 net::TestNetworkDelegate network_delegate_
;
772 ResourceDispatcherHostImpl host_
;
773 ResourceIPCAccumulator accum_
;
774 std::string response_headers_
;
775 std::string response_data_
;
777 net::URLRequest::ProtocolFactory
* old_factory_
;
778 bool send_data_received_acks_
;
779 std::set
<int> child_ids_
;
780 static ResourceDispatcherHostTest
* test_fixture_
;
781 static bool delay_start_
;
782 static bool delay_complete_
;
783 static bool network_start_notification_
;
784 static int url_request_jobs_created_count_
;
787 ResourceDispatcherHostTest
* ResourceDispatcherHostTest::test_fixture_
= NULL
;
788 bool ResourceDispatcherHostTest::delay_start_
= false;
789 bool ResourceDispatcherHostTest::delay_complete_
= false;
790 bool ResourceDispatcherHostTest::network_start_notification_
= false;
791 int ResourceDispatcherHostTest::url_request_jobs_created_count_
= 0;
793 void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id
,
796 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
797 url
, ResourceType::SUB_RESOURCE
);
800 void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
801 ResourceMessageFilter
* filter
,
805 ResourceType::Type type
) {
806 // If it's already there, this'll be dropped on the floor, which is fine.
807 child_ids_
.insert(filter
->child_id());
809 ResourceHostMsg_Request request
=
810 CreateResourceRequest("GET", type
, url
);
811 ResourceHostMsg_RequestResource
msg(render_view_id
, request_id
, request
);
813 host_
.OnMessageReceived(msg
, filter
, &msg_was_ok
);
817 void ResourceDispatcherHostTest::CancelRequest(int request_id
) {
818 host_
.CancelRequest(filter_
->child_id(), request_id
, false);
821 void ResourceDispatcherHostTest::CompleteStartRequest(int request_id
) {
822 CompleteStartRequest(filter_
.get(), request_id
);
825 void ResourceDispatcherHostTest::CompleteStartRequest(
826 ResourceMessageFilter
* filter
,
828 GlobalRequestID
gid(filter
->child_id(), request_id
);
829 net::URLRequest
* req
= host_
.GetURLRequest(gid
);
832 URLRequestTestDelayedStartJob::CompleteStart(req
);
835 void CheckRequestCompleteErrorCode(const IPC::Message
& message
,
836 int expected_error_code
) {
837 // Verify the expected error code was received.
841 ASSERT_EQ(ResourceMsg_RequestComplete::ID
, message
.type());
843 PickleIterator
iter(message
);
844 ASSERT_TRUE(IPC::ReadParam(&message
, &iter
, &request_id
));
845 ASSERT_TRUE(IPC::ReadParam(&message
, &iter
, &error_code
));
846 ASSERT_EQ(expected_error_code
, error_code
);
849 testing::AssertionResult
ExtractDataOffsetAndLength(const IPC::Message
& message
,
852 PickleIterator
iter(message
);
854 if (!IPC::ReadParam(&message
, &iter
, &request_id
))
855 return testing::AssertionFailure() << "Could not read request_id";
856 if (!IPC::ReadParam(&message
, &iter
, data_offset
))
857 return testing::AssertionFailure() << "Could not read data_offset";
858 if (!IPC::ReadParam(&message
, &iter
, data_length
))
859 return testing::AssertionFailure() << "Could not read data_length";
860 return testing::AssertionSuccess();
863 void CheckSuccessfulRequestWithErrorCode(
864 const std::vector
<IPC::Message
>& messages
,
865 const std::string
& reference_data
,
866 int expected_error
) {
867 // A successful request will have received 4 messages:
868 // ReceivedResponse (indicates headers received)
869 // SetDataBuffer (contains shared memory handle)
870 // DataReceived (data offset and length into shared memory)
871 // RequestComplete (request is done)
873 // This function verifies that we received 4 messages and that they are
874 // appropriate. It allows for an error code other than net::OK if the request
875 // should successfully receive data and then abort, e.g., on cancel.
876 ASSERT_EQ(4U, messages
.size());
878 // The first messages should be received response
879 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
881 ASSERT_EQ(ResourceMsg_SetDataBuffer::ID
, messages
[1].type());
883 PickleIterator
iter(messages
[1]);
885 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &request_id
));
886 base::SharedMemoryHandle shm_handle
;
887 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &shm_handle
));
889 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &shm_size
));
891 // Followed by the data, currently we only do the data in one chunk, but
892 // should probably test multiple chunks later
893 ASSERT_EQ(ResourceMsg_DataReceived::ID
, messages
[2].type());
898 ExtractDataOffsetAndLength(messages
[2], &data_offset
, &data_length
));
900 ASSERT_EQ(reference_data
.size(), static_cast<size_t>(data_length
));
901 ASSERT_GE(shm_size
, data_length
);
903 base::SharedMemory
shared_mem(shm_handle
, true); // read only
904 shared_mem
.Map(data_length
);
905 const char* data
= static_cast<char*>(shared_mem
.memory()) + data_offset
;
906 ASSERT_EQ(0, memcmp(reference_data
.c_str(), data
, data_length
));
908 // The last message should be all data received.
909 CheckRequestCompleteErrorCode(messages
[3], expected_error
);
912 void CheckSuccessfulRequest(const std::vector
<IPC::Message
>& messages
,
913 const std::string
& reference_data
) {
914 CheckSuccessfulRequestWithErrorCode(messages
, reference_data
, net::OK
);
917 void CheckSuccessfulRedirect(const std::vector
<IPC::Message
>& messages
,
918 const std::string
& reference_data
) {
919 ASSERT_EQ(5U, messages
.size());
920 ASSERT_EQ(ResourceMsg_ReceivedRedirect::ID
, messages
[0].type());
922 const std::vector
<IPC::Message
> second_req_msgs
=
923 std::vector
<IPC::Message
>(messages
.begin() + 1, messages
.end());
924 CheckSuccessfulRequest(second_req_msgs
, reference_data
);
927 void CheckFailedRequest(const std::vector
<IPC::Message
>& messages
,
928 const std::string
& reference_data
,
929 int expected_error
) {
930 ASSERT_LT(0U, messages
.size());
931 ASSERT_GE(2U, messages
.size());
932 size_t failure_index
= messages
.size() - 1;
934 if (messages
.size() == 2) {
935 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
938 CheckRequestCompleteErrorCode(messages
[failure_index
], expected_error
);
941 // Tests whether many messages get dispatched properly.
942 TEST_F(ResourceDispatcherHostTest
, TestMany
) {
943 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
944 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
945 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
946 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
947 net::URLRequestTestJob::test_url_4(),
948 ResourceType::PREFETCH
); // detachable type
949 MakeTestRequest(0, 5, net::URLRequestTestJob::test_url_redirect_to_url_2());
951 // Finish the redirection
952 ResourceHostMsg_FollowRedirect
redirect_msg(5, false, GURL());
954 host_
.OnMessageReceived(redirect_msg
, filter_
.get(), &msg_was_ok
);
955 base::MessageLoop::current()->RunUntilIdle();
957 // flush all the pending requests
958 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
960 // sorts out all the messages we saw by request
961 ResourceIPCAccumulator::ClassifiedMessages msgs
;
962 accum_
.GetClassifiedMessages(&msgs
);
964 // there are five requests, so we should have gotten them classified as such
965 ASSERT_EQ(5U, msgs
.size());
967 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
968 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_2());
969 CheckSuccessfulRequest(msgs
[2], net::URLRequestTestJob::test_data_3());
970 CheckSuccessfulRequest(msgs
[3], net::URLRequestTestJob::test_data_4());
971 CheckSuccessfulRedirect(msgs
[4], net::URLRequestTestJob::test_data_2());
974 // Tests whether messages get canceled properly. We issue four requests,
975 // cancel two of them, and make sure that each sent the proper notifications.
976 TEST_F(ResourceDispatcherHostTest
, Cancel
) {
977 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
978 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
979 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
981 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
982 net::URLRequestTestJob::test_url_4(),
983 ResourceType::PREFETCH
); // detachable type
987 // Cancel request must come from the renderer for a detachable resource to
989 host_
.CancelRequest(filter_
->child_id(), 4, true);
991 // The handler should have been detached now.
992 GlobalRequestID
global_request_id(filter_
->child_id(), 4);
993 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
994 host_
.GetURLRequest(global_request_id
));
995 ASSERT_TRUE(info
->detachable_handler()->is_detached());
997 // flush all the pending requests
998 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
999 base::MessageLoop::current()->RunUntilIdle();
1001 // Everything should be out now.
1002 EXPECT_EQ(0, host_
.pending_requests());
1004 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1005 accum_
.GetClassifiedMessages(&msgs
);
1007 // there are four requests, so we should have gotten them classified as such
1008 ASSERT_EQ(4U, msgs
.size());
1010 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1011 CheckSuccessfulRequest(msgs
[2], net::URLRequestTestJob::test_data_3());
1013 // Check that request 2 and 4 got canceled, as far as the renderer is
1015 ASSERT_EQ(2U, msgs
[1].size());
1016 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[1][0].type());
1017 CheckRequestCompleteErrorCode(msgs
[1][1], net::ERR_ABORTED
);
1019 ASSERT_EQ(2U, msgs
[3].size());
1020 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[3][0].type());
1021 CheckRequestCompleteErrorCode(msgs
[1][1], net::ERR_ABORTED
);
1023 // However, request 4 should have actually gone to completion. (Only request 2
1025 EXPECT_EQ(4, network_delegate()->completed_requests());
1026 EXPECT_EQ(1, network_delegate()->canceled_requests());
1027 EXPECT_EQ(0, network_delegate()->error_count());
1030 // Shows that detachable requests will timeout if the request takes too long to
1032 TEST_F(ResourceDispatcherHostTest
, DetachedResourceTimesOut
) {
1033 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1034 net::URLRequestTestJob::test_url_2(),
1035 ResourceType::PREFETCH
); // detachable type
1036 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1037 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1038 host_
.GetURLRequest(global_request_id
));
1039 ASSERT_TRUE(info
->detachable_handler());
1040 info
->detachable_handler()->set_cancel_delay(
1041 base::TimeDelta::FromMilliseconds(200));
1042 base::MessageLoop::current()->RunUntilIdle();
1043 host_
.CancelRequest(filter_
->child_id(), 1, true);
1045 // From the renderer's perspective, the request was cancelled.
1046 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1047 accum_
.GetClassifiedMessages(&msgs
);
1048 ASSERT_EQ(1U, msgs
.size());
1049 ASSERT_EQ(2U, msgs
[0].size());
1050 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
1051 CheckRequestCompleteErrorCode(msgs
[0][1], net::ERR_ABORTED
);
1053 // But it continues detached.
1054 EXPECT_EQ(1, host_
.pending_requests());
1055 EXPECT_TRUE(info
->detachable_handler()->is_detached());
1057 // Wait until after the delay timer times out before we start processing any
1059 base::OneShotTimer
<base::MessageLoop
> timer
;
1060 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(210),
1061 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle
);
1062 base::MessageLoop::current()->Run();
1064 // The prefetch should be cancelled by now.
1065 EXPECT_EQ(0, host_
.pending_requests());
1066 EXPECT_EQ(1, network_delegate()->completed_requests());
1067 EXPECT_EQ(1, network_delegate()->canceled_requests());
1068 EXPECT_EQ(0, network_delegate()->error_count());
1071 // If the filter has disappeared then detachable resources should continue to
1073 TEST_F(ResourceDispatcherHostTest
, DeletedFilterDetached
) {
1074 // test_url_1's data is available synchronously, so use 2 and 3.
1075 ResourceHostMsg_Request request_prefetch
= CreateResourceRequest(
1076 "GET", ResourceType::PREFETCH
, net::URLRequestTestJob::test_url_2());
1077 ResourceHostMsg_Request request_ping
= CreateResourceRequest(
1078 "GET", ResourceType::PING
, net::URLRequestTestJob::test_url_3());
1081 ResourceHostMsg_RequestResource
msg_prefetch(0, 1, request_prefetch
);
1082 host_
.OnMessageReceived(msg_prefetch
, filter_
, &msg_was_ok
);
1083 ResourceHostMsg_RequestResource
msg_ping(0, 2, request_ping
);
1084 host_
.OnMessageReceived(msg_ping
, filter_
, &msg_was_ok
);
1086 // Remove the filter before processing the requests by simulating channel
1088 ResourceRequestInfoImpl
* info_prefetch
= ResourceRequestInfoImpl::ForRequest(
1089 host_
.GetURLRequest(GlobalRequestID(filter_
->child_id(), 1)));
1090 ResourceRequestInfoImpl
* info_ping
= ResourceRequestInfoImpl::ForRequest(
1091 host_
.GetURLRequest(GlobalRequestID(filter_
->child_id(), 2)));
1092 DCHECK_EQ(filter_
.get(), info_prefetch
->filter());
1093 DCHECK_EQ(filter_
.get(), info_ping
->filter());
1094 filter_
->OnChannelClosing();
1095 info_prefetch
->filter_
.reset();
1096 info_ping
->filter_
.reset();
1098 // From the renderer's perspective, the requests were cancelled.
1099 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1100 accum_
.GetClassifiedMessages(&msgs
);
1101 ASSERT_EQ(2U, msgs
.size());
1102 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1103 CheckRequestCompleteErrorCode(msgs
[1][0], net::ERR_ABORTED
);
1105 // But it continues detached.
1106 EXPECT_EQ(2, host_
.pending_requests());
1107 EXPECT_TRUE(info_prefetch
->detachable_handler()->is_detached());
1108 EXPECT_TRUE(info_ping
->detachable_handler()->is_detached());
1112 // Make sure the requests weren't canceled early.
1113 EXPECT_EQ(2, host_
.pending_requests());
1115 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1116 base::MessageLoop::current()->RunUntilIdle();
1118 EXPECT_EQ(0, host_
.pending_requests());
1119 EXPECT_EQ(2, network_delegate()->completed_requests());
1120 EXPECT_EQ(0, network_delegate()->canceled_requests());
1121 EXPECT_EQ(0, network_delegate()->error_count());
1124 // If the filter has disappeared (original process dies) then detachable
1125 // resources should continue to load, even when redirected.
1126 TEST_F(ResourceDispatcherHostTest
, DeletedFilterDetachedRedirect
) {
1127 ResourceHostMsg_Request request
= CreateResourceRequest(
1128 "GET", ResourceType::PREFETCH
,
1129 net::URLRequestTestJob::test_url_redirect_to_url_2());
1131 ResourceHostMsg_RequestResource
msg(0, 1, request
);
1133 host_
.OnMessageReceived(msg
, filter_
, &msg_was_ok
);
1135 // Remove the filter before processing the request by simulating channel
1137 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1138 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1139 host_
.GetURLRequest(global_request_id
));
1140 info
->filter_
->OnChannelClosing();
1141 info
->filter_
.reset();
1143 // From the renderer's perspective, the request was cancelled.
1144 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1145 accum_
.GetClassifiedMessages(&msgs
);
1146 ASSERT_EQ(1U, msgs
.size());
1147 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1149 // But it continues detached.
1150 EXPECT_EQ(1, host_
.pending_requests());
1151 EXPECT_TRUE(info
->detachable_handler()->is_detached());
1153 // Verify no redirects before resetting the filter.
1154 net::URLRequest
* url_request
= host_
.GetURLRequest(global_request_id
);
1155 EXPECT_EQ(1u, url_request
->url_chain().size());
1158 // Verify that a redirect was followed.
1159 EXPECT_EQ(2u, url_request
->url_chain().size());
1161 // Make sure the request wasn't canceled early.
1162 EXPECT_EQ(1, host_
.pending_requests());
1164 // Finish up the request.
1165 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1166 base::MessageLoop::current()->RunUntilIdle();
1168 EXPECT_EQ(0, host_
.pending_requests());
1169 EXPECT_EQ(1, network_delegate()->completed_requests());
1170 EXPECT_EQ(0, network_delegate()->canceled_requests());
1171 EXPECT_EQ(0, network_delegate()->error_count());
1174 TEST_F(ResourceDispatcherHostTest
, CancelWhileStartIsDeferred
) {
1175 bool was_deleted
= false;
1177 // Arrange to have requests deferred before starting.
1178 TestResourceDispatcherHostDelegate delegate
;
1179 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1180 delegate
.set_url_request_user_data(new TestUserData(&was_deleted
));
1181 host_
.SetDelegate(&delegate
);
1183 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1186 // Our TestResourceThrottle should not have been deleted yet. This is to
1187 // ensure that destruction of the URLRequest happens asynchronously to
1188 // calling CancelRequest.
1189 EXPECT_FALSE(was_deleted
);
1191 base::MessageLoop::current()->RunUntilIdle();
1193 EXPECT_TRUE(was_deleted
);
1196 TEST_F(ResourceDispatcherHostTest
, DetachWhileStartIsDeferred
) {
1197 bool was_deleted
= false;
1199 // Arrange to have requests deferred before starting.
1200 TestResourceDispatcherHostDelegate delegate
;
1201 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1202 delegate
.set_url_request_user_data(new TestUserData(&was_deleted
));
1203 host_
.SetDelegate(&delegate
);
1205 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1206 net::URLRequestTestJob::test_url_1(),
1207 ResourceType::PREFETCH
); // detachable type
1208 // Cancel request must come from the renderer for a detachable resource to
1210 host_
.CancelRequest(filter_
->child_id(), 1, true);
1212 // Even after driving the event loop, the request has not been deleted.
1213 EXPECT_FALSE(was_deleted
);
1215 // However, it is still throttled because the defer happened above the
1216 // DetachableResourceHandler.
1217 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1218 base::MessageLoop::current()->RunUntilIdle();
1219 EXPECT_FALSE(was_deleted
);
1221 // Resume the request.
1222 GenericResourceThrottle
* throttle
=
1223 GenericResourceThrottle::active_throttle();
1224 ASSERT_TRUE(throttle
);
1227 // Now, the request completes.
1228 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1229 base::MessageLoop::current()->RunUntilIdle();
1230 EXPECT_TRUE(was_deleted
);
1231 EXPECT_EQ(1, network_delegate()->completed_requests());
1232 EXPECT_EQ(0, network_delegate()->canceled_requests());
1233 EXPECT_EQ(0, network_delegate()->error_count());
1236 // Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
1237 // URLRequest will not be started.
1238 TEST_F(ResourceDispatcherHostTest
, CancelInResourceThrottleWillStartRequest
) {
1239 TestResourceDispatcherHostDelegate delegate
;
1240 delegate
.set_flags(CANCEL_BEFORE_START
);
1241 host_
.SetDelegate(&delegate
);
1243 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1245 // flush all the pending requests
1246 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1247 base::MessageLoop::current()->RunUntilIdle();
1249 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1250 accum_
.GetClassifiedMessages(&msgs
);
1252 // Check that request got canceled.
1253 ASSERT_EQ(1U, msgs
[0].size());
1254 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1256 // Make sure URLRequest is never started.
1257 EXPECT_EQ(0, url_request_jobs_created_count_
);
1260 TEST_F(ResourceDispatcherHostTest
, PausedStartError
) {
1261 // Arrange to have requests deferred before processing response headers.
1262 TestResourceDispatcherHostDelegate delegate
;
1263 delegate
.set_flags(DEFER_PROCESSING_RESPONSE
);
1264 host_
.SetDelegate(&delegate
);
1266 SetDelayedStartJobGeneration(true);
1267 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_error());
1268 CompleteStartRequest(1);
1270 // flush all the pending requests
1271 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1272 base::MessageLoop::current()->RunUntilIdle();
1274 EXPECT_EQ(0, host_
.pending_requests());
1277 // Test the OnBeforeNetworkStart throttle.
1278 TEST_F(ResourceDispatcherHostTest
, ThrottleNetworkStart
) {
1279 // Arrange to have requests deferred before processing response headers.
1280 TestResourceDispatcherHostDelegate delegate
;
1281 delegate
.set_flags(DEFER_NETWORK_START
);
1282 host_
.SetDelegate(&delegate
);
1284 SetNetworkStartNotificationJobGeneration(true);
1285 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_2());
1287 // Should have deferred for network start.
1288 GenericResourceThrottle
* first_throttle
=
1289 GenericResourceThrottle::active_throttle();
1290 ASSERT_TRUE(first_throttle
);
1291 EXPECT_EQ(0, network_delegate()->completed_requests());
1292 EXPECT_EQ(1, host_
.pending_requests());
1294 first_throttle
->Resume();
1296 // Flush all the pending requests.
1297 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1298 base::MessageLoop::current()->RunUntilIdle();
1300 EXPECT_EQ(1, network_delegate()->completed_requests());
1301 EXPECT_EQ(0, host_
.pending_requests());
1304 TEST_F(ResourceDispatcherHostTest
, ThrottleAndResumeTwice
) {
1305 // Arrange to have requests deferred before starting.
1306 TestResourceDispatcherHostDelegate delegate
;
1307 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1308 delegate
.set_create_two_throttles(true);
1309 host_
.SetDelegate(&delegate
);
1311 // Make sure the first throttle blocked the request, and then resume.
1312 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1313 GenericResourceThrottle
* first_throttle
=
1314 GenericResourceThrottle::active_throttle();
1315 ASSERT_TRUE(first_throttle
);
1316 first_throttle
->Resume();
1318 // Make sure the second throttle blocked the request, and then resume.
1319 ASSERT_TRUE(GenericResourceThrottle::active_throttle());
1320 ASSERT_NE(first_throttle
, GenericResourceThrottle::active_throttle());
1321 GenericResourceThrottle::active_throttle()->Resume();
1323 ASSERT_FALSE(GenericResourceThrottle::active_throttle());
1325 // The request is started asynchronously.
1326 base::MessageLoop::current()->RunUntilIdle();
1328 // Flush all the pending requests.
1329 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1331 EXPECT_EQ(0, host_
.pending_requests());
1333 // Make sure the request completed successfully.
1334 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1335 accum_
.GetClassifiedMessages(&msgs
);
1336 ASSERT_EQ(1U, msgs
.size());
1337 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1341 // Tests that the delegate can cancel a request and provide a error code.
1342 TEST_F(ResourceDispatcherHostTest
, CancelInDelegate
) {
1343 TestResourceDispatcherHostDelegate delegate
;
1344 delegate
.set_flags(CANCEL_BEFORE_START
);
1345 delegate
.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED
);
1346 host_
.SetDelegate(&delegate
);
1348 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1349 // The request will get cancelled by the throttle.
1351 // flush all the pending requests
1352 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1353 base::MessageLoop::current()->RunUntilIdle();
1355 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1356 accum_
.GetClassifiedMessages(&msgs
);
1358 // Check the cancellation
1359 ASSERT_EQ(1U, msgs
.size());
1360 ASSERT_EQ(1U, msgs
[0].size());
1362 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ACCESS_DENIED
);
1365 // The host delegate acts as a second one so we can have some requests
1366 // pending and some canceled.
1367 class TestFilter
: public ForwardingFilter
{
1369 explicit TestFilter(ResourceContext
* resource_context
)
1370 : ForwardingFilter(NULL
, resource_context
),
1371 has_canceled_(false),
1372 received_after_canceled_(0) {
1375 // ForwardingFilter override
1376 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
1377 // no messages should be received when the process has been canceled
1379 received_after_canceled_
++;
1385 int received_after_canceled_
;
1388 virtual ~TestFilter() {}
1391 // Tests CancelRequestsForProcess
1392 TEST_F(ResourceDispatcherHostTest
, TestProcessCancel
) {
1393 scoped_refptr
<TestFilter
> test_filter
= new TestFilter(
1394 browser_context_
->GetResourceContext());
1396 // request 1 goes to the test delegate
1397 ResourceHostMsg_Request request
= CreateResourceRequest(
1398 "GET", ResourceType::SUB_RESOURCE
, net::URLRequestTestJob::test_url_1());
1400 MakeTestRequestWithResourceType(test_filter
.get(), 0, 1,
1401 net::URLRequestTestJob::test_url_1(),
1402 ResourceType::SUB_RESOURCE
);
1404 // request 2 goes to us
1405 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1407 // request 3 goes to the test delegate
1408 MakeTestRequestWithResourceType(test_filter
.get(), 0, 3,
1409 net::URLRequestTestJob::test_url_3(),
1410 ResourceType::SUB_RESOURCE
);
1412 // request 4 goes to us
1413 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
1414 net::URLRequestTestJob::test_url_4(),
1415 ResourceType::PREFETCH
); // detachable type
1418 // Make sure all requests have finished stage one. test_url_1 will have
1420 base::MessageLoop::current()->RunUntilIdle();
1423 // Now that the async IO path is in place, the IO always completes on the
1424 // initial call; so the requests have already completed. This basically
1425 // breaks the whole test.
1426 //EXPECT_EQ(3, host_.pending_requests());
1428 // Process test_url_2 and test_url_3 for one level so one callback is called.
1429 // We'll cancel test_url_4 (detachable) before processing it to verify that it
1430 // delays the cancel.
1431 for (int i
= 0; i
< 2; i
++)
1432 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
1434 // Cancel the requests to the test process.
1435 host_
.CancelRequestsForProcess(filter_
->child_id());
1436 test_filter
->has_canceled_
= true;
1438 // The requests should all be cancelled, except request 4, which is detached.
1439 EXPECT_EQ(1, host_
.pending_requests());
1440 GlobalRequestID
global_request_id(filter_
->child_id(), 4);
1441 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1442 host_
.GetURLRequest(global_request_id
));
1443 ASSERT_TRUE(info
->detachable_handler()->is_detached());
1445 // Flush all the pending requests.
1446 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1448 EXPECT_EQ(0, host_
.pending_requests());
1450 // The test delegate should not have gotten any messages after being canceled.
1451 ASSERT_EQ(0, test_filter
->received_after_canceled_
);
1453 // There should be two results.
1454 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1455 accum_
.GetClassifiedMessages(&msgs
);
1456 ASSERT_EQ(2U, msgs
.size());
1457 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1458 // The detachable request was cancelled by the renderer before it
1459 // finished. From the perspective of the renderer, it should have cancelled.
1460 ASSERT_EQ(2U, msgs
[1].size());
1461 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[1][0].type());
1462 CheckRequestCompleteErrorCode(msgs
[1][1], net::ERR_ABORTED
);
1463 // But it completed anyway. For the network stack, no requests were canceled.
1464 EXPECT_EQ(4, network_delegate()->completed_requests());
1465 EXPECT_EQ(0, network_delegate()->canceled_requests());
1466 EXPECT_EQ(0, network_delegate()->error_count());
1469 TEST_F(ResourceDispatcherHostTest
, TestProcessCancelDetachedTimesOut
) {
1470 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1471 net::URLRequestTestJob::test_url_4(),
1472 ResourceType::PREFETCH
); // detachable type
1473 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1474 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1475 host_
.GetURLRequest(global_request_id
));
1476 ASSERT_TRUE(info
->detachable_handler());
1477 info
->detachable_handler()->set_cancel_delay(
1478 base::TimeDelta::FromMilliseconds(200));
1479 base::MessageLoop::current()->RunUntilIdle();
1481 // Cancel the requests to the test process.
1482 host_
.CancelRequestsForProcess(filter_
->child_id());
1483 EXPECT_EQ(1, host_
.pending_requests());
1485 // Wait until after the delay timer times out before we start processing any
1487 base::OneShotTimer
<base::MessageLoop
> timer
;
1488 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(210),
1489 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle
);
1490 base::MessageLoop::current()->Run();
1492 // The prefetch should be cancelled by now.
1493 EXPECT_EQ(0, host_
.pending_requests());
1495 // In case any messages are still to be processed.
1496 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1497 base::MessageLoop::current()->RunUntilIdle();
1499 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1500 accum_
.GetClassifiedMessages(&msgs
);
1502 ASSERT_EQ(1U, msgs
.size());
1504 // The request should have cancelled.
1505 ASSERT_EQ(2U, msgs
[0].size());
1506 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
1507 CheckRequestCompleteErrorCode(msgs
[0][1], net::ERR_ABORTED
);
1508 // And not run to completion.
1509 EXPECT_EQ(1, network_delegate()->completed_requests());
1510 EXPECT_EQ(1, network_delegate()->canceled_requests());
1511 EXPECT_EQ(0, network_delegate()->error_count());
1514 // Tests blocking and resuming requests.
1515 TEST_F(ResourceDispatcherHostTest
, TestBlockingResumingRequests
) {
1516 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1517 host_
.BlockRequestsForRoute(filter_
->child_id(), 2);
1518 host_
.BlockRequestsForRoute(filter_
->child_id(), 3);
1520 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1521 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1522 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1523 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1524 MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
1525 MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
1527 // Flush all the pending requests
1528 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1530 // Sort out all the messages we saw by request
1531 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1532 accum_
.GetClassifiedMessages(&msgs
);
1534 // All requests but the 2 for the RVH 0 should have been blocked.
1535 ASSERT_EQ(2U, msgs
.size());
1537 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1538 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1540 // Resume requests for RVH 1 and flush pending requests.
1541 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 1);
1543 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1546 accum_
.GetClassifiedMessages(&msgs
);
1547 ASSERT_EQ(2U, msgs
.size());
1548 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1549 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_1());
1551 // Test that new requests are not blocked for RVH 1.
1552 MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
1553 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1555 accum_
.GetClassifiedMessages(&msgs
);
1556 ASSERT_EQ(1U, msgs
.size());
1557 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1559 // Now resumes requests for all RVH (2 and 3).
1560 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 2);
1561 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 3);
1563 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1566 accum_
.GetClassifiedMessages(&msgs
);
1567 ASSERT_EQ(2U, msgs
.size());
1568 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1569 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1572 // Tests blocking and canceling requests.
1573 TEST_F(ResourceDispatcherHostTest
, TestBlockingCancelingRequests
) {
1574 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1576 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1577 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1578 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1579 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1580 // Blocked detachable resources should not delay cancellation.
1581 MakeTestRequestWithResourceType(filter_
.get(), 1, 5,
1582 net::URLRequestTestJob::test_url_4(),
1583 ResourceType::PREFETCH
); // detachable type
1585 // Flush all the pending requests.
1586 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1588 // Sort out all the messages we saw by request.
1589 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1590 accum_
.GetClassifiedMessages(&msgs
);
1592 // The 2 requests for the RVH 0 should have been processed.
1593 ASSERT_EQ(2U, msgs
.size());
1595 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1596 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1598 // Cancel requests for RVH 1.
1599 host_
.CancelBlockedRequestsForRoute(filter_
->child_id(), 1);
1601 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1604 accum_
.GetClassifiedMessages(&msgs
);
1605 ASSERT_EQ(0U, msgs
.size());
1608 // Tests that blocked requests are canceled if their associated process dies.
1609 TEST_F(ResourceDispatcherHostTest
, TestBlockedRequestsProcessDies
) {
1610 // This second filter is used to emulate a second process.
1611 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
1612 this, browser_context_
->GetResourceContext());
1614 host_
.BlockRequestsForRoute(second_filter
->child_id(), 0);
1616 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1617 net::URLRequestTestJob::test_url_1(),
1618 ResourceType::SUB_RESOURCE
);
1619 MakeTestRequestWithResourceType(second_filter
.get(), 0, 2,
1620 net::URLRequestTestJob::test_url_2(),
1621 ResourceType::SUB_RESOURCE
);
1622 MakeTestRequestWithResourceType(filter_
.get(), 0, 3,
1623 net::URLRequestTestJob::test_url_3(),
1624 ResourceType::SUB_RESOURCE
);
1625 MakeTestRequestWithResourceType(second_filter
.get(), 0, 4,
1626 net::URLRequestTestJob::test_url_1(),
1627 ResourceType::SUB_RESOURCE
);
1628 MakeTestRequestWithResourceType(second_filter
.get(), 0, 5,
1629 net::URLRequestTestJob::test_url_4(),
1630 ResourceType::PREFETCH
); // detachable type
1632 // Simulate process death.
1633 host_
.CancelRequestsForProcess(second_filter
->child_id());
1635 // Flush all the pending requests.
1636 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1638 // Sort out all the messages we saw by request.
1639 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1640 accum_
.GetClassifiedMessages(&msgs
);
1642 // The 2 requests for the RVH 0 should have been processed. Note that
1643 // blocked detachable requests are canceled without delay.
1644 ASSERT_EQ(2U, msgs
.size());
1646 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1647 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1649 EXPECT_TRUE(host_
.blocked_loaders_map_
.empty());
1652 // Tests that blocked requests don't leak when the ResourceDispatcherHost goes
1653 // away. Note that we rely on Purify for finding the leaks if any.
1654 // If this test turns the Purify bot red, check the ResourceDispatcherHost
1655 // destructor to make sure the blocked requests are deleted.
1656 TEST_F(ResourceDispatcherHostTest
, TestBlockedRequestsDontLeak
) {
1657 // This second filter is used to emulate a second process.
1658 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
1659 this, browser_context_
->GetResourceContext());
1661 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1662 host_
.BlockRequestsForRoute(filter_
->child_id(), 2);
1663 host_
.BlockRequestsForRoute(second_filter
->child_id(), 1);
1665 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1666 net::URLRequestTestJob::test_url_1(),
1667 ResourceType::SUB_RESOURCE
);
1668 MakeTestRequestWithResourceType(filter_
.get(), 1, 2,
1669 net::URLRequestTestJob::test_url_2(),
1670 ResourceType::SUB_RESOURCE
);
1671 MakeTestRequestWithResourceType(filter_
.get(), 0, 3,
1672 net::URLRequestTestJob::test_url_3(),
1673 ResourceType::SUB_RESOURCE
);
1674 MakeTestRequestWithResourceType(second_filter
.get(), 1, 4,
1675 net::URLRequestTestJob::test_url_1(),
1676 ResourceType::SUB_RESOURCE
);
1677 MakeTestRequestWithResourceType(filter_
.get(), 2, 5,
1678 net::URLRequestTestJob::test_url_2(),
1679 ResourceType::SUB_RESOURCE
);
1680 MakeTestRequestWithResourceType(filter_
.get(), 2, 6,
1681 net::URLRequestTestJob::test_url_3(),
1682 ResourceType::SUB_RESOURCE
);
1683 MakeTestRequestWithResourceType(filter_
.get(), 0, 7,
1684 net::URLRequestTestJob::test_url_4(),
1685 ResourceType::PREFETCH
); // detachable type
1686 MakeTestRequestWithResourceType(second_filter
.get(), 1, 8,
1687 net::URLRequestTestJob::test_url_4(),
1688 ResourceType::PREFETCH
); // detachable type
1690 host_
.CancelRequestsForProcess(filter_
->child_id());
1691 host_
.CancelRequestsForProcess(second_filter
->child_id());
1693 // Flush all the pending requests.
1694 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1697 // Test the private helper method "CalculateApproximateMemoryCost()".
1698 TEST_F(ResourceDispatcherHostTest
, CalculateApproximateMemoryCost
) {
1699 net::URLRequestContext context
;
1700 net::URLRequest
req(
1701 GURL("http://www.google.com"), net::DEFAULT_PRIORITY
, NULL
, &context
);
1703 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req
));
1705 // Add 9 bytes of referrer.
1706 req
.SetReferrer("123456789");
1708 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req
));
1710 // Add 33 bytes of upload content.
1711 std::string upload_content
;
1712 upload_content
.resize(33);
1713 std::fill(upload_content
.begin(), upload_content
.end(), 'x');
1714 scoped_ptr
<net::UploadElementReader
> reader(new net::UploadBytesElementReader(
1715 upload_content
.data(), upload_content
.size()));
1716 req
.set_upload(make_scoped_ptr(
1717 net::UploadDataStream::CreateWithReader(reader
.Pass(), 0)));
1719 // Since the upload throttling is disabled, this has no effect on the cost.
1721 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req
));
1724 // Test that too much memory for outstanding requests for a particular
1725 // render_process_host_id causes requests to fail.
1726 TEST_F(ResourceDispatcherHostTest
, TooMuchOutstandingRequestsMemory
) {
1727 // Expected cost of each request as measured by
1728 // ResourceDispatcherHost::CalculateApproximateMemoryCost().
1729 int kMemoryCostOfTest2Req
=
1730 ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest
+
1731 std::string("GET").size() +
1732 net::URLRequestTestJob::test_url_2().spec().size();
1734 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
1735 int kMaxCostPerProcess
= 440000;
1736 host_
.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess
);
1738 // Determine how many instance of test_url_2() we can request before
1739 // throttling kicks in.
1740 size_t kMaxRequests
= kMaxCostPerProcess
/ kMemoryCostOfTest2Req
;
1742 // This second filter is used to emulate a second process.
1743 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
1744 this, browser_context_
->GetResourceContext());
1746 // Saturate the number of outstanding requests for our process.
1747 for (size_t i
= 0; i
< kMaxRequests
; ++i
) {
1748 MakeTestRequestWithResourceType(filter_
.get(), 0, i
+ 1,
1749 net::URLRequestTestJob::test_url_2(),
1750 ResourceType::SUB_RESOURCE
);
1753 // Issue two more requests for our process -- these should fail immediately.
1754 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequests
+ 1,
1755 net::URLRequestTestJob::test_url_2(),
1756 ResourceType::SUB_RESOURCE
);
1757 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequests
+ 2,
1758 net::URLRequestTestJob::test_url_2(),
1759 ResourceType::SUB_RESOURCE
);
1761 // Issue two requests for the second process -- these should succeed since
1762 // it is just process 0 that is saturated.
1763 MakeTestRequestWithResourceType(second_filter
.get(), 0, kMaxRequests
+ 3,
1764 net::URLRequestTestJob::test_url_2(),
1765 ResourceType::SUB_RESOURCE
);
1766 MakeTestRequestWithResourceType(second_filter
.get(), 0, kMaxRequests
+ 4,
1767 net::URLRequestTestJob::test_url_2(),
1768 ResourceType::SUB_RESOURCE
);
1770 // Flush all the pending requests.
1771 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1772 base::MessageLoop::current()->RunUntilIdle();
1774 // Sorts out all the messages we saw by request.
1775 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1776 accum_
.GetClassifiedMessages(&msgs
);
1778 // We issued (kMaxRequests + 4) total requests.
1779 ASSERT_EQ(kMaxRequests
+ 4, msgs
.size());
1781 // Check that the first kMaxRequests succeeded.
1782 for (size_t i
= 0; i
< kMaxRequests
; ++i
)
1783 CheckSuccessfulRequest(msgs
[i
], net::URLRequestTestJob::test_data_2());
1785 // Check that the subsequent two requests (kMaxRequests + 1) and
1786 // (kMaxRequests + 2) were failed, since the per-process bound was reached.
1787 for (int i
= 0; i
< 2; ++i
) {
1788 // Should have sent a single RequestComplete message.
1789 int index
= kMaxRequests
+ i
;
1790 CheckFailedRequest(msgs
[index
], net::URLRequestTestJob::test_data_2(),
1791 net::ERR_INSUFFICIENT_RESOURCES
);
1794 // The final 2 requests should have succeeded.
1795 CheckSuccessfulRequest(msgs
[kMaxRequests
+ 2],
1796 net::URLRequestTestJob::test_data_2());
1797 CheckSuccessfulRequest(msgs
[kMaxRequests
+ 3],
1798 net::URLRequestTestJob::test_data_2());
1801 // Test that when too many requests are outstanding for a particular
1802 // render_process_host_id, any subsequent request from it fails. Also verify
1803 // that the global limit is honored.
1804 TEST_F(ResourceDispatcherHostTest
, TooManyOutstandingRequests
) {
1805 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
1806 const size_t kMaxRequestsPerProcess
= 2;
1807 host_
.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess
);
1808 const size_t kMaxRequests
= 3;
1809 host_
.set_max_num_in_flight_requests(kMaxRequests
);
1811 // Needed to emulate additional processes.
1812 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
1813 this, browser_context_
->GetResourceContext());
1814 scoped_refptr
<ForwardingFilter
> third_filter
= new ForwardingFilter(
1815 this, browser_context_
->GetResourceContext());
1817 // Saturate the number of outstanding requests for our process.
1818 for (size_t i
= 0; i
< kMaxRequestsPerProcess
; ++i
) {
1819 MakeTestRequestWithResourceType(filter_
.get(), 0, i
+ 1,
1820 net::URLRequestTestJob::test_url_2(),
1821 ResourceType::SUB_RESOURCE
);
1824 // Issue another request for our process -- this should fail immediately.
1825 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequestsPerProcess
+ 1,
1826 net::URLRequestTestJob::test_url_2(),
1827 ResourceType::SUB_RESOURCE
);
1829 // Issue a request for the second process -- this should succeed, because it
1830 // is just process 0 that is saturated.
1831 MakeTestRequestWithResourceType(
1832 second_filter
.get(), 0, kMaxRequestsPerProcess
+ 2,
1833 net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE
);
1835 // Issue a request for the third process -- this should fail, because the
1836 // global limit has been reached.
1837 MakeTestRequestWithResourceType(
1838 third_filter
.get(), 0, kMaxRequestsPerProcess
+ 3,
1839 net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE
);
1841 // Flush all the pending requests.
1842 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1843 base::MessageLoop::current()->RunUntilIdle();
1845 // Sorts out all the messages we saw by request.
1846 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1847 accum_
.GetClassifiedMessages(&msgs
);
1849 // The processes issued the following requests:
1850 // #1 issued kMaxRequestsPerProcess that passed + 1 that failed
1851 // #2 issued 1 request that passed
1852 // #3 issued 1 request that failed
1853 ASSERT_EQ((kMaxRequestsPerProcess
+ 1) + 1 + 1, msgs
.size());
1855 for (size_t i
= 0; i
< kMaxRequestsPerProcess
; ++i
)
1856 CheckSuccessfulRequest(msgs
[i
], net::URLRequestTestJob::test_data_2());
1858 CheckFailedRequest(msgs
[kMaxRequestsPerProcess
+ 0],
1859 net::URLRequestTestJob::test_data_2(),
1860 net::ERR_INSUFFICIENT_RESOURCES
);
1861 CheckSuccessfulRequest(msgs
[kMaxRequestsPerProcess
+ 1],
1862 net::URLRequestTestJob::test_data_2());
1863 CheckFailedRequest(msgs
[kMaxRequestsPerProcess
+ 2],
1864 net::URLRequestTestJob::test_data_2(),
1865 net::ERR_INSUFFICIENT_RESOURCES
);
1868 // Tests that we sniff the mime type for a simple request.
1869 TEST_F(ResourceDispatcherHostTest
, MimeSniffed
) {
1870 std::string
raw_headers("HTTP/1.1 200 OK\n\n");
1871 std::string
response_data("<html><title>Test One</title></html>");
1872 SetResponse(raw_headers
, response_data
);
1874 HandleScheme("http");
1875 MakeTestRequest(0, 1, GURL("http:bla"));
1877 // Flush all pending requests.
1878 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1880 // Sorts out all the messages we saw by request.
1881 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1882 accum_
.GetClassifiedMessages(&msgs
);
1883 ASSERT_EQ(1U, msgs
.size());
1885 ResourceResponseHead response_head
;
1886 GetResponseHead(msgs
[0], &response_head
);
1887 ASSERT_EQ("text/html", response_head
.mime_type
);
1890 // Tests that we don't sniff the mime type when the server provides one.
1891 TEST_F(ResourceDispatcherHostTest
, MimeNotSniffed
) {
1892 std::string
raw_headers("HTTP/1.1 200 OK\n"
1893 "Content-type: image/jpeg\n\n");
1894 std::string
response_data("<html><title>Test One</title></html>");
1895 SetResponse(raw_headers
, response_data
);
1897 HandleScheme("http");
1898 MakeTestRequest(0, 1, GURL("http:bla"));
1900 // Flush all pending requests.
1901 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1903 // Sorts out all the messages we saw by request.
1904 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1905 accum_
.GetClassifiedMessages(&msgs
);
1906 ASSERT_EQ(1U, msgs
.size());
1908 ResourceResponseHead response_head
;
1909 GetResponseHead(msgs
[0], &response_head
);
1910 ASSERT_EQ("image/jpeg", response_head
.mime_type
);
1913 // Tests that we don't sniff the mime type when there is no message body.
1914 TEST_F(ResourceDispatcherHostTest
, MimeNotSniffed2
) {
1915 SetResponse("HTTP/1.1 304 Not Modified\n\n");
1917 HandleScheme("http");
1918 MakeTestRequest(0, 1, GURL("http:bla"));
1920 // Flush all pending requests.
1921 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1923 // Sorts out all the messages we saw by request.
1924 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1925 accum_
.GetClassifiedMessages(&msgs
);
1926 ASSERT_EQ(1U, msgs
.size());
1928 ResourceResponseHead response_head
;
1929 GetResponseHead(msgs
[0], &response_head
);
1930 ASSERT_EQ("", response_head
.mime_type
);
1933 TEST_F(ResourceDispatcherHostTest
, MimeSniff204
) {
1934 SetResponse("HTTP/1.1 204 No Content\n\n");
1936 HandleScheme("http");
1937 MakeTestRequest(0, 1, GURL("http:bla"));
1939 // Flush all pending requests.
1940 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1942 // Sorts out all the messages we saw by request.
1943 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1944 accum_
.GetClassifiedMessages(&msgs
);
1945 ASSERT_EQ(1U, msgs
.size());
1947 ResourceResponseHead response_head
;
1948 GetResponseHead(msgs
[0], &response_head
);
1949 ASSERT_EQ("text/plain", response_head
.mime_type
);
1952 TEST_F(ResourceDispatcherHostTest
, MimeSniffEmpty
) {
1953 SetResponse("HTTP/1.1 200 OK\n\n");
1955 HandleScheme("http");
1956 MakeTestRequest(0, 1, GURL("http:bla"));
1958 // Flush all pending requests.
1959 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1961 // Sorts out all the messages we saw by request.
1962 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1963 accum_
.GetClassifiedMessages(&msgs
);
1964 ASSERT_EQ(1U, msgs
.size());
1966 ResourceResponseHead response_head
;
1967 GetResponseHead(msgs
[0], &response_head
);
1968 ASSERT_EQ("text/plain", response_head
.mime_type
);
1971 // Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
1972 TEST_F(ResourceDispatcherHostTest
, ForbiddenDownload
) {
1973 std::string
raw_headers("HTTP/1.1 403 Forbidden\n"
1974 "Content-disposition: attachment; filename=blah\n"
1975 "Content-type: application/octet-stream\n\n");
1976 std::string
response_data("<html><title>Test One</title></html>");
1977 SetResponse(raw_headers
, response_data
);
1979 HandleScheme("http");
1981 // Only MAIN_FRAMEs can trigger a download.
1982 MakeTestRequestWithResourceType(filter_
.get(), 0, 1, GURL("http:bla"),
1983 ResourceType::MAIN_FRAME
);
1985 // Flush all pending requests.
1986 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1988 // Sorts out all the messages we saw by request.
1989 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1990 accum_
.GetClassifiedMessages(&msgs
);
1992 // We should have gotten one RequestComplete message.
1993 ASSERT_EQ(1U, msgs
[0].size());
1994 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][0].type());
1996 // The RequestComplete message should have had the error code of
1997 // ERR_FILE_NOT_FOUND.
1998 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_FILE_NOT_FOUND
);
2001 // Test for http://crbug.com/76202 . We don't want to destroy a
2002 // download request prematurely when processing a cancellation from
2004 TEST_F(ResourceDispatcherHostTest
, IgnoreCancelForDownloads
) {
2005 EXPECT_EQ(0, host_
.pending_requests());
2007 int render_view_id
= 0;
2010 std::string
raw_headers("HTTP\n"
2011 "Content-disposition: attachment; filename=foo\n\n");
2012 std::string
response_data("01234567890123456789\x01foobar");
2014 // Get past sniffing metrics in the BufferedResourceHandler. Note that
2015 // if we don't get past the sniffing metrics, the result will be that
2016 // the BufferedResourceHandler won't have figured out that it's a download,
2017 // won't have constructed a DownloadResourceHandler, and and the request
2018 // will be successfully canceled below, failing the test.
2019 response_data
.resize(1025, ' ');
2021 SetResponse(raw_headers
, response_data
);
2022 SetDelayedCompleteJobGeneration(true);
2023 HandleScheme("http");
2025 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2026 GURL("http://example.com/blah"),
2027 ResourceType::MAIN_FRAME
);
2028 // Return some data so that the request is identified as a download
2029 // and the proper resource handlers are created.
2030 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2032 // And now simulate a cancellation coming from the renderer.
2033 ResourceHostMsg_CancelRequest
msg(request_id
);
2035 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2037 // Since the request had already started processing as a download,
2038 // the cancellation above should have been ignored and the request
2039 // should still be alive.
2040 EXPECT_EQ(1, host_
.pending_requests());
2042 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2045 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContext
) {
2046 EXPECT_EQ(0, host_
.pending_requests());
2048 int render_view_id
= 0;
2051 std::string
raw_headers("HTTP\n"
2052 "Content-disposition: attachment; filename=foo\n\n");
2053 std::string
response_data("01234567890123456789\x01foobar");
2054 // Get past sniffing metrics.
2055 response_data
.resize(1025, ' ');
2057 SetResponse(raw_headers
, response_data
);
2058 SetDelayedCompleteJobGeneration(true);
2059 HandleScheme("http");
2061 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2062 GURL("http://example.com/blah"),
2063 ResourceType::MAIN_FRAME
);
2064 // Return some data so that the request is identified as a download
2065 // and the proper resource handlers are created.
2066 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2068 // And now simulate a cancellation coming from the renderer.
2069 ResourceHostMsg_CancelRequest
msg(request_id
);
2071 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2073 // Since the request had already started processing as a download,
2074 // the cancellation above should have been ignored and the request
2075 // should still be alive.
2076 EXPECT_EQ(1, host_
.pending_requests());
2078 // Cancelling by other methods shouldn't work either.
2079 host_
.CancelRequestsForProcess(render_view_id
);
2080 EXPECT_EQ(1, host_
.pending_requests());
2082 // Cancelling by context should work.
2083 host_
.CancelRequestsForContext(filter_
->resource_context());
2084 EXPECT_EQ(0, host_
.pending_requests());
2087 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContextDetached
) {
2088 EXPECT_EQ(0, host_
.pending_requests());
2090 int render_view_id
= 0;
2093 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2094 net::URLRequestTestJob::test_url_4(),
2095 ResourceType::PREFETCH
); // detachable type
2097 // Simulate a cancel coming from the renderer.
2098 host_
.CancelRequest(filter_
->child_id(), request_id
, true);
2100 // Since the request had already started processing as detachable,
2101 // the cancellation above should have been ignored and the request
2102 // should have been detached.
2103 EXPECT_EQ(1, host_
.pending_requests());
2105 // Cancelling by other methods should also leave it detached.
2106 host_
.CancelRequestsForProcess(render_view_id
);
2107 EXPECT_EQ(1, host_
.pending_requests());
2109 // Cancelling by context should work.
2110 host_
.CancelRequestsForContext(filter_
->resource_context());
2111 EXPECT_EQ(0, host_
.pending_requests());
2114 // Test the cancelling of requests that are being transferred to a new renderer
2115 // due to a redirection.
2116 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContextTransferred
) {
2117 EXPECT_EQ(0, host_
.pending_requests());
2119 int render_view_id
= 0;
2122 std::string
raw_headers("HTTP/1.1 200 OK\n"
2123 "Content-Type: text/html; charset=utf-8\n\n");
2124 std::string
response_data("<html>foobar</html>");
2126 SetResponse(raw_headers
, response_data
);
2127 HandleScheme("http");
2129 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2130 GURL("http://example.com/blah"),
2131 ResourceType::MAIN_FRAME
);
2134 GlobalRequestID
global_request_id(filter_
->child_id(), request_id
);
2135 host_
.MarkAsTransferredNavigation(global_request_id
);
2137 // And now simulate a cancellation coming from the renderer.
2138 ResourceHostMsg_CancelRequest
msg(request_id
);
2140 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2142 // Since the request is marked as being transferred,
2143 // the cancellation above should have been ignored and the request
2144 // should still be alive.
2145 EXPECT_EQ(1, host_
.pending_requests());
2147 // Cancelling by other methods shouldn't work either.
2148 host_
.CancelRequestsForProcess(render_view_id
);
2149 EXPECT_EQ(1, host_
.pending_requests());
2151 // Cancelling by context should work.
2152 host_
.CancelRequestsForContext(filter_
->resource_context());
2153 EXPECT_EQ(0, host_
.pending_requests());
2156 // Test transferred navigations with text/html, which doesn't trigger any
2157 // content sniffing.
2158 TEST_F(ResourceDispatcherHostTest
, TransferNavigationHtml
) {
2159 EXPECT_EQ(0, host_
.pending_requests());
2161 int render_view_id
= 0;
2164 // Configure initial request.
2165 SetResponse("HTTP/1.1 302 Found\n"
2166 "Location: http://other.com/blech\n\n");
2168 HandleScheme("http");
2170 // Temporarily replace ContentBrowserClient with one that will trigger the
2171 // transfer navigation code paths.
2172 TransfersAllNavigationsContentBrowserClient new_client
;
2173 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2175 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2176 GURL("http://example.com/blah"),
2177 ResourceType::MAIN_FRAME
);
2179 // Now that we're blocked on the redirect, update the response and unblock by
2180 // telling the AsyncResourceHandler to follow the redirect.
2181 const std::string kResponseBody
= "hello world";
2182 SetResponse("HTTP/1.1 200 OK\n"
2183 "Content-Type: text/html\n\n",
2185 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
, false, GURL());
2187 host_
.OnMessageReceived(redirect_msg
, filter_
.get(), &msg_was_ok
);
2188 base::MessageLoop::current()->RunUntilIdle();
2190 // Flush all the pending requests to get the response through the
2191 // BufferedResourceHandler.
2192 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2194 // Restore, now that we've set up a transfer.
2195 SetBrowserClientForTesting(old_client
);
2197 // This second filter is used to emulate a second process.
2198 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
2199 this, browser_context_
->GetResourceContext());
2201 int new_render_view_id
= 1;
2202 int new_request_id
= 2;
2204 ResourceHostMsg_Request request
=
2205 CreateResourceRequest("GET", ResourceType::MAIN_FRAME
,
2206 GURL("http://other.com/blech"));
2207 request
.transferred_request_child_id
= filter_
->child_id();
2208 request
.transferred_request_request_id
= request_id
;
2211 child_ids_
.insert(second_filter
->child_id());
2212 ResourceHostMsg_RequestResource
transfer_request_msg(
2213 new_render_view_id
, new_request_id
, request
);
2214 host_
.OnMessageReceived(
2215 transfer_request_msg
, second_filter
.get(), &msg_was_ok
);
2216 base::MessageLoop::current()->RunUntilIdle();
2218 // Check generated messages.
2219 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2220 accum_
.GetClassifiedMessages(&msgs
);
2222 ASSERT_EQ(2U, msgs
.size());
2223 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2224 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2227 // Test transferred navigations with text/plain, which causes
2228 // BufferedResourceHandler to buffer the response to sniff the content
2229 // before the transfer occurs.
2230 TEST_F(ResourceDispatcherHostTest
, TransferNavigationText
) {
2231 EXPECT_EQ(0, host_
.pending_requests());
2233 int render_view_id
= 0;
2236 // Configure initial request.
2237 SetResponse("HTTP/1.1 302 Found\n"
2238 "Location: http://other.com/blech\n\n");
2240 HandleScheme("http");
2242 // Temporarily replace ContentBrowserClient with one that will trigger the
2243 // transfer navigation code paths.
2244 TransfersAllNavigationsContentBrowserClient new_client
;
2245 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2247 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2248 GURL("http://example.com/blah"),
2249 ResourceType::MAIN_FRAME
);
2251 // Now that we're blocked on the redirect, update the response and unblock by
2252 // telling the AsyncResourceHandler to follow the redirect. Use a text/plain
2253 // MIME type, which causes BufferedResourceHandler to buffer it before the
2255 const std::string kResponseBody
= "hello world";
2256 SetResponse("HTTP/1.1 200 OK\n"
2257 "Content-Type: text/plain\n\n",
2259 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
, false, GURL());
2261 host_
.OnMessageReceived(redirect_msg
, filter_
.get(), &msg_was_ok
);
2262 base::MessageLoop::current()->RunUntilIdle();
2264 // Flush all the pending requests to get the response through the
2265 // BufferedResourceHandler.
2266 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2268 // Restore, now that we've set up a transfer.
2269 SetBrowserClientForTesting(old_client
);
2271 // This second filter is used to emulate a second process.
2272 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
2273 this, browser_context_
->GetResourceContext());
2275 int new_render_view_id
= 1;
2276 int new_request_id
= 2;
2278 ResourceHostMsg_Request request
=
2279 CreateResourceRequest("GET", ResourceType::MAIN_FRAME
,
2280 GURL("http://other.com/blech"));
2281 request
.transferred_request_child_id
= filter_
->child_id();
2282 request
.transferred_request_request_id
= request_id
;
2285 child_ids_
.insert(second_filter
->child_id());
2286 ResourceHostMsg_RequestResource
transfer_request_msg(
2287 new_render_view_id
, new_request_id
, request
);
2288 host_
.OnMessageReceived(
2289 transfer_request_msg
, second_filter
.get(), &msg_was_ok
);
2290 base::MessageLoop::current()->RunUntilIdle();
2292 // Check generated messages.
2293 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2294 accum_
.GetClassifiedMessages(&msgs
);
2296 ASSERT_EQ(2U, msgs
.size());
2297 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2298 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2301 TEST_F(ResourceDispatcherHostTest
, TransferNavigationWithProcessCrash
) {
2302 EXPECT_EQ(0, host_
.pending_requests());
2304 int render_view_id
= 0;
2306 int first_child_id
= -1;
2308 // Configure initial request.
2309 SetResponse("HTTP/1.1 302 Found\n"
2310 "Location: http://other.com/blech\n\n");
2311 const std::string kResponseBody
= "hello world";
2313 HandleScheme("http");
2315 // Temporarily replace ContentBrowserClient with one that will trigger the
2316 // transfer navigation code paths.
2317 TransfersAllNavigationsContentBrowserClient new_client
;
2318 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2320 // Create a first filter that can be deleted before the second one starts.
2322 scoped_refptr
<ForwardingFilter
> first_filter
= new ForwardingFilter(
2323 this, browser_context_
->GetResourceContext());
2324 first_child_id
= first_filter
->child_id();
2326 ResourceHostMsg_Request first_request
=
2327 CreateResourceRequest("GET", ResourceType::MAIN_FRAME
,
2328 GURL("http://example.com/blah"));
2331 child_ids_
.insert(first_child_id
);
2332 ResourceHostMsg_RequestResource
first_request_msg(
2333 render_view_id
, request_id
, first_request
);
2335 host_
.OnMessageReceived(
2336 first_request_msg
, first_filter
.get(), &msg_was_ok
);
2337 base::MessageLoop::current()->RunUntilIdle();
2339 // Now that we're blocked on the redirect, update the response and unblock
2340 // by telling the AsyncResourceHandler to follow the redirect.
2341 SetResponse("HTTP/1.1 200 OK\n"
2342 "Content-Type: text/html\n\n",
2344 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
, false, GURL());
2345 host_
.OnMessageReceived(redirect_msg
, first_filter
.get(), &msg_was_ok
);
2346 base::MessageLoop::current()->RunUntilIdle();
2348 // Flush all the pending requests to get the response through the
2349 // BufferedResourceHandler.
2350 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2352 // The first filter is now deleted, as if the child process died.
2355 SetBrowserClientForTesting(old_client
);
2357 // Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
2358 GlobalRequestID
first_global_request_id(first_child_id
, request_id
);
2360 // This second filter is used to emulate a second process.
2361 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
2362 this, browser_context_
->GetResourceContext());
2364 int new_render_view_id
= 1;
2365 int new_request_id
= 2;
2367 ResourceHostMsg_Request request
=
2368 CreateResourceRequest("GET", ResourceType::MAIN_FRAME
,
2369 GURL("http://other.com/blech"));
2370 request
.transferred_request_child_id
= first_child_id
;
2371 request
.transferred_request_request_id
= request_id
;
2374 child_ids_
.insert(second_filter
->child_id());
2375 ResourceHostMsg_RequestResource
transfer_request_msg(
2376 new_render_view_id
, new_request_id
, request
);
2378 host_
.OnMessageReceived(
2379 transfer_request_msg
, second_filter
.get(), &msg_was_ok
);
2380 base::MessageLoop::current()->RunUntilIdle();
2382 // Check generated messages.
2383 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2384 accum_
.GetClassifiedMessages(&msgs
);
2386 ASSERT_EQ(2U, msgs
.size());
2387 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2388 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2391 TEST_F(ResourceDispatcherHostTest
, TransferNavigationWithTwoRedirects
) {
2392 EXPECT_EQ(0, host_
.pending_requests());
2394 int render_view_id
= 0;
2397 // Configure initial request.
2398 SetResponse("HTTP/1.1 302 Found\n"
2399 "Location: http://other.com/blech\n\n");
2401 HandleScheme("http");
2403 // Temporarily replace ContentBrowserClient with one that will trigger the
2404 // transfer navigation code paths.
2405 TransfersAllNavigationsContentBrowserClient new_client
;
2406 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2408 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2409 GURL("http://example.com/blah"),
2410 ResourceType::MAIN_FRAME
);
2412 // Now that we're blocked on the redirect, simulate hitting another redirect.
2413 SetResponse("HTTP/1.1 302 Found\n"
2414 "Location: http://other.com/blerg\n\n");
2415 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
, false, GURL());
2417 host_
.OnMessageReceived(redirect_msg
, filter_
.get(), &msg_was_ok
);
2418 base::MessageLoop::current()->RunUntilIdle();
2420 // Now that we're blocked on the second redirect, update the response and
2421 // unblock by telling the AsyncResourceHandler to follow the redirect.
2422 // Again, use text/plain to force BufferedResourceHandler to buffer before
2424 const std::string kResponseBody
= "hello world";
2425 SetResponse("HTTP/1.1 200 OK\n"
2426 "Content-Type: text/plain\n\n",
2428 ResourceHostMsg_FollowRedirect
redirect_msg2(request_id
, false, GURL());
2429 host_
.OnMessageReceived(redirect_msg2
, filter_
.get(), &msg_was_ok
);
2430 base::MessageLoop::current()->RunUntilIdle();
2432 // Flush all the pending requests to get the response through the
2433 // BufferedResourceHandler.
2434 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2437 SetBrowserClientForTesting(old_client
);
2439 // This second filter is used to emulate a second process.
2440 scoped_refptr
<ForwardingFilter
> second_filter
= new ForwardingFilter(
2441 this, browser_context_
->GetResourceContext());
2443 int new_render_view_id
= 1;
2444 int new_request_id
= 2;
2446 ResourceHostMsg_Request request
=
2447 CreateResourceRequest("GET", ResourceType::MAIN_FRAME
,
2448 GURL("http://other.com/blech"));
2449 request
.transferred_request_child_id
= filter_
->child_id();
2450 request
.transferred_request_request_id
= request_id
;
2453 child_ids_
.insert(second_filter
->child_id());
2454 ResourceHostMsg_RequestResource
transfer_request_msg(
2455 new_render_view_id
, new_request_id
, request
);
2456 host_
.OnMessageReceived(
2457 transfer_request_msg
, second_filter
.get(), &msg_was_ok
);
2459 // Verify that we update the ResourceRequestInfo.
2460 GlobalRequestID
global_request_id(second_filter
->child_id(), new_request_id
);
2461 const ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
2462 host_
.GetURLRequest(global_request_id
));
2463 EXPECT_EQ(second_filter
->child_id(), info
->GetChildID());
2464 EXPECT_EQ(new_render_view_id
, info
->GetRouteID());
2465 EXPECT_EQ(new_request_id
, info
->GetRequestID());
2466 EXPECT_EQ(second_filter
, info
->filter());
2468 // Let request complete.
2469 base::MessageLoop::current()->RunUntilIdle();
2471 // Check generated messages.
2472 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2473 accum_
.GetClassifiedMessages(&msgs
);
2475 ASSERT_EQ(2U, msgs
.size());
2476 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2477 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2480 TEST_F(ResourceDispatcherHostTest
, UnknownURLScheme
) {
2481 EXPECT_EQ(0, host_
.pending_requests());
2483 HandleScheme("http");
2485 MakeTestRequestWithResourceType(filter_
.get(), 0, 1, GURL("foo://bar"),
2486 ResourceType::MAIN_FRAME
);
2488 // Flush all pending requests.
2489 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2491 // Sort all the messages we saw by request.
2492 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2493 accum_
.GetClassifiedMessages(&msgs
);
2495 // We should have gotten one RequestComplete message.
2496 ASSERT_EQ(1U, msgs
[0].size());
2497 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][0].type());
2499 // The RequestComplete message should have the error code of
2500 // ERR_UNKNOWN_URL_SCHEME.
2501 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_UNKNOWN_URL_SCHEME
);
2504 TEST_F(ResourceDispatcherHostTest
, DataReceivedACKs
) {
2505 EXPECT_EQ(0, host_
.pending_requests());
2507 SendDataReceivedACKs(true);
2509 HandleScheme("big-job");
2510 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2512 // Sort all the messages we saw by request.
2513 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2514 accum_
.GetClassifiedMessages(&msgs
);
2516 size_t size
= msgs
[0].size();
2518 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
2519 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
2520 for (size_t i
= 2; i
< size
- 1; ++i
)
2521 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2522 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][size
- 1].type());
2525 // Request a very large detachable resource and cancel part way. Some of the
2526 // data should have been sent to the renderer, but not all.
2527 TEST_F(ResourceDispatcherHostTest
, DataSentBeforeDetach
) {
2528 EXPECT_EQ(0, host_
.pending_requests());
2530 int render_view_id
= 0;
2533 std::string
raw_headers("HTTP\n"
2534 "Content-type: image/jpeg\n\n");
2535 std::string
response_data("01234567890123456789\x01foobar");
2537 // Create a response larger than kMaxAllocationSize (currently 32K). Note
2538 // that if this increase beyond 512K we'll need to make the response longer.
2539 const int kAllocSize
= 1024*512;
2540 response_data
.resize(kAllocSize
, ' ');
2542 SetResponse(raw_headers
, response_data
);
2543 SetDelayedCompleteJobGeneration(true);
2544 HandleScheme("http");
2546 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2547 GURL("http://example.com/blah"),
2548 ResourceType::PREFETCH
);
2550 // Get a bit of data before cancelling.
2551 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2553 // Simulate a cancellation coming from the renderer.
2554 ResourceHostMsg_CancelRequest
msg(request_id
);
2556 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2558 EXPECT_EQ(1, host_
.pending_requests());
2560 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2562 // Sort all the messages we saw by request.
2563 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2564 accum_
.GetClassifiedMessages(&msgs
);
2566 EXPECT_EQ(4U, msgs
[0].size());
2568 // Figure out how many bytes were received by the renderer.
2572 ExtractDataOffsetAndLength(msgs
[0][2], &data_offset
, &data_length
));
2573 EXPECT_LT(0, data_length
);
2574 EXPECT_GT(kAllocSize
, data_length
);
2576 // Verify the data that was received before cancellation. The request should
2577 // have appeared to cancel, however.
2578 CheckSuccessfulRequestWithErrorCode(
2580 std::string(response_data
.begin(), response_data
.begin() + data_length
),
2584 TEST_F(ResourceDispatcherHostTest
, DelayedDataReceivedACKs
) {
2585 EXPECT_EQ(0, host_
.pending_requests());
2587 HandleScheme("big-job");
2588 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2590 // Sort all the messages we saw by request.
2591 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2592 accum_
.GetClassifiedMessages(&msgs
);
2594 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
2595 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
2596 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
2597 for (size_t i
= 2; i
< msgs
[0].size(); ++i
)
2598 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2600 // NOTE: If we fail the above checks then it means that we probably didn't
2601 // load a big enough response to trigger the delay mechanism we are trying to
2604 msgs
[0].erase(msgs
[0].begin());
2605 msgs
[0].erase(msgs
[0].begin());
2607 // ACK all DataReceived messages until we find a RequestComplete message.
2608 bool complete
= false;
2610 for (size_t i
= 0; i
< msgs
[0].size(); ++i
) {
2611 if (msgs
[0][i
].type() == ResourceMsg_RequestComplete::ID
) {
2616 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2618 ResourceHostMsg_DataReceived_ACK
msg(1);
2620 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2623 base::MessageLoop::current()->RunUntilIdle();
2626 accum_
.GetClassifiedMessages(&msgs
);
2630 // Flakyness of this test might indicate memory corruption issues with
2631 // for example the ResourceBuffer of AsyncResourceHandler.
2632 TEST_F(ResourceDispatcherHostTest
, DataReceivedUnexpectedACKs
) {
2633 EXPECT_EQ(0, host_
.pending_requests());
2635 HandleScheme("big-job");
2636 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2638 // Sort all the messages we saw by request.
2639 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2640 accum_
.GetClassifiedMessages(&msgs
);
2642 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
2643 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
2644 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
2645 for (size_t i
= 2; i
< msgs
[0].size(); ++i
)
2646 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2648 // NOTE: If we fail the above checks then it means that we probably didn't
2649 // load a big enough response to trigger the delay mechanism.
2651 // Send some unexpected ACKs.
2652 for (size_t i
= 0; i
< 128; ++i
) {
2653 ResourceHostMsg_DataReceived_ACK
msg(1);
2655 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2658 msgs
[0].erase(msgs
[0].begin());
2659 msgs
[0].erase(msgs
[0].begin());
2661 // ACK all DataReceived messages until we find a RequestComplete message.
2662 bool complete
= false;
2664 for (size_t i
= 0; i
< msgs
[0].size(); ++i
) {
2665 if (msgs
[0][i
].type() == ResourceMsg_RequestComplete::ID
) {
2670 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2672 ResourceHostMsg_DataReceived_ACK
msg(1);
2674 host_
.OnMessageReceived(msg
, filter_
.get(), &msg_was_ok
);
2677 base::MessageLoop::current()->RunUntilIdle();
2680 accum_
.GetClassifiedMessages(&msgs
);
2684 } // namespace content