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.
7 #include "base/basictypes.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/location.h"
13 #include "base/memory/scoped_vector.h"
14 #include "base/memory/shared_memory.h"
15 #include "base/pickle.h"
16 #include "base/run_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "content/browser/browser_thread_impl.h"
22 #include "content/browser/child_process_security_policy_impl.h"
23 #include "content/browser/loader/cross_site_resource_handler.h"
24 #include "content/browser/loader/detachable_resource_handler.h"
25 #include "content/browser/loader/resource_dispatcher_host_impl.h"
26 #include "content/browser/loader/resource_loader.h"
27 #include "content/browser/loader/resource_message_filter.h"
28 #include "content/browser/loader/resource_request_info_impl.h"
29 #include "content/common/appcache_interfaces.h"
30 #include "content/common/child_process_host_impl.h"
31 #include "content/common/resource_messages.h"
32 #include "content/common/view_messages.h"
33 #include "content/public/browser/global_request_id.h"
34 #include "content/public/browser/render_process_host.h"
35 #include "content/public/browser/resource_context.h"
36 #include "content/public/browser/resource_dispatcher_host_delegate.h"
37 #include "content/public/browser/resource_request_info.h"
38 #include "content/public/browser/resource_throttle.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/web_contents_observer.h"
41 #include "content/public/common/child_process_host.h"
42 #include "content/public/common/content_switches.h"
43 #include "content/public/common/process_type.h"
44 #include "content/public/common/resource_response.h"
45 #include "content/public/test/test_browser_context.h"
46 #include "content/public/test/test_browser_thread_bundle.h"
47 #include "content/public/test/test_renderer_host.h"
48 #include "content/test/test_content_browser_client.h"
49 #include "net/base/elements_upload_data_stream.h"
50 #include "net/base/net_errors.h"
51 #include "net/base/request_priority.h"
52 #include "net/base/upload_bytes_element_reader.h"
53 #include "net/http/http_util.h"
54 #include "net/url_request/url_request.h"
55 #include "net/url_request/url_request_context.h"
56 #include "net/url_request/url_request_job.h"
57 #include "net/url_request/url_request_job_factory.h"
58 #include "net/url_request/url_request_simple_job.h"
59 #include "net/url_request/url_request_test_job.h"
60 #include "net/url_request/url_request_test_util.h"
61 #include "storage/browser/blob/shareable_file_reference.h"
62 #include "testing/gtest/include/gtest/gtest.h"
64 // TODO(eroman): Write unit tests for SafeBrowsing that exercise
65 // SafeBrowsingResourceHandler.
67 using storage::ShareableFileReference
;
73 // Returns the resource response header structure for this request.
74 void GetResponseHead(const std::vector
<IPC::Message
>& messages
,
75 ResourceResponseHead
* response_head
) {
76 ASSERT_GE(messages
.size(), 2U);
78 // The first messages should be received response.
79 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
81 base::PickleIterator
iter(messages
[0]);
83 ASSERT_TRUE(IPC::ReadParam(&messages
[0], &iter
, &request_id
));
84 ASSERT_TRUE(IPC::ReadParam(&messages
[0], &iter
, response_head
));
87 void GenerateIPCMessage(
88 scoped_refptr
<ResourceMessageFilter
> filter
,
89 scoped_ptr
<IPC::Message
> message
) {
90 ResourceDispatcherHostImpl::Get()->OnMessageReceived(
91 *message
, filter
.get());
94 // On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not
95 // automatically released.
97 // See ResourceDispatcher::ReleaseResourcesInDataMessage.
99 // TODO(davidben): It would be nice if the behavior for base::SharedMemoryHandle
100 // were more like it is in POSIX where the received fds are tracked in a
101 // ref-counted core that closes them if not extracted.
102 void ReleaseHandlesInMessage(const IPC::Message
& message
) {
103 if (message
.type() == ResourceMsg_SetDataBuffer::ID
) {
104 base::PickleIterator
iter(message
);
106 CHECK(iter
.ReadInt(&request_id
));
107 base::SharedMemoryHandle shm_handle
;
108 if (IPC::ParamTraits
<base::SharedMemoryHandle
>::Read(&message
,
111 if (base::SharedMemory::IsHandleValid(shm_handle
))
112 base::SharedMemory::CloseHandle(shm_handle
);
119 static int RequestIDForMessage(const IPC::Message
& msg
) {
121 switch (msg
.type()) {
122 case ResourceMsg_UploadProgress::ID
:
123 case ResourceMsg_ReceivedResponse::ID
:
124 case ResourceMsg_ReceivedRedirect::ID
:
125 case ResourceMsg_SetDataBuffer::ID
:
126 case ResourceMsg_DataReceived::ID
:
127 case ResourceMsg_DataDownloaded::ID
:
128 case ResourceMsg_RequestComplete::ID
: {
129 bool result
= base::PickleIterator(msg
).ReadInt(&request_id
);
137 static ResourceHostMsg_Request
CreateResourceRequest(const char* method
,
140 ResourceHostMsg_Request request
;
141 request
.method
= std::string(method
);
143 request
.first_party_for_cookies
= url
; // bypass third-party cookie blocking
144 request
.referrer_policy
= blink::WebReferrerPolicyDefault
;
145 request
.load_flags
= 0;
146 request
.origin_pid
= 0;
147 request
.resource_type
= type
;
148 request
.request_context
= 0;
149 request
.appcache_host_id
= kAppCacheNoHostId
;
150 request
.download_to_file
= false;
151 request
.should_reset_appcache
= false;
152 request
.is_main_frame
= true;
153 request
.parent_is_main_frame
= false;
154 request
.parent_render_frame_id
= -1;
155 request
.transition_type
= ui::PAGE_TRANSITION_LINK
;
156 request
.allow_download
= true;
160 // Spin up the message loop to kick off the request.
161 static void KickOffRequest() {
162 base::MessageLoop::current()->RunUntilIdle();
165 // We may want to move this to a shared space if it is useful for something else
166 class ResourceIPCAccumulator
{
168 ~ResourceIPCAccumulator() {
169 for (size_t i
= 0; i
< messages_
.size(); i
++) {
170 ReleaseHandlesInMessage(messages_
[i
]);
174 // On Windows, takes ownership of SharedMemoryHandles in |msg|.
175 void AddMessage(const IPC::Message
& msg
) {
176 messages_
.push_back(msg
);
179 // This groups the messages by their request ID. The groups will be in order
180 // that the first message for each request ID was received, and the messages
181 // within the groups will be in the order that they appeared.
182 // Note that this clears messages_. The caller takes ownership of any
183 // SharedMemoryHandles in messages placed into |msgs|.
184 typedef std::vector
< std::vector
<IPC::Message
> > ClassifiedMessages
;
185 void GetClassifiedMessages(ClassifiedMessages
* msgs
);
188 std::vector
<IPC::Message
> messages_
;
191 // This is very inefficient as a result of repeatedly extracting the ID, use
193 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages
* msgs
) {
194 while (!messages_
.empty()) {
195 // Ignore unknown message types as it is valid for code to generated other
196 // IPCs as side-effects that we are not testing here.
197 int cur_id
= RequestIDForMessage(messages_
[0]);
199 std::vector
<IPC::Message
> cur_requests
;
200 cur_requests
.push_back(messages_
[0]);
201 // find all other messages with this ID
202 for (int i
= 1; i
< static_cast<int>(messages_
.size()); i
++) {
203 int id
= RequestIDForMessage(messages_
[i
]);
205 cur_requests
.push_back(messages_
[i
]);
206 messages_
.erase(messages_
.begin() + i
);
210 msgs
->push_back(cur_requests
);
212 messages_
.erase(messages_
.begin());
216 // This is used to create a filter matching a specified child id.
217 class TestFilterSpecifyingChild
: public ResourceMessageFilter
{
219 explicit TestFilterSpecifyingChild(ResourceContext
* resource_context
,
221 : ResourceMessageFilter(
223 PROCESS_TYPE_RENDERER
,
229 base::Bind(&TestFilterSpecifyingChild::GetContexts
,
230 base::Unretained(this))),
231 resource_context_(resource_context
),
233 received_after_canceled_(0) {
234 set_peer_process_for_testing(base::Process::Current());
237 void set_canceled(bool canceled
) { canceled_
= canceled
; }
238 int received_after_canceled() const { return received_after_canceled_
; }
240 // ResourceMessageFilter override
241 bool Send(IPC::Message
* msg
) override
{
242 // No messages should be received when the process has been canceled.
244 received_after_canceled_
++;
245 ReleaseHandlesInMessage(*msg
);
250 ResourceContext
* resource_context() { return resource_context_
; }
253 ~TestFilterSpecifyingChild() override
{}
256 void GetContexts(const ResourceHostMsg_Request
& request
,
257 ResourceContext
** resource_context
,
258 net::URLRequestContext
** request_context
) {
259 *resource_context
= resource_context_
;
260 *request_context
= resource_context_
->GetRequestContext();
263 ResourceContext
* resource_context_
;
265 int received_after_canceled_
;
267 DISALLOW_COPY_AND_ASSIGN(TestFilterSpecifyingChild
);
270 class TestFilter
: public TestFilterSpecifyingChild
{
272 explicit TestFilter(ResourceContext
* resource_context
)
273 : TestFilterSpecifyingChild(
275 ChildProcessHostImpl::GenerateChildProcessUniqueId()) {
276 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
280 ~TestFilter() override
{
281 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(child_id());
285 // This class forwards the incoming messages to the ResourceDispatcherHostTest.
286 // For the test, we want all the incoming messages to go to the same place,
287 // which is why this forwards.
288 class ForwardingFilter
: public TestFilter
{
290 explicit ForwardingFilter(IPC::Sender
* dest
,
291 ResourceContext
* resource_context
)
292 : TestFilter(resource_context
),
296 // TestFilter override
297 bool Send(IPC::Message
* msg
) override
{ return dest_
->Send(msg
); }
300 ~ForwardingFilter() override
{}
304 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter
);
307 // This class is a variation on URLRequestTestJob that will call
308 // URLRequest::WillStartUsingNetwork before starting.
309 class URLRequestTestDelayedNetworkJob
: public net::URLRequestTestJob
{
311 URLRequestTestDelayedNetworkJob(net::URLRequest
* request
,
312 net::NetworkDelegate
* network_delegate
)
313 : net::URLRequestTestJob(request
, network_delegate
) {}
315 // Only start if not deferred for network start.
316 void Start() override
{
318 NotifyBeforeNetworkStart(&defer
);
321 net::URLRequestTestJob::Start();
324 void ResumeNetworkStart() override
{ net::URLRequestTestJob::StartAsync(); }
327 ~URLRequestTestDelayedNetworkJob() override
{}
329 DISALLOW_COPY_AND_ASSIGN(URLRequestTestDelayedNetworkJob
);
332 // This class is a variation on URLRequestTestJob in that it does
333 // not complete start upon entry, only when specifically told to.
334 class URLRequestTestDelayedStartJob
: public net::URLRequestTestJob
{
336 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
337 net::NetworkDelegate
* network_delegate
)
338 : net::URLRequestTestJob(request
, network_delegate
) {
341 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
342 net::NetworkDelegate
* network_delegate
,
344 : net::URLRequestTestJob(request
, network_delegate
, auto_advance
) {
347 URLRequestTestDelayedStartJob(net::URLRequest
* request
,
348 net::NetworkDelegate
* network_delegate
,
349 const std::string
& response_headers
,
350 const std::string
& response_data
,
352 : net::URLRequestTestJob(request
,
360 // Do nothing until you're told to.
361 void Start() override
{}
363 // Finish starting a URL request whose job is an instance of
364 // URLRequestTestDelayedStartJob. It is illegal to call this routine
365 // with a URLRequest that does not use URLRequestTestDelayedStartJob.
366 static void CompleteStart(net::URLRequest
* request
) {
367 for (URLRequestTestDelayedStartJob
* job
= list_head_
;
370 if (job
->request() == request
) {
371 job
->net::URLRequestTestJob::Start();
378 static bool DelayedStartQueueEmpty() {
382 static void ClearQueue() {
385 << "Unreleased entries on URLRequestTestDelayedStartJob delay queue"
386 << "; may result in leaks.";
392 ~URLRequestTestDelayedStartJob() override
{
393 for (URLRequestTestDelayedStartJob
** job
= &list_head_
; *job
;
394 job
= &(*job
)->next_
) {
396 *job
= (*job
)->next_
;
409 static URLRequestTestDelayedStartJob
* list_head_
;
410 URLRequestTestDelayedStartJob
* next_
;
413 URLRequestTestDelayedStartJob
*
414 URLRequestTestDelayedStartJob::list_head_
= NULL
;
416 // This class is a variation on URLRequestTestJob in that it
417 // returns IO_pending errors before every read, not just the first one.
418 class URLRequestTestDelayedCompletionJob
: public net::URLRequestTestJob
{
420 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
421 net::NetworkDelegate
* network_delegate
)
422 : net::URLRequestTestJob(request
, network_delegate
) {}
423 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
424 net::NetworkDelegate
* network_delegate
,
426 : net::URLRequestTestJob(request
, network_delegate
, auto_advance
) {}
427 URLRequestTestDelayedCompletionJob(net::URLRequest
* request
,
428 net::NetworkDelegate
* network_delegate
,
429 const std::string
& response_headers
,
430 const std::string
& response_data
,
432 : net::URLRequestTestJob(request
,
439 ~URLRequestTestDelayedCompletionJob() override
{}
442 bool NextReadAsync() override
{ return true; }
445 class URLRequestBigJob
: public net::URLRequestSimpleJob
{
447 URLRequestBigJob(net::URLRequest
* request
,
448 net::NetworkDelegate
* network_delegate
)
449 : net::URLRequestSimpleJob(request
, network_delegate
) {
452 // URLRequestSimpleJob implementation:
453 int GetData(std::string
* mime_type
,
454 std::string
* charset
,
456 const net::CompletionCallback
& callback
) const override
{
457 *mime_type
= "text/plain";
462 if (!ParseURL(request_
->url(), &text
, &count
))
463 return net::ERR_INVALID_URL
;
465 data
->reserve(text
.size() * count
);
466 for (int i
= 0; i
< count
; ++i
)
472 base::TaskRunner
* GetTaskRunner() const override
{
473 return base::ThreadTaskRunnerHandle::Get().get();
477 ~URLRequestBigJob() override
{}
479 // big-job:substring,N
480 static bool ParseURL(const GURL
& url
, std::string
* text
, int* count
) {
481 std::vector
<std::string
> parts
= base::SplitString(
482 url
.path(), ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
484 if (parts
.size() != 2)
488 return base::StringToInt(parts
[1], count
);
492 // URLRequestJob used to test GetLoadInfoForAllRoutes. The LoadState and
493 // UploadProgress values are set for the jobs at the time of creation, and
494 // the jobs will never actually do anything.
495 class URLRequestLoadInfoJob
: public net::URLRequestJob
{
497 URLRequestLoadInfoJob(net::URLRequest
* request
,
498 net::NetworkDelegate
* network_delegate
,
499 const net::LoadState
& load_state
,
500 const net::UploadProgress
& upload_progress
)
501 : net::URLRequestJob(request
, network_delegate
),
502 load_state_(load_state
),
503 upload_progress_(upload_progress
) {}
505 // net::URLRequestJob implementation:
506 void Start() override
{}
507 net::LoadState
GetLoadState() const override
{ return load_state_
; }
508 net::UploadProgress
GetUploadProgress() const override
{
509 return upload_progress_
;
513 ~URLRequestLoadInfoJob() override
{}
515 // big-job:substring,N
516 static bool ParseURL(const GURL
& url
, std::string
* text
, int* count
) {
517 std::vector
<std::string
> parts
= base::SplitString(
518 url
.path(), ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
520 if (parts
.size() != 2)
524 return base::StringToInt(parts
[1], count
);
527 const net::LoadState load_state_
;
528 const net::UploadProgress upload_progress_
;
531 class ResourceDispatcherHostTest
;
533 class TestURLRequestJobFactory
: public net::URLRequestJobFactory
{
535 explicit TestURLRequestJobFactory(ResourceDispatcherHostTest
* test_fixture
)
536 : test_fixture_(test_fixture
),
538 delay_complete_(false),
539 network_start_notification_(false),
540 url_request_jobs_created_count_(0) {
543 void HandleScheme(const std::string
& scheme
) {
544 supported_schemes_
.insert(scheme
);
547 int url_request_jobs_created_count() const {
548 return url_request_jobs_created_count_
;
551 void SetDelayedStartJobGeneration(bool delay_job_start
) {
552 delay_start_
= delay_job_start
;
555 void SetDelayedCompleteJobGeneration(bool delay_job_complete
) {
556 delay_complete_
= delay_job_complete
;
559 void SetNetworkStartNotificationJobGeneration(bool notification
) {
560 network_start_notification_
= notification
;
563 net::URLRequestJob
* MaybeCreateJobWithProtocolHandler(
564 const std::string
& scheme
,
565 net::URLRequest
* request
,
566 net::NetworkDelegate
* network_delegate
) const override
;
568 net::URLRequestJob
* MaybeInterceptRedirect(
569 net::URLRequest
* request
,
570 net::NetworkDelegate
* network_delegate
,
571 const GURL
& location
) const override
;
573 net::URLRequestJob
* MaybeInterceptResponse(
574 net::URLRequest
* request
,
575 net::NetworkDelegate
* network_delegate
) const override
;
577 bool IsHandledProtocol(const std::string
& scheme
) const override
{
578 return supported_schemes_
.count(scheme
) > 0;
581 bool IsHandledURL(const GURL
& url
) const override
{
582 return supported_schemes_
.count(url
.scheme()) > 0;
585 bool IsSafeRedirectTarget(const GURL
& location
) const override
{
590 ResourceDispatcherHostTest
* test_fixture_
;
592 bool delay_complete_
;
593 bool network_start_notification_
;
594 mutable int url_request_jobs_created_count_
;
595 std::set
<std::string
> supported_schemes_
;
597 DISALLOW_COPY_AND_ASSIGN(TestURLRequestJobFactory
);
600 // Associated with an URLRequest to determine if the URLRequest gets deleted.
601 class TestUserData
: public base::SupportsUserData::Data
{
603 explicit TestUserData(bool* was_deleted
)
604 : was_deleted_(was_deleted
) {
607 ~TestUserData() override
{ *was_deleted_
= true; }
613 class TransfersAllNavigationsContentBrowserClient
614 : public TestContentBrowserClient
{
616 bool ShouldSwapProcessesForRedirect(ResourceContext
* resource_context
,
617 const GURL
& current_url
,
618 const GURL
& new_url
) override
{
623 enum GenericResourceThrottleFlags
{
625 DEFER_STARTING_REQUEST
= 1 << 0,
626 DEFER_PROCESSING_RESPONSE
= 1 << 1,
627 CANCEL_BEFORE_START
= 1 << 2,
628 DEFER_NETWORK_START
= 1 << 3
631 // Throttle that tracks the current throttle blocking a request. Only one
632 // can throttle any request at a time.
633 class GenericResourceThrottle
: public ResourceThrottle
{
635 // The value is used to indicate that the throttle should not provide
636 // a error code when cancelling a request. net::OK is used, because this
637 // is not an error code.
638 static const int USE_DEFAULT_CANCEL_ERROR_CODE
= net::OK
;
640 GenericResourceThrottle(int flags
, int code
)
642 error_code_for_cancellation_(code
) {
645 ~GenericResourceThrottle() override
{
646 if (active_throttle_
== this)
647 active_throttle_
= NULL
;
650 // ResourceThrottle implementation:
651 void WillStartRequest(bool* defer
) override
{
652 ASSERT_EQ(NULL
, active_throttle_
);
653 if (flags_
& DEFER_STARTING_REQUEST
) {
654 active_throttle_
= this;
658 if (flags_
& CANCEL_BEFORE_START
) {
659 if (error_code_for_cancellation_
== USE_DEFAULT_CANCEL_ERROR_CODE
) {
660 controller()->Cancel();
662 controller()->CancelWithError(error_code_for_cancellation_
);
667 void WillProcessResponse(bool* defer
) override
{
668 ASSERT_EQ(NULL
, active_throttle_
);
669 if (flags_
& DEFER_PROCESSING_RESPONSE
) {
670 active_throttle_
= this;
675 void WillStartUsingNetwork(bool* defer
) override
{
676 ASSERT_EQ(NULL
, active_throttle_
);
678 if (flags_
& DEFER_NETWORK_START
) {
679 active_throttle_
= this;
684 const char* GetNameForLogging() const override
{
685 return "GenericResourceThrottle";
689 ASSERT_TRUE(this == active_throttle_
);
690 active_throttle_
= NULL
;
691 controller()->Resume();
694 static GenericResourceThrottle
* active_throttle() {
695 return active_throttle_
;
699 int flags_
; // bit-wise union of GenericResourceThrottleFlags.
700 int error_code_for_cancellation_
;
702 // The currently active throttle, if any.
703 static GenericResourceThrottle
* active_throttle_
;
706 GenericResourceThrottle
* GenericResourceThrottle::active_throttle_
= NULL
;
708 class TestResourceDispatcherHostDelegate
709 : public ResourceDispatcherHostDelegate
{
711 TestResourceDispatcherHostDelegate()
712 : create_two_throttles_(false),
714 error_code_for_cancellation_(
715 GenericResourceThrottle::USE_DEFAULT_CANCEL_ERROR_CODE
) {
718 void set_url_request_user_data(base::SupportsUserData::Data
* user_data
) {
719 user_data_
.reset(user_data
);
722 void set_flags(int value
) {
726 void set_error_code_for_cancellation(int code
) {
727 error_code_for_cancellation_
= code
;
730 void set_create_two_throttles(bool create_two_throttles
) {
731 create_two_throttles_
= create_two_throttles
;
734 // ResourceDispatcherHostDelegate implementation:
736 void RequestBeginning(net::URLRequest
* request
,
737 ResourceContext
* resource_context
,
738 AppCacheService
* appcache_service
,
739 ResourceType resource_type
,
740 ScopedVector
<ResourceThrottle
>* throttles
) override
{
742 const void* key
= user_data_
.get();
743 request
->SetUserData(key
, user_data_
.release());
746 if (flags_
!= NONE
) {
747 throttles
->push_back(new GenericResourceThrottle(
748 flags_
, error_code_for_cancellation_
));
749 if (create_two_throttles_
)
750 throttles
->push_back(new GenericResourceThrottle(
751 flags_
, error_code_for_cancellation_
));
756 bool create_two_throttles_
;
758 int error_code_for_cancellation_
;
759 scoped_ptr
<base::SupportsUserData::Data
> user_data_
;
762 // Waits for a ShareableFileReference to be released.
763 class ShareableFileReleaseWaiter
{
765 ShareableFileReleaseWaiter(const base::FilePath
& path
) {
766 scoped_refptr
<ShareableFileReference
> file
=
767 ShareableFileReference::Get(path
);
768 file
->AddFinalReleaseCallback(
769 base::Bind(&ShareableFileReleaseWaiter::Released
,
770 base::Unretained(this)));
778 void Released(const base::FilePath
& path
) {
784 DISALLOW_COPY_AND_ASSIGN(ShareableFileReleaseWaiter
);
787 // For verifying notifications sent to the WebContents by the
788 // ResourceDispatcherHostImpl.
789 class TestWebContentsObserver
: public WebContentsObserver
{
791 TestWebContentsObserver(WebContents
* web_contents
)
792 : WebContentsObserver(web_contents
),
793 resource_request_redirect_count_(0),
794 resource_response_start_count_(0) {}
796 void DidGetRedirectForResourceRequest(
797 RenderFrameHost
* render_frame_host
,
798 const ResourceRedirectDetails
& details
) override
{
799 ++resource_request_redirect_count_
;
802 void DidGetResourceResponseStart(
803 const ResourceRequestDetails
& details
) override
{
804 ++resource_response_start_count_
;
807 int resource_response_start_count() { return resource_response_start_count_
; }
809 int resource_request_redirect_count() {
810 return resource_request_redirect_count_
;
814 int resource_request_redirect_count_
;
815 int resource_response_start_count_
;
818 // Information used to create resource requests that use URLRequestLoadInfoJobs.
819 // The child_id is just that of ResourceDispatcherHostTest::filter_.
820 struct LoadInfoTestRequestInfo
{
823 net::LoadState load_state
;
824 net::UploadProgress upload_progress
;
827 class ResourceDispatcherHostTest
: public testing::Test
,
830 typedef ResourceDispatcherHostImpl::LoadInfo LoadInfo
;
831 typedef ResourceDispatcherHostImpl::LoadInfoMap LoadInfoMap
;
833 ResourceDispatcherHostTest()
834 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
836 send_data_received_acks_(false) {
837 browser_context_
.reset(new TestBrowserContext());
838 BrowserContext::EnsureResourceContextInitialized(browser_context_
.get());
839 base::RunLoop().RunUntilIdle();
840 filter_
= MakeForwardingFilter();
841 // TODO(cbentzel): Better way to get URLRequestContext?
842 net::URLRequestContext
* request_context
=
843 browser_context_
->GetResourceContext()->GetRequestContext();
844 job_factory_
.reset(new TestURLRequestJobFactory(this));
845 request_context
->set_job_factory(job_factory_
.get());
846 request_context
->set_network_delegate(&network_delegate_
);
849 // IPC::Sender implementation
850 bool Send(IPC::Message
* msg
) override
{
851 accum_
.AddMessage(*msg
);
853 if (send_data_received_acks_
&&
854 msg
->type() == ResourceMsg_DataReceived::ID
) {
855 GenerateDataReceivedACK(*msg
);
858 if (wait_for_request_complete_loop_
&&
859 msg
->type() == ResourceMsg_RequestComplete::ID
) {
860 wait_for_request_complete_loop_
->Quit();
863 // Do not release handles in it yet; the accumulator owns them now.
868 scoped_ptr
<LoadInfoMap
> RunLoadInfoTest(LoadInfoTestRequestInfo
* request_info
,
869 size_t num_requests
) {
870 for (size_t i
= 0; i
< num_requests
; ++i
) {
871 loader_test_request_info_
.reset(
872 new LoadInfoTestRequestInfo(request_info
[i
]));
873 wait_for_request_create_loop_
.reset(new base::RunLoop());
874 MakeTestRequest(request_info
[i
].route_id
, i
+ 1, request_info
[i
].url
);
875 wait_for_request_create_loop_
->Run();
876 wait_for_request_create_loop_
.reset();
878 return ResourceDispatcherHostImpl::Get()->GetLoadInfoForAllRoutes();
882 friend class TestURLRequestJobFactory
;
885 void SetUp() override
{
886 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0);
887 HandleScheme("test");
888 scoped_refptr
<SiteInstance
> site_instance
=
889 SiteInstance::Create(browser_context_
.get());
891 WebContents::Create(WebContents::CreateParams(browser_context_
.get())));
892 web_contents_observer_
.reset(
893 new TestWebContentsObserver(web_contents_
.get()));
894 web_contents_filter_
= new TestFilterSpecifyingChild(
895 browser_context_
->GetResourceContext(),
896 web_contents_
->GetRenderProcessHost()->GetID());
897 child_ids_
.insert(web_contents_
->GetRenderProcessHost()->GetID());
900 void TearDown() override
{
901 web_contents_observer_
.reset();
902 web_contents_
.reset();
904 EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty());
905 URLRequestTestDelayedStartJob::ClearQueue();
907 for (std::set
<int>::iterator it
= child_ids_
.begin();
908 it
!= child_ids_
.end(); ++it
) {
909 host_
.CancelRequestsForProcess(*it
);
914 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(0);
916 // Flush the message loop to make application verifiers happy.
917 if (ResourceDispatcherHostImpl::Get())
918 ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(
919 browser_context_
->GetResourceContext());
921 browser_context_
.reset();
922 base::RunLoop().RunUntilIdle();
925 // Creates a new ForwardingFilter and registers it with |child_ids_| so as not
926 // to leak per-child state on test shutdown.
927 ForwardingFilter
* MakeForwardingFilter() {
928 ForwardingFilter
* filter
=
929 new ForwardingFilter(this, browser_context_
->GetResourceContext());
930 child_ids_
.insert(filter
->child_id());
934 // Creates a request using the current test object as the filter and
935 // SubResource as the resource type.
936 void MakeTestRequest(int render_view_id
,
940 // Generates a request using the given filter and resource type.
941 void MakeTestRequestWithResourceType(ResourceMessageFilter
* filter
,
947 void MakeWebContentsAssociatedTestRequest(int request_id
, const GURL
& url
);
949 // Generates a request with the given priority.
950 void MakeTestRequestWithPriority(int render_view_id
,
952 net::RequestPriority priority
);
954 void MakeWebContentsAssociatedDownloadRequest(int request_id
,
957 void CancelRequest(int request_id
);
958 void RendererCancelRequest(int request_id
) {
959 ResourceMessageFilter
* old_filter
= SetFilter(filter_
.get());
960 host_
.OnCancelRequest(request_id
);
961 SetFilter(old_filter
);
964 void CompleteStartRequest(int request_id
);
965 void CompleteStartRequest(ResourceMessageFilter
* filter
, int request_id
);
967 net::TestNetworkDelegate
* network_delegate() { return &network_delegate_
; }
969 void EnsureSchemeIsAllowed(const std::string
& scheme
) {
970 ChildProcessSecurityPolicyImpl
* policy
=
971 ChildProcessSecurityPolicyImpl::GetInstance();
972 if (!policy
->IsWebSafeScheme(scheme
))
973 policy
->RegisterWebSafeScheme(scheme
);
976 // Sets a particular response for any request from now on. To switch back to
977 // the default bahavior, pass an empty |headers|. |headers| should be raw-
978 // formatted (NULLs instead of EOLs).
979 void SetResponse(const std::string
& headers
, const std::string
& data
) {
980 response_headers_
= net::HttpUtil::AssembleRawHeaders(headers
.data(),
982 response_data_
= data
;
984 void SetResponse(const std::string
& headers
) {
985 SetResponse(headers
, std::string());
988 void SendDataReceivedACKs(bool send_acks
) {
989 send_data_received_acks_
= send_acks
;
992 // Intercepts requests for the given protocol.
993 void HandleScheme(const std::string
& scheme
) {
994 job_factory_
->HandleScheme(scheme
);
995 EnsureSchemeIsAllowed(scheme
);
998 void GenerateDataReceivedACK(const IPC::Message
& msg
) {
999 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msg
.type());
1001 int request_id
= -1;
1002 bool result
= base::PickleIterator(msg
).ReadInt(&request_id
);
1004 scoped_ptr
<IPC::Message
> ack(
1005 new ResourceHostMsg_DataReceived_ACK(request_id
));
1007 base::ThreadTaskRunnerHandle::Get()->PostTask(
1009 base::Bind(&GenerateIPCMessage
, filter_
, base::Passed(&ack
)));
1012 // Setting filters for testing renderer messages.
1013 // Returns the previous filter.
1014 ResourceMessageFilter
* SetFilter(ResourceMessageFilter
* new_filter
) {
1015 ResourceMessageFilter
* old_filter
= host_
.filter_
;
1016 host_
.filter_
= new_filter
;
1020 void WaitForRequestComplete() {
1021 DCHECK(!wait_for_request_complete_loop_
);
1022 wait_for_request_complete_loop_
.reset(new base::RunLoop
);
1023 wait_for_request_complete_loop_
->Run();
1024 wait_for_request_complete_loop_
.reset();
1027 scoped_ptr
<LoadInfoTestRequestInfo
> loader_test_request_info_
;
1028 scoped_ptr
<base::RunLoop
> wait_for_request_create_loop_
;
1030 content::TestBrowserThreadBundle thread_bundle_
;
1031 scoped_ptr
<TestBrowserContext
> browser_context_
;
1032 scoped_ptr
<TestURLRequestJobFactory
> job_factory_
;
1033 scoped_ptr
<WebContents
> web_contents_
;
1034 scoped_ptr
<TestWebContentsObserver
> web_contents_observer_
;
1035 scoped_refptr
<ForwardingFilter
> filter_
;
1036 scoped_refptr
<TestFilterSpecifyingChild
> web_contents_filter_
;
1037 net::TestNetworkDelegate network_delegate_
;
1038 ResourceDispatcherHostImpl host_
;
1039 ResourceIPCAccumulator accum_
;
1040 std::string response_headers_
;
1041 std::string response_data_
;
1042 std::string scheme_
;
1043 net::URLRequest::ProtocolFactory
* old_factory_
;
1044 bool send_data_received_acks_
;
1045 std::set
<int> child_ids_
;
1046 scoped_ptr
<base::RunLoop
> wait_for_request_complete_loop_
;
1047 RenderViewHostTestEnabler render_view_host_test_enabler_
;
1050 void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id
,
1053 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
1054 url
, RESOURCE_TYPE_SUB_RESOURCE
);
1057 void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
1058 ResourceMessageFilter
* filter
,
1062 ResourceType type
) {
1063 ResourceHostMsg_Request request
=
1064 CreateResourceRequest("GET", type
, url
);
1065 ResourceHostMsg_RequestResource
msg(render_view_id
, request_id
, request
);
1066 host_
.OnMessageReceived(msg
, filter
);
1070 void ResourceDispatcherHostTest::MakeWebContentsAssociatedTestRequest(
1073 ResourceHostMsg_Request request
=
1074 CreateResourceRequest("GET", RESOURCE_TYPE_SUB_RESOURCE
, url
);
1075 request
.origin_pid
= web_contents_
->GetRenderProcessHost()->GetID();
1076 request
.render_frame_id
= web_contents_
->GetMainFrame()->GetRoutingID();
1077 ResourceHostMsg_RequestResource
msg(web_contents_
->GetRoutingID(), request_id
,
1079 host_
.OnMessageReceived(msg
, web_contents_filter_
.get());
1083 void ResourceDispatcherHostTest::MakeTestRequestWithPriority(
1086 net::RequestPriority priority
) {
1087 ResourceHostMsg_Request request
= CreateResourceRequest(
1088 "GET", RESOURCE_TYPE_SUB_RESOURCE
, GURL("http://example.com/priority"));
1089 request
.priority
= priority
;
1090 ResourceHostMsg_RequestResource
msg(render_view_id
, request_id
, request
);
1091 host_
.OnMessageReceived(msg
, filter_
.get());
1094 void ResourceDispatcherHostTest::MakeWebContentsAssociatedDownloadRequest(
1097 scoped_ptr
<DownloadSaveInfo
> save_info(new DownloadSaveInfo());
1098 save_info
->prompt_for_save_location
= false;
1099 net::URLRequestContext
* request_context
=
1100 browser_context_
->GetResourceContext()->GetRequestContext();
1101 scoped_ptr
<net::URLRequest
> request(
1102 request_context
->CreateRequest(url
, net::DEFAULT_PRIORITY
, NULL
));
1103 host_
.BeginDownload(
1106 false, // is_content_initiated
1107 browser_context_
->GetResourceContext(),
1108 web_contents_
->GetRenderProcessHost()->GetID(),
1109 web_contents_
->GetRoutingID(),
1110 web_contents_
->GetMainFrame()->GetRoutingID(),
1114 DownloadItem::kInvalidId
,
1115 ResourceDispatcherHostImpl::DownloadStartedCallback());
1118 void ResourceDispatcherHostTest::CancelRequest(int request_id
) {
1119 host_
.CancelRequest(filter_
->child_id(), request_id
);
1122 void ResourceDispatcherHostTest::CompleteStartRequest(int request_id
) {
1123 CompleteStartRequest(filter_
.get(), request_id
);
1126 void ResourceDispatcherHostTest::CompleteStartRequest(
1127 ResourceMessageFilter
* filter
,
1129 GlobalRequestID
gid(filter
->child_id(), request_id
);
1130 net::URLRequest
* req
= host_
.GetURLRequest(gid
);
1133 URLRequestTestDelayedStartJob::CompleteStart(req
);
1136 void CheckRequestCompleteErrorCode(const IPC::Message
& message
,
1137 int expected_error_code
) {
1138 // Verify the expected error code was received.
1142 ASSERT_EQ(ResourceMsg_RequestComplete::ID
, message
.type());
1144 base::PickleIterator
iter(message
);
1145 ASSERT_TRUE(IPC::ReadParam(&message
, &iter
, &request_id
));
1146 ASSERT_TRUE(IPC::ReadParam(&message
, &iter
, &error_code
));
1147 ASSERT_EQ(expected_error_code
, error_code
);
1150 testing::AssertionResult
ExtractDataOffsetAndLength(const IPC::Message
& message
,
1153 base::PickleIterator
iter(message
);
1155 if (!IPC::ReadParam(&message
, &iter
, &request_id
))
1156 return testing::AssertionFailure() << "Could not read request_id";
1157 // TODO(erikchen): This dummy variable is temporary and is only intended to be
1158 // present for one Canary release. http://crbug.com/527588.
1160 if (!IPC::ReadParam(&message
, &iter
, &dummy
))
1161 return testing::AssertionFailure() << "Could not read dummy variable";
1162 if (!IPC::ReadParam(&message
, &iter
, data_offset
))
1163 return testing::AssertionFailure() << "Could not read data_offset";
1164 if (!IPC::ReadParam(&message
, &iter
, data_length
))
1165 return testing::AssertionFailure() << "Could not read data_length";
1166 return testing::AssertionSuccess();
1169 void CheckSuccessfulRequestWithErrorCode(
1170 const std::vector
<IPC::Message
>& messages
,
1171 const std::string
& reference_data
,
1172 int expected_error
) {
1173 // A successful request will have received 4 messages:
1174 // ReceivedResponse (indicates headers received)
1175 // SetDataBuffer (contains shared memory handle)
1176 // DataReceived (data offset and length into shared memory)
1177 // RequestComplete (request is done)
1179 // This function verifies that we received 4 messages and that they are
1180 // appropriate. It allows for an error code other than net::OK if the request
1181 // should successfully receive data and then abort, e.g., on cancel.
1182 ASSERT_EQ(4U, messages
.size());
1184 // The first messages should be received response
1185 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
1187 ASSERT_EQ(ResourceMsg_SetDataBuffer::ID
, messages
[1].type());
1189 base::PickleIterator
iter(messages
[1]);
1191 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &request_id
));
1192 base::SharedMemoryHandle shm_handle
;
1193 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &shm_handle
));
1195 ASSERT_TRUE(IPC::ReadParam(&messages
[1], &iter
, &shm_size
));
1197 // Followed by the data, currently we only do the data in one chunk, but
1198 // should probably test multiple chunks later
1199 ASSERT_EQ(ResourceMsg_DataReceived::ID
, messages
[2].type());
1204 ExtractDataOffsetAndLength(messages
[2], &data_offset
, &data_length
));
1206 ASSERT_EQ(reference_data
.size(), static_cast<size_t>(data_length
));
1207 ASSERT_GE(shm_size
, data_length
);
1209 base::SharedMemory
shared_mem(shm_handle
, true); // read only
1210 shared_mem
.Map(data_length
);
1211 const char* data
= static_cast<char*>(shared_mem
.memory()) + data_offset
;
1212 ASSERT_EQ(0, memcmp(reference_data
.c_str(), data
, data_length
));
1214 // The last message should be all data received.
1215 CheckRequestCompleteErrorCode(messages
[3], expected_error
);
1218 void CheckSuccessfulRequest(const std::vector
<IPC::Message
>& messages
,
1219 const std::string
& reference_data
) {
1220 CheckSuccessfulRequestWithErrorCode(messages
, reference_data
, net::OK
);
1223 void CheckSuccessfulRedirect(const std::vector
<IPC::Message
>& messages
,
1224 const std::string
& reference_data
) {
1225 ASSERT_EQ(5U, messages
.size());
1226 ASSERT_EQ(ResourceMsg_ReceivedRedirect::ID
, messages
[0].type());
1228 const std::vector
<IPC::Message
> second_req_msgs
=
1229 std::vector
<IPC::Message
>(messages
.begin() + 1, messages
.end());
1230 CheckSuccessfulRequest(second_req_msgs
, reference_data
);
1233 void CheckFailedRequest(const std::vector
<IPC::Message
>& messages
,
1234 const std::string
& reference_data
,
1235 int expected_error
) {
1236 ASSERT_LT(0U, messages
.size());
1237 ASSERT_GE(2U, messages
.size());
1238 size_t failure_index
= messages
.size() - 1;
1240 if (messages
.size() == 2) {
1241 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, messages
[0].type());
1244 CheckRequestCompleteErrorCode(messages
[failure_index
], expected_error
);
1247 // Tests whether many messages get dispatched properly.
1248 TEST_F(ResourceDispatcherHostTest
, TestMany
) {
1249 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1250 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1251 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1252 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
1253 net::URLRequestTestJob::test_url_4(),
1254 RESOURCE_TYPE_PREFETCH
); // detachable type
1255 MakeTestRequest(0, 5, net::URLRequestTestJob::test_url_redirect_to_url_2());
1257 // Finish the redirection
1258 ResourceHostMsg_FollowRedirect
redirect_msg(5);
1259 host_
.OnMessageReceived(redirect_msg
, filter_
.get());
1260 base::MessageLoop::current()->RunUntilIdle();
1262 // flush all the pending requests
1263 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1265 // sorts out all the messages we saw by request
1266 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1267 accum_
.GetClassifiedMessages(&msgs
);
1269 // there are five requests, so we should have gotten them classified as such
1270 ASSERT_EQ(5U, msgs
.size());
1272 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1273 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_2());
1274 CheckSuccessfulRequest(msgs
[2], net::URLRequestTestJob::test_data_3());
1275 CheckSuccessfulRequest(msgs
[3], net::URLRequestTestJob::test_data_4());
1276 CheckSuccessfulRedirect(msgs
[4], net::URLRequestTestJob::test_data_2());
1279 // Tests whether messages get canceled properly. We issue four requests,
1280 // cancel two of them, and make sure that each sent the proper notifications.
1281 TEST_F(ResourceDispatcherHostTest
, Cancel
) {
1282 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1283 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1284 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1286 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
1287 net::URLRequestTestJob::test_url_4(),
1288 RESOURCE_TYPE_PREFETCH
); // detachable type
1292 // Cancel request must come from the renderer for a detachable resource to
1294 RendererCancelRequest(4);
1296 // The handler should have been detached now.
1297 GlobalRequestID
global_request_id(filter_
->child_id(), 4);
1298 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1299 host_
.GetURLRequest(global_request_id
));
1300 ASSERT_TRUE(info
->detachable_handler()->is_detached());
1302 // flush all the pending requests
1303 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1304 base::MessageLoop::current()->RunUntilIdle();
1306 // Everything should be out now.
1307 EXPECT_EQ(0, host_
.pending_requests());
1309 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1310 accum_
.GetClassifiedMessages(&msgs
);
1312 // there are four requests, so we should have gotten them classified as such
1313 ASSERT_EQ(4U, msgs
.size());
1315 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1316 CheckSuccessfulRequest(msgs
[2], net::URLRequestTestJob::test_data_3());
1318 // Check that request 2 and 4 got canceled, as far as the renderer is
1319 // concerned. Request 2 will have been deleted.
1320 ASSERT_EQ(1U, msgs
[1].size());
1321 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[1][0].type());
1323 ASSERT_EQ(2U, msgs
[3].size());
1324 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[3][0].type());
1325 CheckRequestCompleteErrorCode(msgs
[3][1], net::ERR_ABORTED
);
1327 // However, request 4 should have actually gone to completion. (Only request 2
1329 EXPECT_EQ(4, network_delegate()->completed_requests());
1330 EXPECT_EQ(1, network_delegate()->canceled_requests());
1331 EXPECT_EQ(0, network_delegate()->error_count());
1334 // Shows that detachable requests will timeout if the request takes too long to
1336 TEST_F(ResourceDispatcherHostTest
, DetachedResourceTimesOut
) {
1337 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1338 net::URLRequestTestJob::test_url_2(),
1339 RESOURCE_TYPE_PREFETCH
); // detachable type
1340 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1341 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1342 host_
.GetURLRequest(global_request_id
));
1343 ASSERT_TRUE(info
->detachable_handler());
1344 info
->detachable_handler()->set_cancel_delay(
1345 base::TimeDelta::FromMilliseconds(200));
1346 base::MessageLoop::current()->RunUntilIdle();
1348 RendererCancelRequest(1);
1350 // From the renderer's perspective, the request was cancelled.
1351 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1352 accum_
.GetClassifiedMessages(&msgs
);
1353 ASSERT_EQ(1U, msgs
.size());
1354 ASSERT_EQ(2U, msgs
[0].size());
1355 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
1356 CheckRequestCompleteErrorCode(msgs
[0][1], net::ERR_ABORTED
);
1358 // But it continues detached.
1359 EXPECT_EQ(1, host_
.pending_requests());
1360 EXPECT_TRUE(info
->detachable_handler()->is_detached());
1362 // Wait until after the delay timer times out before we start processing any
1364 base::OneShotTimer
<base::MessageLoop
> timer
;
1365 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(210),
1366 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle
);
1367 base::MessageLoop::current()->Run();
1369 // The prefetch should be cancelled by now.
1370 EXPECT_EQ(0, host_
.pending_requests());
1371 EXPECT_EQ(1, network_delegate()->completed_requests());
1372 EXPECT_EQ(1, network_delegate()->canceled_requests());
1373 EXPECT_EQ(0, network_delegate()->error_count());
1376 // If the filter has disappeared then detachable resources should continue to
1378 TEST_F(ResourceDispatcherHostTest
, DeletedFilterDetached
) {
1379 // test_url_1's data is available synchronously, so use 2 and 3.
1380 ResourceHostMsg_Request request_prefetch
= CreateResourceRequest(
1381 "GET", RESOURCE_TYPE_PREFETCH
, net::URLRequestTestJob::test_url_2());
1382 ResourceHostMsg_Request request_ping
= CreateResourceRequest(
1383 "GET", RESOURCE_TYPE_PING
, net::URLRequestTestJob::test_url_3());
1385 ResourceHostMsg_RequestResource
msg_prefetch(0, 1, request_prefetch
);
1386 host_
.OnMessageReceived(msg_prefetch
, filter_
.get());
1387 ResourceHostMsg_RequestResource
msg_ping(0, 2, request_ping
);
1388 host_
.OnMessageReceived(msg_ping
, filter_
.get());
1390 // Remove the filter before processing the requests by simulating channel
1392 ResourceRequestInfoImpl
* info_prefetch
= ResourceRequestInfoImpl::ForRequest(
1393 host_
.GetURLRequest(GlobalRequestID(filter_
->child_id(), 1)));
1394 ResourceRequestInfoImpl
* info_ping
= ResourceRequestInfoImpl::ForRequest(
1395 host_
.GetURLRequest(GlobalRequestID(filter_
->child_id(), 2)));
1396 DCHECK_EQ(filter_
.get(), info_prefetch
->filter());
1397 DCHECK_EQ(filter_
.get(), info_ping
->filter());
1398 filter_
->OnChannelClosing();
1399 info_prefetch
->filter_
.reset();
1400 info_ping
->filter_
.reset();
1402 // From the renderer's perspective, the requests were cancelled.
1403 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1404 accum_
.GetClassifiedMessages(&msgs
);
1405 ASSERT_EQ(2U, msgs
.size());
1406 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1407 CheckRequestCompleteErrorCode(msgs
[1][0], net::ERR_ABORTED
);
1409 // But it continues detached.
1410 EXPECT_EQ(2, host_
.pending_requests());
1411 EXPECT_TRUE(info_prefetch
->detachable_handler()->is_detached());
1412 EXPECT_TRUE(info_ping
->detachable_handler()->is_detached());
1416 // Make sure the requests weren't canceled early.
1417 EXPECT_EQ(2, host_
.pending_requests());
1419 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1420 base::MessageLoop::current()->RunUntilIdle();
1422 EXPECT_EQ(0, host_
.pending_requests());
1423 EXPECT_EQ(2, network_delegate()->completed_requests());
1424 EXPECT_EQ(0, network_delegate()->canceled_requests());
1425 EXPECT_EQ(0, network_delegate()->error_count());
1428 // If the filter has disappeared (original process dies) then detachable
1429 // resources should continue to load, even when redirected.
1430 TEST_F(ResourceDispatcherHostTest
, DeletedFilterDetachedRedirect
) {
1431 ResourceHostMsg_Request request
= CreateResourceRequest(
1432 "GET", RESOURCE_TYPE_PREFETCH
,
1433 net::URLRequestTestJob::test_url_redirect_to_url_2());
1435 ResourceHostMsg_RequestResource
msg(0, 1, request
);
1436 host_
.OnMessageReceived(msg
, filter_
.get());
1438 // Remove the filter before processing the request by simulating channel
1440 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1441 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1442 host_
.GetURLRequest(global_request_id
));
1443 info
->filter_
->OnChannelClosing();
1444 info
->filter_
.reset();
1446 // From the renderer's perspective, the request was cancelled.
1447 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1448 accum_
.GetClassifiedMessages(&msgs
);
1449 ASSERT_EQ(1U, msgs
.size());
1450 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1452 // But it continues detached.
1453 EXPECT_EQ(1, host_
.pending_requests());
1454 EXPECT_TRUE(info
->detachable_handler()->is_detached());
1456 // Verify no redirects before resetting the filter.
1457 net::URLRequest
* url_request
= host_
.GetURLRequest(global_request_id
);
1458 EXPECT_EQ(1u, url_request
->url_chain().size());
1461 // Verify that a redirect was followed.
1462 EXPECT_EQ(2u, url_request
->url_chain().size());
1464 // Make sure the request wasn't canceled early.
1465 EXPECT_EQ(1, host_
.pending_requests());
1467 // Finish up the request.
1468 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1469 base::MessageLoop::current()->RunUntilIdle();
1471 EXPECT_EQ(0, host_
.pending_requests());
1472 EXPECT_EQ(1, network_delegate()->completed_requests());
1473 EXPECT_EQ(0, network_delegate()->canceled_requests());
1474 EXPECT_EQ(0, network_delegate()->error_count());
1477 TEST_F(ResourceDispatcherHostTest
, CancelWhileStartIsDeferred
) {
1478 bool was_deleted
= false;
1480 // Arrange to have requests deferred before starting.
1481 TestResourceDispatcherHostDelegate delegate
;
1482 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1483 delegate
.set_url_request_user_data(new TestUserData(&was_deleted
));
1484 host_
.SetDelegate(&delegate
);
1486 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1487 // We cancel from the renderer because all non-renderer cancels delete
1488 // the request synchronously.
1489 RendererCancelRequest(1);
1491 // Our TestResourceThrottle should not have been deleted yet. This is to
1492 // ensure that destruction of the URLRequest happens asynchronously to
1493 // calling CancelRequest.
1494 EXPECT_FALSE(was_deleted
);
1496 base::MessageLoop::current()->RunUntilIdle();
1498 EXPECT_TRUE(was_deleted
);
1501 TEST_F(ResourceDispatcherHostTest
, DetachWhileStartIsDeferred
) {
1502 bool was_deleted
= false;
1504 // Arrange to have requests deferred before starting.
1505 TestResourceDispatcherHostDelegate delegate
;
1506 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1507 delegate
.set_url_request_user_data(new TestUserData(&was_deleted
));
1508 host_
.SetDelegate(&delegate
);
1510 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1511 net::URLRequestTestJob::test_url_1(),
1512 RESOURCE_TYPE_PREFETCH
); // detachable type
1513 // Cancel request must come from the renderer for a detachable resource to
1515 RendererCancelRequest(1);
1517 // Even after driving the event loop, the request has not been deleted.
1518 EXPECT_FALSE(was_deleted
);
1520 // However, it is still throttled because the defer happened above the
1521 // DetachableResourceHandler.
1522 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1523 base::MessageLoop::current()->RunUntilIdle();
1524 EXPECT_FALSE(was_deleted
);
1526 // Resume the request.
1527 GenericResourceThrottle
* throttle
=
1528 GenericResourceThrottle::active_throttle();
1529 ASSERT_TRUE(throttle
);
1532 // Now, the request completes.
1533 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1534 base::MessageLoop::current()->RunUntilIdle();
1535 EXPECT_TRUE(was_deleted
);
1536 EXPECT_EQ(1, network_delegate()->completed_requests());
1537 EXPECT_EQ(0, network_delegate()->canceled_requests());
1538 EXPECT_EQ(0, network_delegate()->error_count());
1541 // Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
1542 // URLRequest will not be started.
1543 TEST_F(ResourceDispatcherHostTest
, CancelInResourceThrottleWillStartRequest
) {
1544 TestResourceDispatcherHostDelegate delegate
;
1545 delegate
.set_flags(CANCEL_BEFORE_START
);
1546 host_
.SetDelegate(&delegate
);
1548 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1550 // flush all the pending requests
1551 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1552 base::MessageLoop::current()->RunUntilIdle();
1554 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1555 accum_
.GetClassifiedMessages(&msgs
);
1557 // Check that request got canceled.
1558 ASSERT_EQ(1U, msgs
[0].size());
1559 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ABORTED
);
1561 // Make sure URLRequest is never started.
1562 EXPECT_EQ(0, job_factory_
->url_request_jobs_created_count());
1565 TEST_F(ResourceDispatcherHostTest
, PausedStartError
) {
1566 // Arrange to have requests deferred before processing response headers.
1567 TestResourceDispatcherHostDelegate delegate
;
1568 delegate
.set_flags(DEFER_PROCESSING_RESPONSE
);
1569 host_
.SetDelegate(&delegate
);
1571 job_factory_
->SetDelayedStartJobGeneration(true);
1572 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_error());
1573 CompleteStartRequest(1);
1575 // flush all the pending requests
1576 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1577 base::MessageLoop::current()->RunUntilIdle();
1579 EXPECT_EQ(0, host_
.pending_requests());
1582 // Test the WillStartUsingNetwork throttle.
1583 TEST_F(ResourceDispatcherHostTest
, ThrottleNetworkStart
) {
1584 // Arrange to have requests deferred before processing response headers.
1585 TestResourceDispatcherHostDelegate delegate
;
1586 delegate
.set_flags(DEFER_NETWORK_START
);
1587 host_
.SetDelegate(&delegate
);
1589 job_factory_
->SetNetworkStartNotificationJobGeneration(true);
1590 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_2());
1592 // Should have deferred for network start.
1593 GenericResourceThrottle
* first_throttle
=
1594 GenericResourceThrottle::active_throttle();
1595 ASSERT_TRUE(first_throttle
);
1596 EXPECT_EQ(0, network_delegate()->completed_requests());
1597 EXPECT_EQ(1, host_
.pending_requests());
1599 first_throttle
->Resume();
1601 // Flush all the pending requests.
1602 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1603 base::MessageLoop::current()->RunUntilIdle();
1605 EXPECT_EQ(1, network_delegate()->completed_requests());
1606 EXPECT_EQ(0, host_
.pending_requests());
1609 TEST_F(ResourceDispatcherHostTest
, ThrottleAndResumeTwice
) {
1610 // Arrange to have requests deferred before starting.
1611 TestResourceDispatcherHostDelegate delegate
;
1612 delegate
.set_flags(DEFER_STARTING_REQUEST
);
1613 delegate
.set_create_two_throttles(true);
1614 host_
.SetDelegate(&delegate
);
1616 // Make sure the first throttle blocked the request, and then resume.
1617 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1618 GenericResourceThrottle
* first_throttle
=
1619 GenericResourceThrottle::active_throttle();
1620 ASSERT_TRUE(first_throttle
);
1621 first_throttle
->Resume();
1623 // Make sure the second throttle blocked the request, and then resume.
1624 ASSERT_TRUE(GenericResourceThrottle::active_throttle());
1625 ASSERT_NE(first_throttle
, GenericResourceThrottle::active_throttle());
1626 GenericResourceThrottle::active_throttle()->Resume();
1628 ASSERT_FALSE(GenericResourceThrottle::active_throttle());
1630 // The request is started asynchronously.
1631 base::MessageLoop::current()->RunUntilIdle();
1633 // Flush all the pending requests.
1634 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1636 EXPECT_EQ(0, host_
.pending_requests());
1638 // Make sure the request completed successfully.
1639 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1640 accum_
.GetClassifiedMessages(&msgs
);
1641 ASSERT_EQ(1U, msgs
.size());
1642 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1646 // Tests that the delegate can cancel a request and provide a error code.
1647 TEST_F(ResourceDispatcherHostTest
, CancelInDelegate
) {
1648 TestResourceDispatcherHostDelegate delegate
;
1649 delegate
.set_flags(CANCEL_BEFORE_START
);
1650 delegate
.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED
);
1651 host_
.SetDelegate(&delegate
);
1653 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1654 // The request will get cancelled by the throttle.
1656 // flush all the pending requests
1657 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1658 base::MessageLoop::current()->RunUntilIdle();
1660 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1661 accum_
.GetClassifiedMessages(&msgs
);
1663 // Check the cancellation
1664 ASSERT_EQ(1U, msgs
.size());
1665 ASSERT_EQ(1U, msgs
[0].size());
1667 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_ACCESS_DENIED
);
1670 // Tests CancelRequestsForProcess
1671 TEST_F(ResourceDispatcherHostTest
, TestProcessCancel
) {
1672 scoped_refptr
<TestFilter
> test_filter
= new TestFilter(
1673 browser_context_
->GetResourceContext());
1674 child_ids_
.insert(test_filter
->child_id());
1676 // request 1 goes to the test delegate
1677 ResourceHostMsg_Request request
= CreateResourceRequest(
1678 "GET", RESOURCE_TYPE_SUB_RESOURCE
, net::URLRequestTestJob::test_url_1());
1680 MakeTestRequestWithResourceType(test_filter
.get(), 0, 1,
1681 net::URLRequestTestJob::test_url_1(),
1682 RESOURCE_TYPE_SUB_RESOURCE
);
1684 // request 2 goes to us
1685 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1687 // request 3 goes to the test delegate
1688 MakeTestRequestWithResourceType(test_filter
.get(), 0, 3,
1689 net::URLRequestTestJob::test_url_3(),
1690 RESOURCE_TYPE_SUB_RESOURCE
);
1692 // request 4 goes to us
1693 MakeTestRequestWithResourceType(filter_
.get(), 0, 4,
1694 net::URLRequestTestJob::test_url_4(),
1695 RESOURCE_TYPE_PREFETCH
); // detachable type
1698 // Make sure all requests have finished stage one. test_url_1 will have
1700 base::MessageLoop::current()->RunUntilIdle();
1703 // Now that the async IO path is in place, the IO always completes on the
1704 // initial call; so the requests have already completed. This basically
1705 // breaks the whole test.
1706 //EXPECT_EQ(3, host_.pending_requests());
1708 // Process test_url_2 and test_url_3 for one level so one callback is called.
1709 // We'll cancel test_url_4 (detachable) before processing it to verify that it
1710 // delays the cancel.
1711 for (int i
= 0; i
< 2; i
++)
1712 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
1714 // Cancel the requests to the test process.
1715 host_
.CancelRequestsForProcess(filter_
->child_id());
1716 test_filter
->set_canceled(true);
1718 // The requests should all be cancelled, except request 4, which is detached.
1719 EXPECT_EQ(1, host_
.pending_requests());
1720 GlobalRequestID
global_request_id(filter_
->child_id(), 4);
1721 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1722 host_
.GetURLRequest(global_request_id
));
1723 ASSERT_TRUE(info
->detachable_handler()->is_detached());
1725 // Flush all the pending requests.
1726 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1728 EXPECT_EQ(0, host_
.pending_requests());
1730 // The test delegate should not have gotten any messages after being canceled.
1731 ASSERT_EQ(0, test_filter
->received_after_canceled());
1733 // There should be two results.
1734 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1735 accum_
.GetClassifiedMessages(&msgs
);
1736 ASSERT_EQ(2U, msgs
.size());
1737 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1738 // The detachable request was cancelled by the renderer before it
1739 // finished. From the perspective of the renderer, it should have cancelled.
1740 ASSERT_EQ(2U, msgs
[1].size());
1741 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[1][0].type());
1742 CheckRequestCompleteErrorCode(msgs
[1][1], net::ERR_ABORTED
);
1743 // But it completed anyway. For the network stack, no requests were canceled.
1744 EXPECT_EQ(4, network_delegate()->completed_requests());
1745 EXPECT_EQ(0, network_delegate()->canceled_requests());
1746 EXPECT_EQ(0, network_delegate()->error_count());
1749 TEST_F(ResourceDispatcherHostTest
, TestProcessCancelDetachedTimesOut
) {
1750 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1751 net::URLRequestTestJob::test_url_4(),
1752 RESOURCE_TYPE_PREFETCH
); // detachable type
1753 GlobalRequestID
global_request_id(filter_
->child_id(), 1);
1754 ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
1755 host_
.GetURLRequest(global_request_id
));
1756 ASSERT_TRUE(info
->detachable_handler());
1757 info
->detachable_handler()->set_cancel_delay(
1758 base::TimeDelta::FromMilliseconds(200));
1759 base::MessageLoop::current()->RunUntilIdle();
1761 // Cancel the requests to the test process.
1762 host_
.CancelRequestsForProcess(filter_
->child_id());
1763 EXPECT_EQ(1, host_
.pending_requests());
1765 // Wait until after the delay timer times out before we start processing any
1767 base::OneShotTimer
<base::MessageLoop
> timer
;
1768 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(210),
1769 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle
);
1770 base::MessageLoop::current()->Run();
1772 // The prefetch should be cancelled by now.
1773 EXPECT_EQ(0, host_
.pending_requests());
1775 // In case any messages are still to be processed.
1776 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1777 base::MessageLoop::current()->RunUntilIdle();
1779 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1780 accum_
.GetClassifiedMessages(&msgs
);
1782 ASSERT_EQ(1U, msgs
.size());
1784 // The request should have cancelled.
1785 ASSERT_EQ(2U, msgs
[0].size());
1786 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
1787 CheckRequestCompleteErrorCode(msgs
[0][1], net::ERR_ABORTED
);
1788 // And not run to completion.
1789 EXPECT_EQ(1, network_delegate()->completed_requests());
1790 EXPECT_EQ(1, network_delegate()->canceled_requests());
1791 EXPECT_EQ(0, network_delegate()->error_count());
1794 // Tests blocking and resuming requests.
1795 TEST_F(ResourceDispatcherHostTest
, TestBlockingResumingRequests
) {
1796 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1797 host_
.BlockRequestsForRoute(filter_
->child_id(), 2);
1798 host_
.BlockRequestsForRoute(filter_
->child_id(), 3);
1800 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1801 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1802 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1803 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1804 MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
1805 MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
1807 // Flush all the pending requests
1808 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1810 // Sort out all the messages we saw by request
1811 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1812 accum_
.GetClassifiedMessages(&msgs
);
1814 // All requests but the 2 for the RVH 0 should have been blocked.
1815 ASSERT_EQ(2U, msgs
.size());
1817 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1818 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1820 // Resume requests for RVH 1 and flush pending requests.
1821 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 1);
1823 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1826 accum_
.GetClassifiedMessages(&msgs
);
1827 ASSERT_EQ(2U, msgs
.size());
1828 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1829 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_1());
1831 // Test that new requests are not blocked for RVH 1.
1832 MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
1833 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1835 accum_
.GetClassifiedMessages(&msgs
);
1836 ASSERT_EQ(1U, msgs
.size());
1837 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1839 // Now resumes requests for all RVH (2 and 3).
1840 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 2);
1841 host_
.ResumeBlockedRequestsForRoute(filter_
->child_id(), 3);
1843 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1846 accum_
.GetClassifiedMessages(&msgs
);
1847 ASSERT_EQ(2U, msgs
.size());
1848 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_2());
1849 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1852 // Tests blocking and canceling requests.
1853 TEST_F(ResourceDispatcherHostTest
, TestBlockingCancelingRequests
) {
1854 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1856 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1857 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1858 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1859 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1860 // Blocked detachable resources should not delay cancellation.
1861 MakeTestRequestWithResourceType(filter_
.get(), 1, 5,
1862 net::URLRequestTestJob::test_url_4(),
1863 RESOURCE_TYPE_PREFETCH
); // detachable type
1865 // Flush all the pending requests.
1866 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1868 // Sort out all the messages we saw by request.
1869 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1870 accum_
.GetClassifiedMessages(&msgs
);
1872 // The 2 requests for the RVH 0 should have been processed.
1873 ASSERT_EQ(2U, msgs
.size());
1875 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1876 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1878 // Cancel requests for RVH 1.
1879 host_
.CancelBlockedRequestsForRoute(filter_
->child_id(), 1);
1881 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1884 accum_
.GetClassifiedMessages(&msgs
);
1885 ASSERT_EQ(0U, msgs
.size());
1888 // Tests that blocked requests are canceled if their associated process dies.
1889 TEST_F(ResourceDispatcherHostTest
, TestBlockedRequestsProcessDies
) {
1890 // This second filter is used to emulate a second process.
1891 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
1893 host_
.BlockRequestsForRoute(second_filter
->child_id(), 0);
1895 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1896 net::URLRequestTestJob::test_url_1(),
1897 RESOURCE_TYPE_SUB_RESOURCE
);
1898 MakeTestRequestWithResourceType(second_filter
.get(), 0, 2,
1899 net::URLRequestTestJob::test_url_2(),
1900 RESOURCE_TYPE_SUB_RESOURCE
);
1901 MakeTestRequestWithResourceType(filter_
.get(), 0, 3,
1902 net::URLRequestTestJob::test_url_3(),
1903 RESOURCE_TYPE_SUB_RESOURCE
);
1904 MakeTestRequestWithResourceType(second_filter
.get(), 0, 4,
1905 net::URLRequestTestJob::test_url_1(),
1906 RESOURCE_TYPE_SUB_RESOURCE
);
1907 MakeTestRequestWithResourceType(second_filter
.get(), 0, 5,
1908 net::URLRequestTestJob::test_url_4(),
1909 RESOURCE_TYPE_PREFETCH
); // detachable type
1911 // Simulate process death.
1912 host_
.CancelRequestsForProcess(second_filter
->child_id());
1914 // Flush all the pending requests.
1915 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1917 // Sort out all the messages we saw by request.
1918 ResourceIPCAccumulator::ClassifiedMessages msgs
;
1919 accum_
.GetClassifiedMessages(&msgs
);
1921 // The 2 requests for the RVH 0 should have been processed. Note that
1922 // blocked detachable requests are canceled without delay.
1923 ASSERT_EQ(2U, msgs
.size());
1925 CheckSuccessfulRequest(msgs
[0], net::URLRequestTestJob::test_data_1());
1926 CheckSuccessfulRequest(msgs
[1], net::URLRequestTestJob::test_data_3());
1928 EXPECT_TRUE(host_
.blocked_loaders_map_
.empty());
1931 // Tests that blocked requests don't leak when the ResourceDispatcherHost goes
1932 // away. Note that we rely on Purify for finding the leaks if any.
1933 // If this test turns the Purify bot red, check the ResourceDispatcherHost
1934 // destructor to make sure the blocked requests are deleted.
1935 TEST_F(ResourceDispatcherHostTest
, TestBlockedRequestsDontLeak
) {
1936 // This second filter is used to emulate a second process.
1937 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
1939 host_
.BlockRequestsForRoute(filter_
->child_id(), 1);
1940 host_
.BlockRequestsForRoute(filter_
->child_id(), 2);
1941 host_
.BlockRequestsForRoute(second_filter
->child_id(), 1);
1943 MakeTestRequestWithResourceType(filter_
.get(), 0, 1,
1944 net::URLRequestTestJob::test_url_1(),
1945 RESOURCE_TYPE_SUB_RESOURCE
);
1946 MakeTestRequestWithResourceType(filter_
.get(), 1, 2,
1947 net::URLRequestTestJob::test_url_2(),
1948 RESOURCE_TYPE_SUB_RESOURCE
);
1949 MakeTestRequestWithResourceType(filter_
.get(), 0, 3,
1950 net::URLRequestTestJob::test_url_3(),
1951 RESOURCE_TYPE_SUB_RESOURCE
);
1952 MakeTestRequestWithResourceType(second_filter
.get(), 1, 4,
1953 net::URLRequestTestJob::test_url_1(),
1954 RESOURCE_TYPE_SUB_RESOURCE
);
1955 MakeTestRequestWithResourceType(filter_
.get(), 2, 5,
1956 net::URLRequestTestJob::test_url_2(),
1957 RESOURCE_TYPE_SUB_RESOURCE
);
1958 MakeTestRequestWithResourceType(filter_
.get(), 2, 6,
1959 net::URLRequestTestJob::test_url_3(),
1960 RESOURCE_TYPE_SUB_RESOURCE
);
1961 MakeTestRequestWithResourceType(filter_
.get(), 0, 7,
1962 net::URLRequestTestJob::test_url_4(),
1963 RESOURCE_TYPE_PREFETCH
); // detachable type
1964 MakeTestRequestWithResourceType(second_filter
.get(), 1, 8,
1965 net::URLRequestTestJob::test_url_4(),
1966 RESOURCE_TYPE_PREFETCH
); // detachable type
1968 host_
.CancelRequestsForProcess(filter_
->child_id());
1969 host_
.CancelRequestsForProcess(second_filter
->child_id());
1971 // Flush all the pending requests.
1972 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1975 // Test the private helper method "CalculateApproximateMemoryCost()".
1976 TEST_F(ResourceDispatcherHostTest
, CalculateApproximateMemoryCost
) {
1977 net::URLRequestContext context
;
1978 scoped_ptr
<net::URLRequest
> req(context
.CreateRequest(
1979 GURL("http://www.google.com"), net::DEFAULT_PRIORITY
, NULL
));
1982 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req
.get()));
1984 // Add 9 bytes of referrer.
1985 req
->SetReferrer("123456789");
1988 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req
.get()));
1990 // Add 33 bytes of upload content.
1991 std::string upload_content
;
1992 upload_content
.resize(33);
1993 std::fill(upload_content
.begin(), upload_content
.end(), 'x');
1994 scoped_ptr
<net::UploadElementReader
> reader(new net::UploadBytesElementReader(
1995 upload_content
.data(), upload_content
.size()));
1997 net::ElementsUploadDataStream::CreateWithReader(reader
.Pass(), 0));
1999 // Since the upload throttling is disabled, this has no effect on the cost.
2002 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req
.get()));
2005 // Test that too much memory for outstanding requests for a particular
2006 // render_process_host_id causes requests to fail.
2007 TEST_F(ResourceDispatcherHostTest
, TooMuchOutstandingRequestsMemory
) {
2008 // Expected cost of each request as measured by
2009 // ResourceDispatcherHost::CalculateApproximateMemoryCost().
2010 int kMemoryCostOfTest2Req
=
2011 ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest
+
2012 std::string("GET").size() +
2013 net::URLRequestTestJob::test_url_2().spec().size();
2015 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
2016 int kMaxCostPerProcess
= 440000;
2017 host_
.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess
);
2019 // Determine how many instance of test_url_2() we can request before
2020 // throttling kicks in.
2021 size_t kMaxRequests
= kMaxCostPerProcess
/ kMemoryCostOfTest2Req
;
2023 // This second filter is used to emulate a second process.
2024 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2026 // Saturate the number of outstanding requests for our process.
2027 for (size_t i
= 0; i
< kMaxRequests
; ++i
) {
2028 MakeTestRequestWithResourceType(filter_
.get(), 0, i
+ 1,
2029 net::URLRequestTestJob::test_url_2(),
2030 RESOURCE_TYPE_SUB_RESOURCE
);
2033 // Issue two more requests for our process -- these should fail immediately.
2034 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequests
+ 1,
2035 net::URLRequestTestJob::test_url_2(),
2036 RESOURCE_TYPE_SUB_RESOURCE
);
2037 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequests
+ 2,
2038 net::URLRequestTestJob::test_url_2(),
2039 RESOURCE_TYPE_SUB_RESOURCE
);
2041 // Issue two requests for the second process -- these should succeed since
2042 // it is just process 0 that is saturated.
2043 MakeTestRequestWithResourceType(second_filter
.get(), 0, kMaxRequests
+ 3,
2044 net::URLRequestTestJob::test_url_2(),
2045 RESOURCE_TYPE_SUB_RESOURCE
);
2046 MakeTestRequestWithResourceType(second_filter
.get(), 0, kMaxRequests
+ 4,
2047 net::URLRequestTestJob::test_url_2(),
2048 RESOURCE_TYPE_SUB_RESOURCE
);
2050 // Flush all the pending requests.
2051 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2052 base::MessageLoop::current()->RunUntilIdle();
2054 // Sorts out all the messages we saw by request.
2055 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2056 accum_
.GetClassifiedMessages(&msgs
);
2058 // We issued (kMaxRequests + 4) total requests.
2059 ASSERT_EQ(kMaxRequests
+ 4, msgs
.size());
2061 // Check that the first kMaxRequests succeeded.
2062 for (size_t i
= 0; i
< kMaxRequests
; ++i
)
2063 CheckSuccessfulRequest(msgs
[i
], net::URLRequestTestJob::test_data_2());
2065 // Check that the subsequent two requests (kMaxRequests + 1) and
2066 // (kMaxRequests + 2) were failed, since the per-process bound was reached.
2067 for (int i
= 0; i
< 2; ++i
) {
2068 // Should have sent a single RequestComplete message.
2069 int index
= kMaxRequests
+ i
;
2070 CheckFailedRequest(msgs
[index
], net::URLRequestTestJob::test_data_2(),
2071 net::ERR_INSUFFICIENT_RESOURCES
);
2074 // The final 2 requests should have succeeded.
2075 CheckSuccessfulRequest(msgs
[kMaxRequests
+ 2],
2076 net::URLRequestTestJob::test_data_2());
2077 CheckSuccessfulRequest(msgs
[kMaxRequests
+ 3],
2078 net::URLRequestTestJob::test_data_2());
2081 // Test that when too many requests are outstanding for a particular
2082 // render_process_host_id, any subsequent request from it fails. Also verify
2083 // that the global limit is honored.
2084 TEST_F(ResourceDispatcherHostTest
, TooManyOutstandingRequests
) {
2085 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
2086 const size_t kMaxRequestsPerProcess
= 2;
2087 host_
.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess
);
2088 const size_t kMaxRequests
= 3;
2089 host_
.set_max_num_in_flight_requests(kMaxRequests
);
2091 // Needed to emulate additional processes.
2092 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2093 scoped_refptr
<ForwardingFilter
> third_filter
= MakeForwardingFilter();
2095 // Saturate the number of outstanding requests for our process.
2096 for (size_t i
= 0; i
< kMaxRequestsPerProcess
; ++i
) {
2097 MakeTestRequestWithResourceType(filter_
.get(), 0, i
+ 1,
2098 net::URLRequestTestJob::test_url_2(),
2099 RESOURCE_TYPE_SUB_RESOURCE
);
2102 // Issue another request for our process -- this should fail immediately.
2103 MakeTestRequestWithResourceType(filter_
.get(), 0, kMaxRequestsPerProcess
+ 1,
2104 net::URLRequestTestJob::test_url_2(),
2105 RESOURCE_TYPE_SUB_RESOURCE
);
2107 // Issue a request for the second process -- this should succeed, because it
2108 // is just process 0 that is saturated.
2109 MakeTestRequestWithResourceType(
2110 second_filter
.get(), 0, kMaxRequestsPerProcess
+ 2,
2111 net::URLRequestTestJob::test_url_2(), RESOURCE_TYPE_SUB_RESOURCE
);
2113 // Issue a request for the third process -- this should fail, because the
2114 // global limit has been reached.
2115 MakeTestRequestWithResourceType(
2116 third_filter
.get(), 0, kMaxRequestsPerProcess
+ 3,
2117 net::URLRequestTestJob::test_url_2(), RESOURCE_TYPE_SUB_RESOURCE
);
2119 // Flush all the pending requests.
2120 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2121 base::MessageLoop::current()->RunUntilIdle();
2123 // Sorts out all the messages we saw by request.
2124 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2125 accum_
.GetClassifiedMessages(&msgs
);
2127 // The processes issued the following requests:
2128 // #1 issued kMaxRequestsPerProcess that passed + 1 that failed
2129 // #2 issued 1 request that passed
2130 // #3 issued 1 request that failed
2131 ASSERT_EQ((kMaxRequestsPerProcess
+ 1) + 1 + 1, msgs
.size());
2133 for (size_t i
= 0; i
< kMaxRequestsPerProcess
; ++i
)
2134 CheckSuccessfulRequest(msgs
[i
], net::URLRequestTestJob::test_data_2());
2136 CheckFailedRequest(msgs
[kMaxRequestsPerProcess
+ 0],
2137 net::URLRequestTestJob::test_data_2(),
2138 net::ERR_INSUFFICIENT_RESOURCES
);
2139 CheckSuccessfulRequest(msgs
[kMaxRequestsPerProcess
+ 1],
2140 net::URLRequestTestJob::test_data_2());
2141 CheckFailedRequest(msgs
[kMaxRequestsPerProcess
+ 2],
2142 net::URLRequestTestJob::test_data_2(),
2143 net::ERR_INSUFFICIENT_RESOURCES
);
2146 // Tests that we sniff the mime type for a simple request.
2147 TEST_F(ResourceDispatcherHostTest
, MimeSniffed
) {
2148 std::string
raw_headers("HTTP/1.1 200 OK\n\n");
2149 std::string
response_data("<html><title>Test One</title></html>");
2150 SetResponse(raw_headers
, response_data
);
2152 HandleScheme("http");
2153 MakeTestRequest(0, 1, GURL("http:bla"));
2155 // Flush all pending requests.
2156 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2158 // Sorts out all the messages we saw by request.
2159 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2160 accum_
.GetClassifiedMessages(&msgs
);
2161 ASSERT_EQ(1U, msgs
.size());
2163 ResourceResponseHead response_head
;
2164 GetResponseHead(msgs
[0], &response_head
);
2165 ASSERT_EQ("text/html", response_head
.mime_type
);
2168 // Tests that we don't sniff the mime type when the server provides one.
2169 TEST_F(ResourceDispatcherHostTest
, MimeNotSniffed
) {
2170 std::string
raw_headers("HTTP/1.1 200 OK\n"
2171 "Content-type: image/jpeg\n\n");
2172 std::string
response_data("<html><title>Test One</title></html>");
2173 SetResponse(raw_headers
, response_data
);
2175 HandleScheme("http");
2176 MakeTestRequest(0, 1, GURL("http:bla"));
2178 // Flush all pending requests.
2179 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2181 // Sorts out all the messages we saw by request.
2182 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2183 accum_
.GetClassifiedMessages(&msgs
);
2184 ASSERT_EQ(1U, msgs
.size());
2186 ResourceResponseHead response_head
;
2187 GetResponseHead(msgs
[0], &response_head
);
2188 ASSERT_EQ("image/jpeg", response_head
.mime_type
);
2191 // Tests that we don't sniff the mime type when there is no message body.
2192 TEST_F(ResourceDispatcherHostTest
, MimeNotSniffed2
) {
2193 SetResponse("HTTP/1.1 304 Not Modified\n\n");
2195 HandleScheme("http");
2196 MakeTestRequest(0, 1, GURL("http:bla"));
2198 // Flush all pending requests.
2199 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2201 // Sorts out all the messages we saw by request.
2202 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2203 accum_
.GetClassifiedMessages(&msgs
);
2204 ASSERT_EQ(1U, msgs
.size());
2206 ResourceResponseHead response_head
;
2207 GetResponseHead(msgs
[0], &response_head
);
2208 ASSERT_EQ("", response_head
.mime_type
);
2211 TEST_F(ResourceDispatcherHostTest
, MimeSniff204
) {
2212 SetResponse("HTTP/1.1 204 No Content\n\n");
2214 HandleScheme("http");
2215 MakeTestRequest(0, 1, GURL("http:bla"));
2217 // Flush all pending requests.
2218 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2220 // Sorts out all the messages we saw by request.
2221 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2222 accum_
.GetClassifiedMessages(&msgs
);
2223 ASSERT_EQ(1U, msgs
.size());
2225 ResourceResponseHead response_head
;
2226 GetResponseHead(msgs
[0], &response_head
);
2227 ASSERT_EQ("text/plain", response_head
.mime_type
);
2230 TEST_F(ResourceDispatcherHostTest
, MimeSniffEmpty
) {
2231 SetResponse("HTTP/1.1 200 OK\n\n");
2233 HandleScheme("http");
2234 MakeTestRequest(0, 1, GURL("http:bla"));
2236 // Flush all pending requests.
2237 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2239 // Sorts out all the messages we saw by request.
2240 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2241 accum_
.GetClassifiedMessages(&msgs
);
2242 ASSERT_EQ(1U, msgs
.size());
2244 ResourceResponseHead response_head
;
2245 GetResponseHead(msgs
[0], &response_head
);
2246 ASSERT_EQ("text/plain", response_head
.mime_type
);
2249 // Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
2250 TEST_F(ResourceDispatcherHostTest
, ForbiddenDownload
) {
2251 std::string
raw_headers("HTTP/1.1 403 Forbidden\n"
2252 "Content-disposition: attachment; filename=blah\n"
2253 "Content-type: application/octet-stream\n\n");
2254 std::string
response_data("<html><title>Test One</title></html>");
2255 SetResponse(raw_headers
, response_data
);
2257 HandleScheme("http");
2259 // Only MAIN_FRAMEs can trigger a download.
2260 MakeTestRequestWithResourceType(filter_
.get(), 0, 1, GURL("http:bla"),
2261 RESOURCE_TYPE_MAIN_FRAME
);
2263 // Flush all pending requests.
2264 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2265 base::MessageLoop::current()->RunUntilIdle();
2267 // Sorts out all the messages we saw by request.
2268 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2269 accum_
.GetClassifiedMessages(&msgs
);
2271 // We should have gotten one RequestComplete message.
2272 ASSERT_EQ(1U, msgs
.size());
2273 ASSERT_EQ(1U, msgs
[0].size());
2274 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][0].type());
2276 // The RequestComplete message should have had the error code of
2277 // ERR_INVALID_RESPONSE.
2278 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_INVALID_RESPONSE
);
2281 // Test for http://crbug.com/76202 . We don't want to destroy a
2282 // download request prematurely when processing a cancellation from
2284 TEST_F(ResourceDispatcherHostTest
, IgnoreCancelForDownloads
) {
2285 EXPECT_EQ(0, host_
.pending_requests());
2287 int render_view_id
= 0;
2290 std::string
raw_headers("HTTP\n"
2291 "Content-disposition: attachment; filename=foo\n\n");
2292 std::string
response_data("01234567890123456789\x01foobar");
2294 // Get past sniffing metrics in the MimeTypeResourceHandler. Note that
2295 // if we don't get past the sniffing metrics, the result will be that
2296 // the MimeTypeResourceHandler won't have figured out that it's a download,
2297 // won't have constructed a DownloadResourceHandler, and and the request will
2298 // be successfully canceled below, failing the test.
2299 response_data
.resize(1025, ' ');
2301 SetResponse(raw_headers
, response_data
);
2302 job_factory_
->SetDelayedCompleteJobGeneration(true);
2303 HandleScheme("http");
2305 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2306 GURL("http://example.com/blah"),
2307 RESOURCE_TYPE_MAIN_FRAME
);
2308 // Return some data so that the request is identified as a download
2309 // and the proper resource handlers are created.
2310 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2312 // And now simulate a cancellation coming from the renderer.
2313 ResourceHostMsg_CancelRequest
msg(request_id
);
2314 host_
.OnMessageReceived(msg
, filter_
.get());
2316 // Since the request had already started processing as a download,
2317 // the cancellation above should have been ignored and the request
2318 // should still be alive.
2319 EXPECT_EQ(1, host_
.pending_requests());
2321 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2324 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContext
) {
2325 EXPECT_EQ(0, host_
.pending_requests());
2327 int render_view_id
= 0;
2330 std::string
raw_headers("HTTP\n"
2331 "Content-disposition: attachment; filename=foo\n\n");
2332 std::string
response_data("01234567890123456789\x01foobar");
2333 // Get past sniffing metrics.
2334 response_data
.resize(1025, ' ');
2336 SetResponse(raw_headers
, response_data
);
2337 job_factory_
->SetDelayedCompleteJobGeneration(true);
2338 HandleScheme("http");
2340 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2341 GURL("http://example.com/blah"),
2342 RESOURCE_TYPE_MAIN_FRAME
);
2343 // Return some data so that the request is identified as a download
2344 // and the proper resource handlers are created.
2345 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2347 // And now simulate a cancellation coming from the renderer.
2348 ResourceHostMsg_CancelRequest
msg(request_id
);
2349 host_
.OnMessageReceived(msg
, filter_
.get());
2351 // Since the request had already started processing as a download,
2352 // the cancellation above should have been ignored and the request
2353 // should still be alive.
2354 EXPECT_EQ(1, host_
.pending_requests());
2356 // Cancelling by other methods shouldn't work either.
2357 host_
.CancelRequestsForProcess(render_view_id
);
2358 EXPECT_EQ(1, host_
.pending_requests());
2360 // Cancelling by context should work.
2361 host_
.CancelRequestsForContext(filter_
->resource_context());
2362 EXPECT_EQ(0, host_
.pending_requests());
2365 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContextDetached
) {
2366 EXPECT_EQ(0, host_
.pending_requests());
2368 int render_view_id
= 0;
2371 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2372 net::URLRequestTestJob::test_url_4(),
2373 RESOURCE_TYPE_PREFETCH
); // detachable type
2375 // Simulate a cancel coming from the renderer.
2376 RendererCancelRequest(request_id
);
2378 // Since the request had already started processing as detachable,
2379 // the cancellation above should have been ignored and the request
2380 // should have been detached.
2381 EXPECT_EQ(1, host_
.pending_requests());
2383 // Cancelling by other methods should also leave it detached.
2384 host_
.CancelRequestsForProcess(render_view_id
);
2385 EXPECT_EQ(1, host_
.pending_requests());
2387 // Cancelling by context should work.
2388 host_
.CancelRequestsForContext(filter_
->resource_context());
2389 EXPECT_EQ(0, host_
.pending_requests());
2392 // Test the cancelling of requests that are being transferred to a new renderer
2393 // due to a redirection.
2394 TEST_F(ResourceDispatcherHostTest
, CancelRequestsForContextTransferred
) {
2395 EXPECT_EQ(0, host_
.pending_requests());
2397 int render_view_id
= 0;
2400 std::string
raw_headers("HTTP/1.1 200 OK\n"
2401 "Content-Type: text/html; charset=utf-8\n\n");
2402 std::string
response_data("<html>foobar</html>");
2404 SetResponse(raw_headers
, response_data
);
2405 HandleScheme("http");
2407 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2408 GURL("http://example.com/blah"),
2409 RESOURCE_TYPE_MAIN_FRAME
);
2412 GlobalRequestID
global_request_id(filter_
->child_id(), request_id
);
2413 host_
.MarkAsTransferredNavigation(global_request_id
);
2415 // And now simulate a cancellation coming from the renderer.
2416 ResourceHostMsg_CancelRequest
msg(request_id
);
2417 host_
.OnMessageReceived(msg
, filter_
.get());
2419 // Since the request is marked as being transferred,
2420 // the cancellation above should have been ignored and the request
2421 // should still be alive.
2422 EXPECT_EQ(1, host_
.pending_requests());
2424 // Cancelling by other methods shouldn't work either.
2425 host_
.CancelRequestsForProcess(render_view_id
);
2426 EXPECT_EQ(1, host_
.pending_requests());
2428 // Cancelling by context should work.
2429 host_
.CancelRequestsForContext(filter_
->resource_context());
2430 EXPECT_EQ(0, host_
.pending_requests());
2433 // Test transferred navigations with text/html, which doesn't trigger any
2434 // content sniffing.
2435 TEST_F(ResourceDispatcherHostTest
, TransferNavigationHtml
) {
2436 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2437 switches::kEnableBrowserSideNavigation
)) {
2438 SUCCEED() << "Test is not applicable with browser side navigation enabled";
2441 // This test expects the cross site request to be leaked, so it can transfer
2442 // the request directly.
2443 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2445 EXPECT_EQ(0, host_
.pending_requests());
2447 int render_view_id
= 0;
2450 // Configure initial request.
2451 SetResponse("HTTP/1.1 302 Found\n"
2452 "Location: http://other.com/blech\n\n");
2454 HandleScheme("http");
2456 // Temporarily replace ContentBrowserClient with one that will trigger the
2457 // transfer navigation code paths.
2458 TransfersAllNavigationsContentBrowserClient new_client
;
2459 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2461 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2462 GURL("http://example.com/blah"),
2463 RESOURCE_TYPE_MAIN_FRAME
);
2465 // Now that we're blocked on the redirect, update the response and unblock by
2466 // telling the AsyncResourceHandler to follow the redirect.
2467 const std::string kResponseBody
= "hello world";
2468 SetResponse("HTTP/1.1 200 OK\n"
2469 "Content-Type: text/html\n\n",
2471 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
);
2472 host_
.OnMessageReceived(redirect_msg
, filter_
.get());
2473 base::MessageLoop::current()->RunUntilIdle();
2475 // Flush all the pending requests to get the response through the
2476 // MimeTypeResourceHandler.
2477 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2479 // Restore, now that we've set up a transfer.
2480 SetBrowserClientForTesting(old_client
);
2482 // This second filter is used to emulate a second process.
2483 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2485 int new_render_view_id
= 1;
2486 int new_request_id
= 2;
2488 ResourceHostMsg_Request request
=
2489 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2490 GURL("http://other.com/blech"));
2491 request
.transferred_request_child_id
= filter_
->child_id();
2492 request
.transferred_request_request_id
= request_id
;
2494 ResourceHostMsg_RequestResource
transfer_request_msg(
2495 new_render_view_id
, new_request_id
, request
);
2496 host_
.OnMessageReceived(transfer_request_msg
, second_filter
.get());
2497 base::MessageLoop::current()->RunUntilIdle();
2499 // Check generated messages.
2500 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2501 accum_
.GetClassifiedMessages(&msgs
);
2503 ASSERT_EQ(2U, msgs
.size());
2504 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2505 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2508 // Test transferring two navigations with text/html, to ensure the resource
2509 // accounting works.
2510 TEST_F(ResourceDispatcherHostTest
, TransferTwoNavigationsHtml
) {
2511 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2512 switches::kEnableBrowserSideNavigation
)) {
2513 SUCCEED() << "Test is not applicable with browser side navigation enabled";
2516 // This test expects the cross site request to be leaked, so it can transfer
2517 // the request directly.
2518 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2520 EXPECT_EQ(0, host_
.pending_requests());
2522 int render_view_id
= 0;
2525 // Configure initial request.
2526 const std::string kResponseBody
= "hello world";
2527 SetResponse("HTTP/1.1 200 OK\n"
2528 "Content-Type: text/html\n\n",
2531 HandleScheme("http");
2533 // Temporarily replace ContentBrowserClient with one that will trigger the
2534 // transfer navigation code paths.
2535 TransfersAllNavigationsContentBrowserClient new_client
;
2536 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2538 // Make the first request.
2539 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2540 GURL("http://example.com/blah"),
2541 RESOURCE_TYPE_MAIN_FRAME
);
2543 // Make a second request from the same process.
2544 int second_request_id
= 2;
2545 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
,
2547 GURL("http://example.com/foo"),
2548 RESOURCE_TYPE_MAIN_FRAME
);
2550 // Flush all the pending requests to get the response through the
2551 // MimeTypeResourceHandler.
2552 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2554 // Restore, now that we've set up a transfer.
2555 SetBrowserClientForTesting(old_client
);
2557 // This second filter is used to emulate a second process.
2558 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2560 // Transfer the first request.
2561 int new_render_view_id
= 1;
2562 int new_request_id
= 5;
2563 ResourceHostMsg_Request request
=
2564 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2565 GURL("http://example.com/blah"));
2566 request
.transferred_request_child_id
= filter_
->child_id();
2567 request
.transferred_request_request_id
= request_id
;
2569 ResourceHostMsg_RequestResource
transfer_request_msg(
2570 new_render_view_id
, new_request_id
, request
);
2571 host_
.OnMessageReceived(transfer_request_msg
, second_filter
.get());
2572 base::MessageLoop::current()->RunUntilIdle();
2574 // Transfer the second request.
2575 int new_second_request_id
= 6;
2576 ResourceHostMsg_Request second_request
=
2577 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2578 GURL("http://example.com/foo"));
2579 request
.transferred_request_child_id
= filter_
->child_id();
2580 request
.transferred_request_request_id
= second_request_id
;
2582 ResourceHostMsg_RequestResource
second_transfer_request_msg(
2583 new_render_view_id
, new_second_request_id
, second_request
);
2584 host_
.OnMessageReceived(second_transfer_request_msg
, second_filter
.get());
2585 base::MessageLoop::current()->RunUntilIdle();
2587 // Check generated messages.
2588 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2589 accum_
.GetClassifiedMessages(&msgs
);
2591 ASSERT_EQ(2U, msgs
.size());
2592 CheckSuccessfulRequest(msgs
[0], kResponseBody
);
2595 // Test transferred navigations with text/plain, which causes
2596 // MimeTypeResourceHandler to buffer the response to sniff the content before
2597 // the transfer occurs.
2598 TEST_F(ResourceDispatcherHostTest
, TransferNavigationText
) {
2599 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2600 switches::kEnableBrowserSideNavigation
)) {
2601 SUCCEED() << "Test is not applicable with browser side navigation enabled";
2604 // This test expects the cross site request to be leaked, so it can transfer
2605 // the request directly.
2606 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2608 EXPECT_EQ(0, host_
.pending_requests());
2610 int render_view_id
= 0;
2613 // Configure initial request.
2614 SetResponse("HTTP/1.1 302 Found\n"
2615 "Location: http://other.com/blech\n\n");
2617 HandleScheme("http");
2619 // Temporarily replace ContentBrowserClient with one that will trigger the
2620 // transfer navigation code paths.
2621 TransfersAllNavigationsContentBrowserClient new_client
;
2622 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2624 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2625 GURL("http://example.com/blah"),
2626 RESOURCE_TYPE_MAIN_FRAME
);
2628 // Now that we're blocked on the redirect, update the response and unblock by
2629 // telling the AsyncResourceHandler to follow the redirect. Use a text/plain
2630 // MIME type, which causes MimeTypeResourceHandler to buffer it before the
2632 const std::string kResponseBody
= "hello world";
2633 SetResponse("HTTP/1.1 200 OK\n"
2634 "Content-Type: text/plain\n\n",
2636 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
);
2637 host_
.OnMessageReceived(redirect_msg
, filter_
.get());
2638 base::MessageLoop::current()->RunUntilIdle();
2640 // Flush all the pending requests to get the response through the
2641 // MimeTypeResourceHandler.
2642 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2644 // Restore, now that we've set up a transfer.
2645 SetBrowserClientForTesting(old_client
);
2647 // This second filter is used to emulate a second process.
2648 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2650 int new_render_view_id
= 1;
2651 int new_request_id
= 2;
2653 ResourceHostMsg_Request request
=
2654 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2655 GURL("http://other.com/blech"));
2656 request
.transferred_request_child_id
= filter_
->child_id();
2657 request
.transferred_request_request_id
= request_id
;
2659 ResourceHostMsg_RequestResource
transfer_request_msg(
2660 new_render_view_id
, new_request_id
, request
);
2661 host_
.OnMessageReceived(transfer_request_msg
, second_filter
.get());
2662 base::MessageLoop::current()->RunUntilIdle();
2664 // Check generated messages.
2665 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2666 accum_
.GetClassifiedMessages(&msgs
);
2668 ASSERT_EQ(2U, msgs
.size());
2669 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2670 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2673 TEST_F(ResourceDispatcherHostTest
, TransferNavigationWithProcessCrash
) {
2674 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2675 switches::kEnableBrowserSideNavigation
)) {
2676 SUCCEED() << "Test is not applicable with browser side navigation enabled";
2679 // This test expects the cross site request to be leaked, so it can transfer
2680 // the request directly.
2681 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2683 EXPECT_EQ(0, host_
.pending_requests());
2685 int render_view_id
= 0;
2687 int first_child_id
= -1;
2689 // Configure initial request.
2690 SetResponse("HTTP/1.1 302 Found\n"
2691 "Location: http://other.com/blech\n\n");
2692 const std::string kResponseBody
= "hello world";
2694 HandleScheme("http");
2696 // Temporarily replace ContentBrowserClient with one that will trigger the
2697 // transfer navigation code paths.
2698 TransfersAllNavigationsContentBrowserClient new_client
;
2699 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2701 // Create a first filter that can be deleted before the second one starts.
2703 scoped_refptr
<ForwardingFilter
> first_filter
= MakeForwardingFilter();
2704 first_child_id
= first_filter
->child_id();
2706 ResourceHostMsg_Request first_request
=
2707 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2708 GURL("http://example.com/blah"));
2710 ResourceHostMsg_RequestResource
first_request_msg(
2711 render_view_id
, request_id
, first_request
);
2712 host_
.OnMessageReceived(first_request_msg
, first_filter
.get());
2713 base::MessageLoop::current()->RunUntilIdle();
2715 // Now that we're blocked on the redirect, update the response and unblock
2716 // by telling the AsyncResourceHandler to follow the redirect.
2717 SetResponse("HTTP/1.1 200 OK\n"
2718 "Content-Type: text/html\n\n",
2720 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
);
2721 host_
.OnMessageReceived(redirect_msg
, first_filter
.get());
2722 base::MessageLoop::current()->RunUntilIdle();
2724 // Flush all the pending requests to get the response through the
2725 // MimeTypeResourceHandler.
2726 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2728 // The first filter is now deleted, as if the child process died.
2731 SetBrowserClientForTesting(old_client
);
2733 // Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
2734 GlobalRequestID
first_global_request_id(first_child_id
, request_id
);
2736 // This second filter is used to emulate a second process.
2737 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2739 int new_render_view_id
= 1;
2740 int new_request_id
= 2;
2742 ResourceHostMsg_Request request
=
2743 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2744 GURL("http://other.com/blech"));
2745 request
.transferred_request_child_id
= first_child_id
;
2746 request
.transferred_request_request_id
= request_id
;
2749 child_ids_
.insert(second_filter
->child_id());
2750 ResourceHostMsg_RequestResource
transfer_request_msg(
2751 new_render_view_id
, new_request_id
, request
);
2752 host_
.OnMessageReceived(transfer_request_msg
, second_filter
.get());
2753 base::MessageLoop::current()->RunUntilIdle();
2755 // Check generated messages.
2756 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2757 accum_
.GetClassifiedMessages(&msgs
);
2759 ASSERT_EQ(2U, msgs
.size());
2760 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2761 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2764 TEST_F(ResourceDispatcherHostTest
, TransferNavigationWithTwoRedirects
) {
2765 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2766 switches::kEnableBrowserSideNavigation
)) {
2767 SUCCEED() << "Test is not applicable with browser side navigation enabled";
2770 // This test expects the cross site request to be leaked, so it can transfer
2771 // the request directly.
2772 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2774 EXPECT_EQ(0, host_
.pending_requests());
2776 int render_view_id
= 0;
2779 // Configure initial request.
2780 SetResponse("HTTP/1.1 302 Found\n"
2781 "Location: http://other.com/blech\n\n");
2783 HandleScheme("http");
2785 // Temporarily replace ContentBrowserClient with one that will trigger the
2786 // transfer navigation code paths.
2787 TransfersAllNavigationsContentBrowserClient new_client
;
2788 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&new_client
);
2790 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2791 GURL("http://example.com/blah"),
2792 RESOURCE_TYPE_MAIN_FRAME
);
2794 // Now that we're blocked on the redirect, simulate hitting another redirect.
2795 SetResponse("HTTP/1.1 302 Found\n"
2796 "Location: http://other.com/blerg\n\n");
2797 ResourceHostMsg_FollowRedirect
redirect_msg(request_id
);
2798 host_
.OnMessageReceived(redirect_msg
, filter_
.get());
2799 base::MessageLoop::current()->RunUntilIdle();
2801 // Now that we're blocked on the second redirect, update the response and
2802 // unblock by telling the AsyncResourceHandler to follow the redirect.
2803 // Again, use text/plain to force MimeTypeResourceHandler to buffer before
2805 const std::string kResponseBody
= "hello world";
2806 SetResponse("HTTP/1.1 200 OK\n"
2807 "Content-Type: text/plain\n\n",
2809 ResourceHostMsg_FollowRedirect
redirect_msg2(request_id
);
2810 host_
.OnMessageReceived(redirect_msg2
, filter_
.get());
2811 base::MessageLoop::current()->RunUntilIdle();
2813 // Flush all the pending requests to get the response through the
2814 // MimeTypeResourceHandler.
2815 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2818 SetBrowserClientForTesting(old_client
);
2820 // This second filter is used to emulate a second process.
2821 scoped_refptr
<ForwardingFilter
> second_filter
= MakeForwardingFilter();
2823 int new_render_view_id
= 1;
2824 int new_request_id
= 2;
2826 ResourceHostMsg_Request request
=
2827 CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME
,
2828 GURL("http://other.com/blech"));
2829 request
.transferred_request_child_id
= filter_
->child_id();
2830 request
.transferred_request_request_id
= request_id
;
2833 child_ids_
.insert(second_filter
->child_id());
2834 ResourceHostMsg_RequestResource
transfer_request_msg(
2835 new_render_view_id
, new_request_id
, request
);
2836 host_
.OnMessageReceived(transfer_request_msg
, second_filter
.get());
2838 // Verify that we update the ResourceRequestInfo.
2839 GlobalRequestID
global_request_id(second_filter
->child_id(), new_request_id
);
2840 const ResourceRequestInfoImpl
* info
= ResourceRequestInfoImpl::ForRequest(
2841 host_
.GetURLRequest(global_request_id
));
2842 EXPECT_EQ(second_filter
->child_id(), info
->GetChildID());
2843 EXPECT_EQ(new_render_view_id
, info
->GetRouteID());
2844 EXPECT_EQ(new_request_id
, info
->GetRequestID());
2845 EXPECT_EQ(second_filter
.get(), info
->filter());
2847 // Let request complete.
2848 base::MessageLoop::current()->RunUntilIdle();
2850 // Check generated messages.
2851 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2852 accum_
.GetClassifiedMessages(&msgs
);
2854 ASSERT_EQ(2U, msgs
.size());
2855 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID
, msgs
[0][0].type());
2856 CheckSuccessfulRequest(msgs
[1], kResponseBody
);
2859 TEST_F(ResourceDispatcherHostTest
, UnknownURLScheme
) {
2860 EXPECT_EQ(0, host_
.pending_requests());
2862 HandleScheme("http");
2864 MakeTestRequestWithResourceType(filter_
.get(), 0, 1, GURL("foo://bar"),
2865 RESOURCE_TYPE_MAIN_FRAME
);
2867 // Flush all pending requests.
2868 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2870 // Sort all the messages we saw by request.
2871 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2872 accum_
.GetClassifiedMessages(&msgs
);
2874 // We should have gotten one RequestComplete message.
2875 ASSERT_EQ(1U, msgs
[0].size());
2876 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][0].type());
2878 // The RequestComplete message should have the error code of
2879 // ERR_UNKNOWN_URL_SCHEME.
2880 CheckRequestCompleteErrorCode(msgs
[0][0], net::ERR_UNKNOWN_URL_SCHEME
);
2883 TEST_F(ResourceDispatcherHostTest
, DataReceivedACKs
) {
2884 EXPECT_EQ(0, host_
.pending_requests());
2886 SendDataReceivedACKs(true);
2888 HandleScheme("big-job");
2889 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2891 base::RunLoop().RunUntilIdle();
2893 // Sort all the messages we saw by request.
2894 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2895 accum_
.GetClassifiedMessages(&msgs
);
2897 size_t size
= msgs
[0].size();
2899 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
2900 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
2901 for (size_t i
= 2; i
< size
- 1; ++i
)
2902 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2903 EXPECT_EQ(ResourceMsg_RequestComplete::ID
, msgs
[0][size
- 1].type());
2906 // Request a very large detachable resource and cancel part way. Some of the
2907 // data should have been sent to the renderer, but not all.
2908 TEST_F(ResourceDispatcherHostTest
, DataSentBeforeDetach
) {
2909 EXPECT_EQ(0, host_
.pending_requests());
2911 int render_view_id
= 0;
2914 std::string
raw_headers("HTTP\n"
2915 "Content-type: image/jpeg\n\n");
2916 std::string
response_data("01234567890123456789\x01foobar");
2918 // Create a response larger than kMaxAllocationSize (currently 32K). Note
2919 // that if this increase beyond 512K we'll need to make the response longer.
2920 const int kAllocSize
= 1024*512;
2921 response_data
.resize(kAllocSize
, ' ');
2923 SetResponse(raw_headers
, response_data
);
2924 job_factory_
->SetDelayedCompleteJobGeneration(true);
2925 HandleScheme("http");
2927 MakeTestRequestWithResourceType(filter_
.get(), render_view_id
, request_id
,
2928 GURL("http://example.com/blah"),
2929 RESOURCE_TYPE_PREFETCH
);
2931 // Get a bit of data before cancelling.
2932 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2934 // Simulate a cancellation coming from the renderer.
2935 ResourceHostMsg_CancelRequest
msg(request_id
);
2936 host_
.OnMessageReceived(msg
, filter_
.get());
2938 EXPECT_EQ(1, host_
.pending_requests());
2940 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2942 // Sort all the messages we saw by request.
2943 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2944 accum_
.GetClassifiedMessages(&msgs
);
2946 EXPECT_EQ(4U, msgs
[0].size());
2948 // Figure out how many bytes were received by the renderer.
2952 ExtractDataOffsetAndLength(msgs
[0][2], &data_offset
, &data_length
));
2953 EXPECT_LT(0, data_length
);
2954 EXPECT_GT(kAllocSize
, data_length
);
2956 // Verify the data that was received before cancellation. The request should
2957 // have appeared to cancel, however.
2958 CheckSuccessfulRequestWithErrorCode(
2960 std::string(response_data
.begin(), response_data
.begin() + data_length
),
2964 TEST_F(ResourceDispatcherHostTest
, DelayedDataReceivedACKs
) {
2965 EXPECT_EQ(0, host_
.pending_requests());
2967 HandleScheme("big-job");
2968 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2970 base::RunLoop().RunUntilIdle();
2972 // Sort all the messages we saw by request.
2973 ResourceIPCAccumulator::ClassifiedMessages msgs
;
2974 accum_
.GetClassifiedMessages(&msgs
);
2976 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
2977 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
2978 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
2979 for (size_t i
= 2; i
< msgs
[0].size(); ++i
)
2980 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
2982 // NOTE: If we fail the above checks then it means that we probably didn't
2983 // load a big enough response to trigger the delay mechanism we are trying to
2986 msgs
[0].erase(msgs
[0].begin());
2987 msgs
[0].erase(msgs
[0].begin());
2989 // ACK all DataReceived messages until we find a RequestComplete message.
2990 bool complete
= false;
2992 for (size_t i
= 0; i
< msgs
[0].size(); ++i
) {
2993 if (msgs
[0][i
].type() == ResourceMsg_RequestComplete::ID
) {
2998 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
3000 ResourceHostMsg_DataReceived_ACK
msg(1);
3001 host_
.OnMessageReceived(msg
, filter_
.get());
3004 base::MessageLoop::current()->RunUntilIdle();
3007 accum_
.GetClassifiedMessages(&msgs
);
3011 // Flakyness of this test might indicate memory corruption issues with
3012 // for example the ResourceBuffer of AsyncResourceHandler.
3013 TEST_F(ResourceDispatcherHostTest
, DataReceivedUnexpectedACKs
) {
3014 EXPECT_EQ(0, host_
.pending_requests());
3016 HandleScheme("big-job");
3017 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
3019 base::RunLoop().RunUntilIdle();
3021 // Sort all the messages we saw by request.
3022 ResourceIPCAccumulator::ClassifiedMessages msgs
;
3023 accum_
.GetClassifiedMessages(&msgs
);
3025 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
3026 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID
, msgs
[0][0].type());
3027 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID
, msgs
[0][1].type());
3028 for (size_t i
= 2; i
< msgs
[0].size(); ++i
)
3029 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
3031 // NOTE: If we fail the above checks then it means that we probably didn't
3032 // load a big enough response to trigger the delay mechanism.
3034 // Send some unexpected ACKs.
3035 for (size_t i
= 0; i
< 128; ++i
) {
3036 ResourceHostMsg_DataReceived_ACK
msg(1);
3037 host_
.OnMessageReceived(msg
, filter_
.get());
3040 msgs
[0].erase(msgs
[0].begin());
3041 msgs
[0].erase(msgs
[0].begin());
3043 // ACK all DataReceived messages until we find a RequestComplete message.
3044 bool complete
= false;
3046 for (size_t i
= 0; i
< msgs
[0].size(); ++i
) {
3047 if (msgs
[0][i
].type() == ResourceMsg_RequestComplete::ID
) {
3052 EXPECT_EQ(ResourceMsg_DataReceived::ID
, msgs
[0][i
].type());
3054 ResourceHostMsg_DataReceived_ACK
msg(1);
3055 host_
.OnMessageReceived(msg
, filter_
.get());
3058 base::MessageLoop::current()->RunUntilIdle();
3061 accum_
.GetClassifiedMessages(&msgs
);
3065 // Tests the dispatcher host's temporary file management.
3066 TEST_F(ResourceDispatcherHostTest
, RegisterDownloadedTempFile
) {
3067 const int kRequestID
= 1;
3069 // Create a temporary file.
3070 base::FilePath file_path
;
3071 ASSERT_TRUE(base::CreateTemporaryFile(&file_path
));
3072 scoped_refptr
<ShareableFileReference
> deletable_file
=
3073 ShareableFileReference::GetOrCreate(
3075 ShareableFileReference::DELETE_ON_FINAL_RELEASE
,
3076 BrowserThread::GetMessageLoopProxyForThread(
3077 BrowserThread::FILE).get());
3080 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3081 filter_
->child_id(), file_path
));
3083 // Register it for a resource request.
3084 host_
.RegisterDownloadedTempFile(filter_
->child_id(), kRequestID
, file_path
);
3086 // Should be readable now.
3087 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3088 filter_
->child_id(), file_path
));
3090 // The child releases from the request.
3091 ResourceHostMsg_ReleaseDownloadedFile
release_msg(kRequestID
);
3092 host_
.OnMessageReceived(release_msg
, filter_
.get());
3094 // Still readable because there is another reference to the file. (The child
3095 // may take additional blob references.)
3096 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3097 filter_
->child_id(), file_path
));
3099 // Release extra references and wait for the file to be deleted. (This relies
3100 // on the delete happening on the FILE thread which is mapped to main thread
3102 deletable_file
= NULL
;
3103 base::RunLoop().RunUntilIdle();
3105 // The file is no longer readable to the child and has been deleted.
3106 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3107 filter_
->child_id(), file_path
));
3108 EXPECT_FALSE(base::PathExists(file_path
));
3111 // Tests that temporary files held on behalf of child processes are released
3112 // when the child process dies.
3113 TEST_F(ResourceDispatcherHostTest
, ReleaseTemporiesOnProcessExit
) {
3114 const int kRequestID
= 1;
3116 // Create a temporary file.
3117 base::FilePath file_path
;
3118 ASSERT_TRUE(base::CreateTemporaryFile(&file_path
));
3119 scoped_refptr
<ShareableFileReference
> deletable_file
=
3120 ShareableFileReference::GetOrCreate(
3122 ShareableFileReference::DELETE_ON_FINAL_RELEASE
,
3123 BrowserThread::GetMessageLoopProxyForThread(
3124 BrowserThread::FILE).get());
3126 // Register it for a resource request.
3127 host_
.RegisterDownloadedTempFile(filter_
->child_id(), kRequestID
, file_path
);
3128 deletable_file
= NULL
;
3130 // Should be readable now.
3131 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3132 filter_
->child_id(), file_path
));
3134 // Let the process die.
3135 filter_
->OnChannelClosing();
3136 base::RunLoop().RunUntilIdle();
3138 // The file is no longer readable to the child and has been deleted.
3139 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3140 filter_
->child_id(), file_path
));
3141 EXPECT_FALSE(base::PathExists(file_path
));
3144 TEST_F(ResourceDispatcherHostTest
, DownloadToFile
) {
3145 // Make a request which downloads to file.
3146 ResourceHostMsg_Request request
= CreateResourceRequest(
3147 "GET", RESOURCE_TYPE_SUB_RESOURCE
, net::URLRequestTestJob::test_url_1());
3148 request
.download_to_file
= true;
3149 ResourceHostMsg_RequestResource
request_msg(0, 1, request
);
3150 host_
.OnMessageReceived(request_msg
, filter_
.get());
3152 // Running the message loop until idle does not work because
3153 // RedirectToFileResourceHandler posts things to base::WorkerPool. Instead,
3154 // wait for the ResourceMsg_RequestComplete to go out. Then run the event loop
3155 // until idle so the loader is gone.
3156 WaitForRequestComplete();
3157 base::RunLoop().RunUntilIdle();
3158 EXPECT_EQ(0, host_
.pending_requests());
3160 ResourceIPCAccumulator::ClassifiedMessages msgs
;
3161 accum_
.GetClassifiedMessages(&msgs
);
3163 ASSERT_EQ(1U, msgs
.size());
3164 const std::vector
<IPC::Message
>& messages
= msgs
[0];
3166 // The request should contain the following messages:
3167 // ReceivedResponse (indicates headers received and filename)
3168 // DataDownloaded* (bytes downloaded and total length)
3169 // RequestComplete (request is done)
3172 ResourceResponseHead response_head
;
3173 GetResponseHead(messages
, &response_head
);
3174 ASSERT_FALSE(response_head
.download_file_path
.empty());
3177 size_t total_len
= 0;
3178 for (size_t i
= 1; i
< messages
.size() - 1; i
++) {
3179 ASSERT_EQ(ResourceMsg_DataDownloaded::ID
, messages
[i
].type());
3180 base::PickleIterator
iter(messages
[i
]);
3181 int request_id
, data_len
;
3182 ASSERT_TRUE(IPC::ReadParam(&messages
[i
], &iter
, &request_id
));
3183 ASSERT_TRUE(IPC::ReadParam(&messages
[i
], &iter
, &data_len
));
3184 total_len
+= data_len
;
3186 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), total_len
);
3189 CheckRequestCompleteErrorCode(messages
.back(), net::OK
);
3191 // Verify that the data ended up in the temporary file.
3192 std::string contents
;
3193 ASSERT_TRUE(base::ReadFileToString(response_head
.download_file_path
,
3195 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents
);
3197 // The file should be readable by the child.
3198 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3199 filter_
->child_id(), response_head
.download_file_path
));
3201 // When the renderer releases the file, it should be deleted. Again,
3202 // RunUntilIdle doesn't work because base::WorkerPool is involved.
3203 ShareableFileReleaseWaiter
waiter(response_head
.download_file_path
);
3204 ResourceHostMsg_ReleaseDownloadedFile
release_msg(1);
3205 host_
.OnMessageReceived(release_msg
, filter_
.get());
3207 // The release callback runs before the delete is scheduled, so pump the
3208 // message loop for the delete itself. (This relies on the delete happening on
3209 // the FILE thread which is mapped to main thread in this test.)
3210 base::RunLoop().RunUntilIdle();
3212 EXPECT_FALSE(base::PathExists(response_head
.download_file_path
));
3213 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
3214 filter_
->child_id(), response_head
.download_file_path
));
3217 // Tests GetLoadInfoForAllRoutes when there are no pending requests.
3218 TEST_F(ResourceDispatcherHostTest
, LoadInfoNoRequests
) {
3219 scoped_ptr
<LoadInfoMap
> load_info_map
= RunLoadInfoTest(nullptr, 0);
3220 EXPECT_EQ(0u, load_info_map
->size());
3223 // Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
3224 // RenderView. The second one is farthest along.
3225 TEST_F(ResourceDispatcherHostTest
, LoadInfo
) {
3226 const GlobalRoutingID
kId(filter_
->child_id(), 0);
3227 LoadInfoTestRequestInfo request_info
[] = {
3230 net::LOAD_STATE_SENDING_REQUEST
,
3231 net::UploadProgress(0, 0)},
3234 net::LOAD_STATE_READING_RESPONSE
,
3235 net::UploadProgress(0, 0)},
3238 net::LOAD_STATE_SENDING_REQUEST
,
3239 net::UploadProgress(0, 0)},
3241 scoped_ptr
<LoadInfoMap
> load_info_map
=
3242 RunLoadInfoTest(request_info
, arraysize(request_info
));
3243 ASSERT_EQ(1u, load_info_map
->size());
3244 ASSERT_TRUE(load_info_map
->find(kId
) != load_info_map
->end());
3245 EXPECT_EQ(GURL("test://2/"), (*load_info_map
)[kId
].url
);
3246 EXPECT_EQ(net::LOAD_STATE_READING_RESPONSE
,
3247 (*load_info_map
)[kId
].load_state
.state
);
3248 EXPECT_EQ(0u, (*load_info_map
)[kId
].upload_position
);
3249 EXPECT_EQ(0u, (*load_info_map
)[kId
].upload_size
);
3252 // Tests GetLoadInfoForAllRoutes when there are 2 requests with the same
3253 // priority. The first one (Which will have the lowest ID) should be returned.
3254 TEST_F(ResourceDispatcherHostTest
, LoadInfoSamePriority
) {
3255 const GlobalRoutingID
kId(filter_
->child_id(), 0);
3256 LoadInfoTestRequestInfo request_info
[] = {
3259 net::LOAD_STATE_IDLE
,
3260 net::UploadProgress(0, 0)},
3263 net::LOAD_STATE_IDLE
,
3264 net::UploadProgress(0, 0)},
3266 scoped_ptr
<LoadInfoMap
> load_info_map
=
3267 RunLoadInfoTest(request_info
, arraysize(request_info
));
3268 ASSERT_EQ(1u, load_info_map
->size());
3269 ASSERT_TRUE(load_info_map
->find(kId
) != load_info_map
->end());
3270 EXPECT_EQ(GURL("test://1/"), (*load_info_map
)[kId
].url
);
3271 EXPECT_EQ(net::LOAD_STATE_IDLE
, (*load_info_map
)[kId
].load_state
.state
);
3272 EXPECT_EQ(0u, (*load_info_map
)[kId
].upload_position
);
3273 EXPECT_EQ(0u, (*load_info_map
)[kId
].upload_size
);
3276 // Tests GetLoadInfoForAllRoutes when a request is uploading a body.
3277 TEST_F(ResourceDispatcherHostTest
, LoadInfoUploadProgress
) {
3278 const GlobalRoutingID
kId(filter_
->child_id(), 0);
3279 LoadInfoTestRequestInfo request_info
[] = {
3282 net::LOAD_STATE_READING_RESPONSE
,
3283 net::UploadProgress(0, 0)},
3286 net::LOAD_STATE_READING_RESPONSE
,
3287 net::UploadProgress(1000, 1000)},
3290 net::LOAD_STATE_SENDING_REQUEST
,
3291 net::UploadProgress(50, 100)},
3294 net::LOAD_STATE_READING_RESPONSE
,
3295 net::UploadProgress(1000, 1000)},
3298 net::LOAD_STATE_READING_RESPONSE
,
3299 net::UploadProgress(0, 0)},
3301 scoped_ptr
<LoadInfoMap
> load_info_map
=
3302 RunLoadInfoTest(request_info
, arraysize(request_info
));
3303 ASSERT_EQ(1u, load_info_map
->size());
3304 ASSERT_TRUE(load_info_map
->find(kId
) != load_info_map
->end());
3305 EXPECT_EQ(GURL("test://2/"), (*load_info_map
)[kId
].url
);
3306 EXPECT_EQ(net::LOAD_STATE_SENDING_REQUEST
,
3307 (*load_info_map
)[kId
].load_state
.state
);
3308 EXPECT_EQ(50u, (*load_info_map
)[kId
].upload_position
);
3309 EXPECT_EQ(100u, (*load_info_map
)[kId
].upload_size
);
3312 // Tests GetLoadInfoForAllRoutes when there are 4 requests from 2 different
3313 // RenderViews. Also tests the case where the first / last requests are the
3314 // most interesting ones.
3315 TEST_F(ResourceDispatcherHostTest
, LoadInfoTwoRenderViews
) {
3316 const GlobalRoutingID
kId1(filter_
->child_id(), 0);
3317 const GlobalRoutingID
kId2(filter_
->child_id(), 1);
3318 LoadInfoTestRequestInfo request_info
[] = {
3321 net::LOAD_STATE_CONNECTING
,
3322 net::UploadProgress(0, 0)},
3325 net::LOAD_STATE_IDLE
,
3326 net::UploadProgress(0, 0)},
3329 net::LOAD_STATE_IDLE
,
3330 net::UploadProgress(0, 0)},
3333 net::LOAD_STATE_CONNECTING
,
3334 net::UploadProgress(0, 0)},
3336 scoped_ptr
<LoadInfoMap
> load_info_map
=
3337 RunLoadInfoTest(request_info
, arraysize(request_info
));
3338 ASSERT_EQ(2u, load_info_map
->size());
3340 ASSERT_TRUE(load_info_map
->find(kId1
) != load_info_map
->end());
3341 EXPECT_EQ(GURL("test://1/"), (*load_info_map
)[kId1
].url
);
3342 EXPECT_EQ(net::LOAD_STATE_CONNECTING
,
3343 (*load_info_map
)[kId1
].load_state
.state
);
3344 EXPECT_EQ(0u, (*load_info_map
)[kId1
].upload_position
);
3345 EXPECT_EQ(0u, (*load_info_map
)[kId1
].upload_size
);
3347 ASSERT_TRUE(load_info_map
->find(kId2
) != load_info_map
->end());
3348 EXPECT_EQ(GURL("test://4/"), (*load_info_map
)[kId2
].url
);
3349 EXPECT_EQ(net::LOAD_STATE_CONNECTING
,
3350 (*load_info_map
)[kId2
].load_state
.state
);
3351 EXPECT_EQ(0u, (*load_info_map
)[kId2
].upload_position
);
3352 EXPECT_EQ(0u, (*load_info_map
)[kId2
].upload_size
);
3355 // Confirm that resource response started notifications are correctly
3356 // transmitted to the WebContents.
3357 TEST_F(ResourceDispatcherHostTest
, TransferResponseStarted
) {
3358 int initial_count
= web_contents_observer_
->resource_response_start_count();
3360 MakeWebContentsAssociatedTestRequest(1, net::URLRequestTestJob::test_url_1());
3361 base::MessageLoop::current()->RunUntilIdle();
3363 EXPECT_EQ(initial_count
+ 1,
3364 web_contents_observer_
->resource_response_start_count());
3367 // Confirm that request redirected notifications are correctly
3368 // transmitted to the WebContents.
3369 TEST_F(ResourceDispatcherHostTest
, TransferRequestRedirected
) {
3370 int initial_count
= web_contents_observer_
->resource_request_redirect_count();
3372 MakeWebContentsAssociatedTestRequest(
3373 1, net::URLRequestTestJob::test_url_redirect_to_url_2());
3374 base::MessageLoop::current()->RunUntilIdle();
3376 EXPECT_EQ(initial_count
+ 1,
3377 web_contents_observer_
->resource_request_redirect_count());
3380 // Confirm that DidChangePriority messages are respected.
3381 TEST_F(ResourceDispatcherHostTest
, DidChangePriority
) {
3382 // ResourceScheduler only throttles http and https requests.
3383 HandleScheme("http");
3385 // Needed to enable scheduling for this child.
3386 host_
.OnRenderViewHostCreated(filter_
->child_id(), // child_id
3389 false); // is_audible
3391 // Prevent any of these requests from completing.
3392 job_factory_
->SetDelayedCompleteJobGeneration(true);
3393 SetResponse("HTTP/1.1 200 OK\n\n", "<title>Dummy body</title>");
3395 // Only one idle priority request will run while a high-priority request
3397 MakeTestRequestWithPriority(0, 1, net::HIGHEST
);
3398 MakeTestRequestWithPriority(0, 2, net::IDLE
);
3399 MakeTestRequestWithPriority(0, 3, net::IDLE
);
3403 EXPECT_EQ(2, job_factory_
->url_request_jobs_created_count());
3405 // Increase the priority of the second idle priority request. It was
3406 // scheduled later, so it is not currently running.
3407 ResourceHostMsg_DidChangePriority
priority_msg(3, net::MAXIMUM_PRIORITY
, 0);
3408 host_
.OnMessageReceived(priority_msg
, filter_
.get());
3409 base::MessageLoop::current()->RunUntilIdle();
3411 EXPECT_EQ(3, job_factory_
->url_request_jobs_created_count());
3414 host_
.OnRenderViewHostDeleted(filter_
->child_id(), // child_id
3418 // Confirm that resource response started notifications for downloads are not
3419 // transmitted to the WebContents.
3420 TEST_F(ResourceDispatcherHostTest
, TransferResponseStartedDownload
) {
3421 int initial_count(web_contents_observer_
->resource_response_start_count());
3423 MakeWebContentsAssociatedDownloadRequest(
3424 1, net::URLRequestTestJob::test_url_1());
3425 base::MessageLoop::current()->RunUntilIdle();
3426 EXPECT_EQ(initial_count
,
3427 web_contents_observer_
->resource_response_start_count());
3430 // Confirm that request redirected notifications for downloads are not
3431 // transmitted to the WebContents.
3432 TEST_F(ResourceDispatcherHostTest
, TransferRequestRedirectedDownload
) {
3433 int initial_count(web_contents_observer_
->resource_request_redirect_count());
3435 MakeWebContentsAssociatedDownloadRequest(
3436 1, net::URLRequestTestJob::test_url_redirect_to_url_2());
3437 base::MessageLoop::current()->RunUntilIdle();
3438 EXPECT_EQ(initial_count
,
3439 web_contents_observer_
->resource_request_redirect_count());
3442 net::URLRequestJob
* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
3443 const std::string
& scheme
,
3444 net::URLRequest
* request
,
3445 net::NetworkDelegate
* network_delegate
) const {
3446 url_request_jobs_created_count_
++;
3447 if (test_fixture_
->wait_for_request_create_loop_
)
3448 test_fixture_
->wait_for_request_create_loop_
->Quit();
3449 if (test_fixture_
->loader_test_request_info_
) {
3450 DCHECK_EQ(test_fixture_
->loader_test_request_info_
->url
, request
->url());
3451 scoped_ptr
<LoadInfoTestRequestInfo
> info
=
3452 test_fixture_
->loader_test_request_info_
.Pass();
3453 return new URLRequestLoadInfoJob(request
, network_delegate
,
3454 info
->load_state
, info
->upload_progress
);
3456 if (test_fixture_
->response_headers_
.empty()) {
3458 return new URLRequestTestDelayedStartJob(request
, network_delegate
);
3459 } else if (delay_complete_
) {
3460 return new URLRequestTestDelayedCompletionJob(request
,
3462 } else if (network_start_notification_
) {
3463 return new URLRequestTestDelayedNetworkJob(request
, network_delegate
);
3464 } else if (scheme
== "big-job") {
3465 return new URLRequestBigJob(request
, network_delegate
);
3467 return new net::URLRequestTestJob(request
, network_delegate
);
3471 return new URLRequestTestDelayedStartJob(
3472 request
, network_delegate
,
3473 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
3475 } else if (delay_complete_
) {
3476 return new URLRequestTestDelayedCompletionJob(
3477 request
, network_delegate
,
3478 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
3481 return new net::URLRequestTestJob(
3482 request
, network_delegate
,
3483 test_fixture_
->response_headers_
, test_fixture_
->response_data_
,
3489 net::URLRequestJob
* TestURLRequestJobFactory::MaybeInterceptRedirect(
3490 net::URLRequest
* request
,
3491 net::NetworkDelegate
* network_delegate
,
3492 const GURL
& location
) const {
3496 net::URLRequestJob
* TestURLRequestJobFactory::MaybeInterceptResponse(
3497 net::URLRequest
* request
,
3498 net::NetworkDelegate
* network_delegate
) const {
3502 } // namespace content