When enabling new profile management programmatically, make sure to set the
[chromium-blink-merge.git] / content / browser / loader / resource_dispatcher_host_unittest.cc
bloba815032ac6f5a1d1f40267691243911f2578bf8b
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.
5 #include <vector>
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/memory/shared_memory.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/pickle.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "content/browser/browser_thread_impl.h"
19 #include "content/browser/child_process_security_policy_impl.h"
20 #include "content/browser/loader/cross_site_resource_handler.h"
21 #include "content/browser/loader/detachable_resource_handler.h"
22 #include "content/browser/loader/resource_dispatcher_host_impl.h"
23 #include "content/browser/loader/resource_loader.h"
24 #include "content/browser/loader/resource_message_filter.h"
25 #include "content/browser/loader/resource_request_info_impl.h"
26 #include "content/browser/worker_host/worker_service_impl.h"
27 #include "content/common/child_process_host_impl.h"
28 #include "content/common/resource_messages.h"
29 #include "content/common/view_messages.h"
30 #include "content/public/browser/global_request_id.h"
31 #include "content/public/browser/resource_context.h"
32 #include "content/public/browser/resource_dispatcher_host_delegate.h"
33 #include "content/public/browser/resource_request_info.h"
34 #include "content/public/browser/resource_throttle.h"
35 #include "content/public/common/process_type.h"
36 #include "content/public/common/resource_response.h"
37 #include "content/public/test/test_browser_context.h"
38 #include "content/public/test/test_browser_thread_bundle.h"
39 #include "content/test/test_content_browser_client.h"
40 #include "net/base/net_errors.h"
41 #include "net/base/request_priority.h"
42 #include "net/base/upload_bytes_element_reader.h"
43 #include "net/base/upload_data_stream.h"
44 #include "net/http/http_util.h"
45 #include "net/url_request/url_request.h"
46 #include "net/url_request/url_request_context.h"
47 #include "net/url_request/url_request_job.h"
48 #include "net/url_request/url_request_job_factory.h"
49 #include "net/url_request/url_request_simple_job.h"
50 #include "net/url_request/url_request_test_job.h"
51 #include "net/url_request/url_request_test_util.h"
52 #include "testing/gtest/include/gtest/gtest.h"
53 #include "webkit/common/appcache/appcache_interfaces.h"
54 #include "webkit/common/blob/shareable_file_reference.h"
56 // TODO(eroman): Write unit tests for SafeBrowsing that exercise
57 // SafeBrowsingResourceHandler.
59 using webkit_blob::ShareableFileReference;
61 namespace content {
63 namespace {
65 // Returns the resource response header structure for this request.
66 void GetResponseHead(const std::vector<IPC::Message>& messages,
67 ResourceResponseHead* response_head) {
68 ASSERT_GE(messages.size(), 2U);
70 // The first messages should be received response.
71 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
73 PickleIterator iter(messages[0]);
74 int request_id;
75 ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, &request_id));
76 ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, response_head));
79 void GenerateIPCMessage(
80 scoped_refptr<ResourceMessageFilter> filter,
81 scoped_ptr<IPC::Message> message) {
82 ResourceDispatcherHostImpl::Get()->OnMessageReceived(
83 *message, filter.get());
86 // On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not
87 // automatically released.
89 // See ResourceDispatcher::ReleaseResourcesInDataMessage.
91 // TODO(davidben): It would be nice if the behavior for base::SharedMemoryHandle
92 // were more like it is in POSIX where the received fds are tracked in a
93 // ref-counted core that closes them if not extracted.
94 void ReleaseHandlesInMessage(const IPC::Message& message) {
95 if (message.type() == ResourceMsg_SetDataBuffer::ID) {
96 PickleIterator iter(message);
97 int request_id;
98 CHECK(message.ReadInt(&iter, &request_id));
99 base::SharedMemoryHandle shm_handle;
100 if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message,
101 &iter,
102 &shm_handle)) {
103 if (base::SharedMemory::IsHandleValid(shm_handle))
104 base::SharedMemory::CloseHandle(shm_handle);
109 } // namespace
111 static int RequestIDForMessage(const IPC::Message& msg) {
112 int request_id = -1;
113 switch (msg.type()) {
114 case ResourceMsg_UploadProgress::ID:
115 case ResourceMsg_ReceivedResponse::ID:
116 case ResourceMsg_ReceivedRedirect::ID:
117 case ResourceMsg_SetDataBuffer::ID:
118 case ResourceMsg_DataReceived::ID:
119 case ResourceMsg_DataDownloaded::ID:
120 case ResourceMsg_RequestComplete::ID: {
121 bool result = PickleIterator(msg).ReadInt(&request_id);
122 DCHECK(result);
123 break;
126 return request_id;
129 static ResourceHostMsg_Request CreateResourceRequest(
130 const char* method,
131 ResourceType::Type type,
132 const GURL& url) {
133 ResourceHostMsg_Request request;
134 request.method = std::string(method);
135 request.url = url;
136 request.first_party_for_cookies = url; // bypass third-party cookie blocking
137 request.referrer_policy = blink::WebReferrerPolicyDefault;
138 request.load_flags = 0;
139 request.origin_pid = 0;
140 request.resource_type = type;
141 request.request_context = 0;
142 request.appcache_host_id = appcache::kAppCacheNoHostId;
143 request.download_to_file = false;
144 request.is_main_frame = true;
145 request.parent_is_main_frame = false;
146 request.parent_render_frame_id = -1;
147 request.transition_type = PAGE_TRANSITION_LINK;
148 request.allow_download = true;
149 return request;
152 // Spin up the message loop to kick off the request.
153 static void KickOffRequest() {
154 base::MessageLoop::current()->RunUntilIdle();
157 // We may want to move this to a shared space if it is useful for something else
158 class ResourceIPCAccumulator {
159 public:
160 ~ResourceIPCAccumulator() {
161 for (size_t i = 0; i < messages_.size(); i++) {
162 ReleaseHandlesInMessage(messages_[i]);
166 // On Windows, takes ownership of SharedMemoryHandles in |msg|.
167 void AddMessage(const IPC::Message& msg) {
168 messages_.push_back(msg);
171 // This groups the messages by their request ID. The groups will be in order
172 // that the first message for each request ID was received, and the messages
173 // within the groups will be in the order that they appeared.
174 // Note that this clears messages_. The caller takes ownership of any
175 // SharedMemoryHandles in messages placed into |msgs|.
176 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages;
177 void GetClassifiedMessages(ClassifiedMessages* msgs);
179 private:
180 std::vector<IPC::Message> messages_;
183 // This is very inefficient as a result of repeatedly extracting the ID, use
184 // only for tests!
185 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
186 while (!messages_.empty()) {
187 // Ignore unknown message types as it is valid for code to generated other
188 // IPCs as side-effects that we are not testing here.
189 int cur_id = RequestIDForMessage(messages_[0]);
190 if (cur_id != -1) {
191 std::vector<IPC::Message> cur_requests;
192 cur_requests.push_back(messages_[0]);
193 // find all other messages with this ID
194 for (int i = 1; i < static_cast<int>(messages_.size()); i++) {
195 int id = RequestIDForMessage(messages_[i]);
196 if (id == cur_id) {
197 cur_requests.push_back(messages_[i]);
198 messages_.erase(messages_.begin() + i);
199 i--;
202 msgs->push_back(cur_requests);
204 messages_.erase(messages_.begin());
208 // This is used to emulate different sub-processes, since this filter will
209 // have a different ID than the original.
210 class TestFilter : public ResourceMessageFilter {
211 public:
212 explicit TestFilter(ResourceContext* resource_context)
213 : ResourceMessageFilter(
214 ChildProcessHostImpl::GenerateChildProcessUniqueId(),
215 PROCESS_TYPE_RENDERER, NULL, NULL, NULL, NULL,
216 base::Bind(&TestFilter::GetContexts, base::Unretained(this))),
217 resource_context_(resource_context),
218 canceled_(false),
219 received_after_canceled_(0) {
220 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
221 set_peer_pid_for_testing(base::GetCurrentProcId());
224 void set_canceled(bool canceled) { canceled_ = canceled; }
225 int received_after_canceled() const { return received_after_canceled_; }
227 // ResourceMessageFilter override
228 virtual bool Send(IPC::Message* msg) OVERRIDE {
229 // No messages should be received when the process has been canceled.
230 if (canceled_)
231 received_after_canceled_++;
232 ReleaseHandlesInMessage(*msg);
233 delete msg;
234 return true;
237 ResourceContext* resource_context() { return resource_context_; }
239 protected:
240 virtual ~TestFilter() {}
242 private:
243 void GetContexts(const ResourceHostMsg_Request& request,
244 ResourceContext** resource_context,
245 net::URLRequestContext** request_context) {
246 *resource_context = resource_context_;
247 *request_context = resource_context_->GetRequestContext();
250 ResourceContext* resource_context_;
251 bool canceled_;
252 int received_after_canceled_;
254 DISALLOW_COPY_AND_ASSIGN(TestFilter);
258 // This class forwards the incoming messages to the ResourceDispatcherHostTest.
259 // For the test, we want all the incoming messages to go to the same place,
260 // which is why this forwards.
261 class ForwardingFilter : public TestFilter {
262 public:
263 explicit ForwardingFilter(IPC::Sender* dest,
264 ResourceContext* resource_context)
265 : TestFilter(resource_context),
266 dest_(dest) {
269 // TestFilter override
270 virtual bool Send(IPC::Message* msg) OVERRIDE {
271 return dest_->Send(msg);
274 private:
275 virtual ~ForwardingFilter() {}
277 IPC::Sender* dest_;
279 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter);
282 // This class is a variation on URLRequestTestJob that will call
283 // URLRequest::OnBeforeNetworkStart before starting.
284 class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob {
285 public:
286 URLRequestTestDelayedNetworkJob(net::URLRequest* request,
287 net::NetworkDelegate* network_delegate)
288 : net::URLRequestTestJob(request, network_delegate) {}
290 // Only start if not deferred for network start.
291 virtual void Start() OVERRIDE {
292 bool defer = false;
293 NotifyBeforeNetworkStart(&defer);
294 if (defer)
295 return;
296 net::URLRequestTestJob::Start();
299 virtual void ResumeNetworkStart() OVERRIDE {
300 net::URLRequestTestJob::StartAsync();
303 private:
304 virtual ~URLRequestTestDelayedNetworkJob() {}
306 DISALLOW_COPY_AND_ASSIGN(URLRequestTestDelayedNetworkJob);
309 // This class is a variation on URLRequestTestJob in that it does
310 // not complete start upon entry, only when specifically told to.
311 class URLRequestTestDelayedStartJob : public net::URLRequestTestJob {
312 public:
313 URLRequestTestDelayedStartJob(net::URLRequest* request,
314 net::NetworkDelegate* network_delegate)
315 : net::URLRequestTestJob(request, network_delegate) {
316 Init();
318 URLRequestTestDelayedStartJob(net::URLRequest* request,
319 net::NetworkDelegate* network_delegate,
320 bool auto_advance)
321 : net::URLRequestTestJob(request, network_delegate, auto_advance) {
322 Init();
324 URLRequestTestDelayedStartJob(net::URLRequest* request,
325 net::NetworkDelegate* network_delegate,
326 const std::string& response_headers,
327 const std::string& response_data,
328 bool auto_advance)
329 : net::URLRequestTestJob(request,
330 network_delegate,
331 response_headers,
332 response_data,
333 auto_advance) {
334 Init();
337 // Do nothing until you're told to.
338 virtual void Start() OVERRIDE {}
340 // Finish starting a URL request whose job is an instance of
341 // URLRequestTestDelayedStartJob. It is illegal to call this routine
342 // with a URLRequest that does not use URLRequestTestDelayedStartJob.
343 static void CompleteStart(net::URLRequest* request) {
344 for (URLRequestTestDelayedStartJob* job = list_head_;
345 job;
346 job = job->next_) {
347 if (job->request() == request) {
348 job->net::URLRequestTestJob::Start();
349 return;
352 NOTREACHED();
355 static bool DelayedStartQueueEmpty() {
356 return !list_head_;
359 static void ClearQueue() {
360 if (list_head_) {
361 LOG(ERROR)
362 << "Unreleased entries on URLRequestTestDelayedStartJob delay queue"
363 << "; may result in leaks.";
364 list_head_ = NULL;
368 protected:
369 virtual ~URLRequestTestDelayedStartJob() {
370 for (URLRequestTestDelayedStartJob** job = &list_head_; *job;
371 job = &(*job)->next_) {
372 if (*job == this) {
373 *job = (*job)->next_;
374 return;
377 NOTREACHED();
380 private:
381 void Init() {
382 next_ = list_head_;
383 list_head_ = this;
386 static URLRequestTestDelayedStartJob* list_head_;
387 URLRequestTestDelayedStartJob* next_;
390 URLRequestTestDelayedStartJob*
391 URLRequestTestDelayedStartJob::list_head_ = NULL;
393 // This class is a variation on URLRequestTestJob in that it
394 // returns IO_pending errors before every read, not just the first one.
395 class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob {
396 public:
397 URLRequestTestDelayedCompletionJob(net::URLRequest* request,
398 net::NetworkDelegate* network_delegate)
399 : net::URLRequestTestJob(request, network_delegate) {}
400 URLRequestTestDelayedCompletionJob(net::URLRequest* request,
401 net::NetworkDelegate* network_delegate,
402 bool auto_advance)
403 : net::URLRequestTestJob(request, network_delegate, auto_advance) {}
404 URLRequestTestDelayedCompletionJob(net::URLRequest* request,
405 net::NetworkDelegate* network_delegate,
406 const std::string& response_headers,
407 const std::string& response_data,
408 bool auto_advance)
409 : net::URLRequestTestJob(request,
410 network_delegate,
411 response_headers,
412 response_data,
413 auto_advance) {}
415 protected:
416 virtual ~URLRequestTestDelayedCompletionJob() {}
418 private:
419 virtual bool NextReadAsync() OVERRIDE { return true; }
422 class URLRequestBigJob : public net::URLRequestSimpleJob {
423 public:
424 URLRequestBigJob(net::URLRequest* request,
425 net::NetworkDelegate* network_delegate)
426 : net::URLRequestSimpleJob(request, network_delegate) {
429 virtual int GetData(std::string* mime_type,
430 std::string* charset,
431 std::string* data,
432 const net::CompletionCallback& callback) const OVERRIDE {
433 *mime_type = "text/plain";
434 *charset = "UTF-8";
436 std::string text;
437 int count;
438 if (!ParseURL(request_->url(), &text, &count))
439 return net::ERR_INVALID_URL;
441 data->reserve(text.size() * count);
442 for (int i = 0; i < count; ++i)
443 data->append(text);
445 return net::OK;
448 private:
449 virtual ~URLRequestBigJob() {}
451 // big-job:substring,N
452 static bool ParseURL(const GURL& url, std::string* text, int* count) {
453 std::vector<std::string> parts;
454 base::SplitString(url.path(), ',', &parts);
456 if (parts.size() != 2)
457 return false;
459 *text = parts[0];
460 return base::StringToInt(parts[1], count);
464 class ResourceDispatcherHostTest;
466 class TestURLRequestJobFactory : public net::URLRequestJobFactory {
467 public:
468 explicit TestURLRequestJobFactory(ResourceDispatcherHostTest* test_fixture)
469 : test_fixture_(test_fixture),
470 delay_start_(false),
471 delay_complete_(false),
472 network_start_notification_(false),
473 url_request_jobs_created_count_(0) {
476 void HandleScheme(const std::string& scheme) {
477 supported_schemes_.insert(scheme);
480 int url_request_jobs_created_count() const {
481 return url_request_jobs_created_count_;
484 void SetDelayedStartJobGeneration(bool delay_job_start) {
485 delay_start_ = delay_job_start;
488 void SetDelayedCompleteJobGeneration(bool delay_job_complete) {
489 delay_complete_ = delay_job_complete;
492 void SetNetworkStartNotificationJobGeneration(bool notification) {
493 network_start_notification_ = notification;
496 virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
497 const std::string& scheme,
498 net::URLRequest* request,
499 net::NetworkDelegate* network_delegate) const OVERRIDE;
501 virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
502 return supported_schemes_.count(scheme) > 0;
505 virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
506 return supported_schemes_.count(url.scheme()) > 0;
509 virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
510 return false;
513 private:
514 ResourceDispatcherHostTest* test_fixture_;
515 bool delay_start_;
516 bool delay_complete_;
517 bool network_start_notification_;
518 mutable int url_request_jobs_created_count_;
519 std::set<std::string> supported_schemes_;
521 DISALLOW_COPY_AND_ASSIGN(TestURLRequestJobFactory);
524 // Associated with an URLRequest to determine if the URLRequest gets deleted.
525 class TestUserData : public base::SupportsUserData::Data {
526 public:
527 explicit TestUserData(bool* was_deleted)
528 : was_deleted_(was_deleted) {
531 virtual ~TestUserData() {
532 *was_deleted_ = true;
535 private:
536 bool* was_deleted_;
539 class TransfersAllNavigationsContentBrowserClient
540 : public TestContentBrowserClient {
541 public:
542 virtual bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context,
543 const GURL& current_url,
544 const GURL& new_url) OVERRIDE {
545 return true;
549 enum GenericResourceThrottleFlags {
550 NONE = 0,
551 DEFER_STARTING_REQUEST = 1 << 0,
552 DEFER_PROCESSING_RESPONSE = 1 << 1,
553 CANCEL_BEFORE_START = 1 << 2,
554 DEFER_NETWORK_START = 1 << 3
557 // Throttle that tracks the current throttle blocking a request. Only one
558 // can throttle any request at a time.
559 class GenericResourceThrottle : public ResourceThrottle {
560 public:
561 // The value is used to indicate that the throttle should not provide
562 // a error code when cancelling a request. net::OK is used, because this
563 // is not an error code.
564 static const int USE_DEFAULT_CANCEL_ERROR_CODE = net::OK;
566 GenericResourceThrottle(int flags, int code)
567 : flags_(flags),
568 error_code_for_cancellation_(code) {
571 virtual ~GenericResourceThrottle() {
572 if (active_throttle_ == this)
573 active_throttle_ = NULL;
576 // ResourceThrottle implementation:
577 virtual void WillStartRequest(bool* defer) OVERRIDE {
578 ASSERT_EQ(NULL, active_throttle_);
579 if (flags_ & DEFER_STARTING_REQUEST) {
580 active_throttle_ = this;
581 *defer = true;
584 if (flags_ & CANCEL_BEFORE_START) {
585 if (error_code_for_cancellation_ == USE_DEFAULT_CANCEL_ERROR_CODE) {
586 controller()->Cancel();
587 } else {
588 controller()->CancelWithError(error_code_for_cancellation_);
593 virtual void WillProcessResponse(bool* defer) OVERRIDE {
594 ASSERT_EQ(NULL, active_throttle_);
595 if (flags_ & DEFER_PROCESSING_RESPONSE) {
596 active_throttle_ = this;
597 *defer = true;
601 virtual void OnBeforeNetworkStart(bool* defer) OVERRIDE {
602 ASSERT_EQ(NULL, active_throttle_);
604 if (flags_ & DEFER_NETWORK_START) {
605 active_throttle_ = this;
606 *defer = true;
610 virtual const char* GetNameForLogging() const OVERRIDE {
611 return "GenericResourceThrottle";
614 void Resume() {
615 ASSERT_TRUE(this == active_throttle_);
616 active_throttle_ = NULL;
617 controller()->Resume();
620 static GenericResourceThrottle* active_throttle() {
621 return active_throttle_;
624 private:
625 int flags_; // bit-wise union of GenericResourceThrottleFlags.
626 int error_code_for_cancellation_;
628 // The currently active throttle, if any.
629 static GenericResourceThrottle* active_throttle_;
631 // static
632 GenericResourceThrottle* GenericResourceThrottle::active_throttle_ = NULL;
634 class TestResourceDispatcherHostDelegate
635 : public ResourceDispatcherHostDelegate {
636 public:
637 TestResourceDispatcherHostDelegate()
638 : create_two_throttles_(false),
639 flags_(NONE),
640 error_code_for_cancellation_(
641 GenericResourceThrottle::USE_DEFAULT_CANCEL_ERROR_CODE) {
644 void set_url_request_user_data(base::SupportsUserData::Data* user_data) {
645 user_data_.reset(user_data);
648 void set_flags(int value) {
649 flags_ = value;
652 void set_error_code_for_cancellation(int code) {
653 error_code_for_cancellation_ = code;
656 void set_create_two_throttles(bool create_two_throttles) {
657 create_two_throttles_ = create_two_throttles;
660 // ResourceDispatcherHostDelegate implementation:
662 virtual void RequestBeginning(
663 net::URLRequest* request,
664 ResourceContext* resource_context,
665 appcache::AppCacheService* appcache_service,
666 ResourceType::Type resource_type,
667 int child_id,
668 int route_id,
669 ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
670 if (user_data_) {
671 const void* key = user_data_.get();
672 request->SetUserData(key, user_data_.release());
675 if (flags_ != NONE) {
676 throttles->push_back(new GenericResourceThrottle(
677 flags_, error_code_for_cancellation_));
678 if (create_two_throttles_)
679 throttles->push_back(new GenericResourceThrottle(
680 flags_, error_code_for_cancellation_));
684 private:
685 bool create_two_throttles_;
686 int flags_;
687 int error_code_for_cancellation_;
688 scoped_ptr<base::SupportsUserData::Data> user_data_;
691 // Waits for a ShareableFileReference to be released.
692 class ShareableFileReleaseWaiter {
693 public:
694 ShareableFileReleaseWaiter(const base::FilePath& path) {
695 scoped_refptr<ShareableFileReference> file =
696 ShareableFileReference::Get(path);
697 file->AddFinalReleaseCallback(
698 base::Bind(&ShareableFileReleaseWaiter::Released,
699 base::Unretained(this)));
702 void Wait() {
703 loop_.Run();
706 private:
707 void Released(const base::FilePath& path) {
708 loop_.Quit();
711 base::RunLoop loop_;
713 DISALLOW_COPY_AND_ASSIGN(ShareableFileReleaseWaiter);
716 class ResourceDispatcherHostTest : public testing::Test,
717 public IPC::Sender {
718 public:
719 ResourceDispatcherHostTest()
720 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
721 old_factory_(NULL),
722 send_data_received_acks_(false) {
723 browser_context_.reset(new TestBrowserContext());
724 BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
725 base::RunLoop().RunUntilIdle();
726 filter_ = MakeForwardingFilter();
727 // TODO(cbentzel): Better way to get URLRequestContext?
728 net::URLRequestContext* request_context =
729 browser_context_->GetResourceContext()->GetRequestContext();
730 job_factory_.reset(new TestURLRequestJobFactory(this));
731 request_context->set_job_factory(job_factory_.get());
732 request_context->set_network_delegate(&network_delegate_);
735 // IPC::Sender implementation
736 virtual bool Send(IPC::Message* msg) OVERRIDE {
737 accum_.AddMessage(*msg);
739 if (send_data_received_acks_ &&
740 msg->type() == ResourceMsg_DataReceived::ID) {
741 GenerateDataReceivedACK(*msg);
744 if (wait_for_request_complete_loop_ &&
745 msg->type() == ResourceMsg_RequestComplete::ID) {
746 wait_for_request_complete_loop_->Quit();
749 // Do not release handles in it yet; the accumulator owns them now.
750 delete msg;
751 return true;
754 protected:
755 friend class TestURLRequestJobFactory;
757 // testing::Test
758 virtual void SetUp() OVERRIDE {
759 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0);
760 HandleScheme("test");
763 virtual void TearDown() {
764 EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty());
765 URLRequestTestDelayedStartJob::ClearQueue();
767 for (std::set<int>::iterator it = child_ids_.begin();
768 it != child_ids_.end(); ++it) {
769 host_.CancelRequestsForProcess(*it);
772 host_.Shutdown();
774 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(0);
776 // Flush the message loop to make application verifiers happy.
777 if (ResourceDispatcherHostImpl::Get())
778 ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(
779 browser_context_->GetResourceContext());
781 WorkerServiceImpl::GetInstance()->PerformTeardownForTesting();
783 browser_context_.reset();
784 base::RunLoop().RunUntilIdle();
787 // Creates a new ForwardingFilter and registers it with |child_ids_| so as not
788 // to leak per-child state on test shutdown.
789 ForwardingFilter* MakeForwardingFilter() {
790 ForwardingFilter* filter =
791 new ForwardingFilter(this, browser_context_->GetResourceContext());
792 child_ids_.insert(filter->child_id());
793 return filter;
796 // Creates a request using the current test object as the filter and
797 // SubResource as the resource type.
798 void MakeTestRequest(int render_view_id,
799 int request_id,
800 const GURL& url);
802 // Generates a request using the given filter and resource type.
803 void MakeTestRequestWithResourceType(ResourceMessageFilter* filter,
804 int render_view_id, int request_id,
805 const GURL& url,
806 ResourceType::Type type);
808 void CancelRequest(int request_id);
809 void RendererCancelRequest(int request_id) {
810 ResourceMessageFilter* old_filter = SetFilter(filter_.get());
811 host_.OnCancelRequest(request_id);
812 SetFilter(old_filter);
815 void CompleteStartRequest(int request_id);
816 void CompleteStartRequest(ResourceMessageFilter* filter, int request_id);
818 net::TestNetworkDelegate* network_delegate() { return &network_delegate_; }
820 void EnsureSchemeIsAllowed(const std::string& scheme) {
821 ChildProcessSecurityPolicyImpl* policy =
822 ChildProcessSecurityPolicyImpl::GetInstance();
823 if (!policy->IsWebSafeScheme(scheme))
824 policy->RegisterWebSafeScheme(scheme);
827 // Sets a particular response for any request from now on. To switch back to
828 // the default bahavior, pass an empty |headers|. |headers| should be raw-
829 // formatted (NULLs instead of EOLs).
830 void SetResponse(const std::string& headers, const std::string& data) {
831 response_headers_ = net::HttpUtil::AssembleRawHeaders(headers.data(),
832 headers.size());
833 response_data_ = data;
835 void SetResponse(const std::string& headers) {
836 SetResponse(headers, std::string());
839 void SendDataReceivedACKs(bool send_acks) {
840 send_data_received_acks_ = send_acks;
843 // Intercepts requests for the given protocol.
844 void HandleScheme(const std::string& scheme) {
845 job_factory_->HandleScheme(scheme);
846 EnsureSchemeIsAllowed(scheme);
849 void GenerateDataReceivedACK(const IPC::Message& msg) {
850 EXPECT_EQ(ResourceMsg_DataReceived::ID, msg.type());
852 int request_id = -1;
853 bool result = PickleIterator(msg).ReadInt(&request_id);
854 DCHECK(result);
855 scoped_ptr<IPC::Message> ack(
856 new ResourceHostMsg_DataReceived_ACK(request_id));
858 base::MessageLoop::current()->PostTask(
859 FROM_HERE,
860 base::Bind(&GenerateIPCMessage, filter_, base::Passed(&ack)));
863 // Setting filters for testing renderer messages.
864 // Returns the previous filter.
865 ResourceMessageFilter* SetFilter(ResourceMessageFilter* new_filter) {
866 ResourceMessageFilter* old_filter = host_.filter_;
867 host_.filter_ = new_filter;
868 return old_filter;
871 void WaitForRequestComplete() {
872 DCHECK(!wait_for_request_complete_loop_);
873 wait_for_request_complete_loop_.reset(new base::RunLoop);
874 wait_for_request_complete_loop_->Run();
875 wait_for_request_complete_loop_.reset();
878 content::TestBrowserThreadBundle thread_bundle_;
879 scoped_ptr<TestBrowserContext> browser_context_;
880 scoped_ptr<TestURLRequestJobFactory> job_factory_;
881 scoped_refptr<ForwardingFilter> filter_;
882 net::TestNetworkDelegate network_delegate_;
883 ResourceDispatcherHostImpl host_;
884 ResourceIPCAccumulator accum_;
885 std::string response_headers_;
886 std::string response_data_;
887 std::string scheme_;
888 net::URLRequest::ProtocolFactory* old_factory_;
889 bool send_data_received_acks_;
890 std::set<int> child_ids_;
891 scoped_ptr<base::RunLoop> wait_for_request_complete_loop_;
894 void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
895 int request_id,
896 const GURL& url) {
897 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
898 url, ResourceType::SUB_RESOURCE);
901 void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
902 ResourceMessageFilter* filter,
903 int render_view_id,
904 int request_id,
905 const GURL& url,
906 ResourceType::Type type) {
907 ResourceHostMsg_Request request =
908 CreateResourceRequest("GET", type, url);
909 ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
910 host_.OnMessageReceived(msg, filter);
911 KickOffRequest();
914 void ResourceDispatcherHostTest::CancelRequest(int request_id) {
915 host_.CancelRequest(filter_->child_id(), request_id);
918 void ResourceDispatcherHostTest::CompleteStartRequest(int request_id) {
919 CompleteStartRequest(filter_.get(), request_id);
922 void ResourceDispatcherHostTest::CompleteStartRequest(
923 ResourceMessageFilter* filter,
924 int request_id) {
925 GlobalRequestID gid(filter->child_id(), request_id);
926 net::URLRequest* req = host_.GetURLRequest(gid);
927 EXPECT_TRUE(req);
928 if (req)
929 URLRequestTestDelayedStartJob::CompleteStart(req);
932 void CheckRequestCompleteErrorCode(const IPC::Message& message,
933 int expected_error_code) {
934 // Verify the expected error code was received.
935 int request_id;
936 int error_code;
938 ASSERT_EQ(ResourceMsg_RequestComplete::ID, message.type());
940 PickleIterator iter(message);
941 ASSERT_TRUE(IPC::ReadParam(&message, &iter, &request_id));
942 ASSERT_TRUE(IPC::ReadParam(&message, &iter, &error_code));
943 ASSERT_EQ(expected_error_code, error_code);
946 testing::AssertionResult ExtractDataOffsetAndLength(const IPC::Message& message,
947 int* data_offset,
948 int* data_length) {
949 PickleIterator iter(message);
950 int request_id;
951 if (!IPC::ReadParam(&message, &iter, &request_id))
952 return testing::AssertionFailure() << "Could not read request_id";
953 if (!IPC::ReadParam(&message, &iter, data_offset))
954 return testing::AssertionFailure() << "Could not read data_offset";
955 if (!IPC::ReadParam(&message, &iter, data_length))
956 return testing::AssertionFailure() << "Could not read data_length";
957 return testing::AssertionSuccess();
960 void CheckSuccessfulRequestWithErrorCode(
961 const std::vector<IPC::Message>& messages,
962 const std::string& reference_data,
963 int expected_error) {
964 // A successful request will have received 4 messages:
965 // ReceivedResponse (indicates headers received)
966 // SetDataBuffer (contains shared memory handle)
967 // DataReceived (data offset and length into shared memory)
968 // RequestComplete (request is done)
970 // This function verifies that we received 4 messages and that they are
971 // appropriate. It allows for an error code other than net::OK if the request
972 // should successfully receive data and then abort, e.g., on cancel.
973 ASSERT_EQ(4U, messages.size());
975 // The first messages should be received response
976 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
978 ASSERT_EQ(ResourceMsg_SetDataBuffer::ID, messages[1].type());
980 PickleIterator iter(messages[1]);
981 int request_id;
982 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &request_id));
983 base::SharedMemoryHandle shm_handle;
984 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &shm_handle));
985 int shm_size;
986 ASSERT_TRUE(IPC::ReadParam(&messages[1], &iter, &shm_size));
988 // Followed by the data, currently we only do the data in one chunk, but
989 // should probably test multiple chunks later
990 ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2].type());
992 int data_offset;
993 int data_length;
994 ASSERT_TRUE(
995 ExtractDataOffsetAndLength(messages[2], &data_offset, &data_length));
997 ASSERT_EQ(reference_data.size(), static_cast<size_t>(data_length));
998 ASSERT_GE(shm_size, data_length);
1000 base::SharedMemory shared_mem(shm_handle, true); // read only
1001 shared_mem.Map(data_length);
1002 const char* data = static_cast<char*>(shared_mem.memory()) + data_offset;
1003 ASSERT_EQ(0, memcmp(reference_data.c_str(), data, data_length));
1005 // The last message should be all data received.
1006 CheckRequestCompleteErrorCode(messages[3], expected_error);
1009 void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages,
1010 const std::string& reference_data) {
1011 CheckSuccessfulRequestWithErrorCode(messages, reference_data, net::OK);
1014 void CheckSuccessfulRedirect(const std::vector<IPC::Message>& messages,
1015 const std::string& reference_data) {
1016 ASSERT_EQ(5U, messages.size());
1017 ASSERT_EQ(ResourceMsg_ReceivedRedirect::ID, messages[0].type());
1019 const std::vector<IPC::Message> second_req_msgs =
1020 std::vector<IPC::Message>(messages.begin() + 1, messages.end());
1021 CheckSuccessfulRequest(second_req_msgs, reference_data);
1024 void CheckFailedRequest(const std::vector<IPC::Message>& messages,
1025 const std::string& reference_data,
1026 int expected_error) {
1027 ASSERT_LT(0U, messages.size());
1028 ASSERT_GE(2U, messages.size());
1029 size_t failure_index = messages.size() - 1;
1031 if (messages.size() == 2) {
1032 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
1035 CheckRequestCompleteErrorCode(messages[failure_index], expected_error);
1038 // Tests whether many messages get dispatched properly.
1039 TEST_F(ResourceDispatcherHostTest, TestMany) {
1040 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1041 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1042 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1043 MakeTestRequestWithResourceType(filter_.get(), 0, 4,
1044 net::URLRequestTestJob::test_url_4(),
1045 ResourceType::PREFETCH); // detachable type
1046 MakeTestRequest(0, 5, net::URLRequestTestJob::test_url_redirect_to_url_2());
1048 // Finish the redirection
1049 ResourceHostMsg_FollowRedirect redirect_msg(5);
1050 host_.OnMessageReceived(redirect_msg, filter_.get());
1051 base::MessageLoop::current()->RunUntilIdle();
1053 // flush all the pending requests
1054 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1056 // sorts out all the messages we saw by request
1057 ResourceIPCAccumulator::ClassifiedMessages msgs;
1058 accum_.GetClassifiedMessages(&msgs);
1060 // there are five requests, so we should have gotten them classified as such
1061 ASSERT_EQ(5U, msgs.size());
1063 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1064 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_2());
1065 CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
1066 CheckSuccessfulRequest(msgs[3], net::URLRequestTestJob::test_data_4());
1067 CheckSuccessfulRedirect(msgs[4], net::URLRequestTestJob::test_data_2());
1070 // Tests whether messages get canceled properly. We issue four requests,
1071 // cancel two of them, and make sure that each sent the proper notifications.
1072 TEST_F(ResourceDispatcherHostTest, Cancel) {
1073 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1074 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1075 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1077 MakeTestRequestWithResourceType(filter_.get(), 0, 4,
1078 net::URLRequestTestJob::test_url_4(),
1079 ResourceType::PREFETCH); // detachable type
1081 CancelRequest(2);
1083 // Cancel request must come from the renderer for a detachable resource to
1084 // delay.
1085 RendererCancelRequest(4);
1087 // The handler should have been detached now.
1088 GlobalRequestID global_request_id(filter_->child_id(), 4);
1089 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
1090 host_.GetURLRequest(global_request_id));
1091 ASSERT_TRUE(info->detachable_handler()->is_detached());
1093 // flush all the pending requests
1094 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1095 base::MessageLoop::current()->RunUntilIdle();
1097 // Everything should be out now.
1098 EXPECT_EQ(0, host_.pending_requests());
1100 ResourceIPCAccumulator::ClassifiedMessages msgs;
1101 accum_.GetClassifiedMessages(&msgs);
1103 // there are four requests, so we should have gotten them classified as such
1104 ASSERT_EQ(4U, msgs.size());
1106 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1107 CheckSuccessfulRequest(msgs[2], net::URLRequestTestJob::test_data_3());
1109 // Check that request 2 and 4 got canceled, as far as the renderer is
1110 // concerned. Request 2 will have been deleted.
1111 ASSERT_EQ(1U, msgs[1].size());
1112 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
1114 ASSERT_EQ(2U, msgs[3].size());
1115 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[3][0].type());
1116 CheckRequestCompleteErrorCode(msgs[3][1], net::ERR_ABORTED);
1118 // However, request 4 should have actually gone to completion. (Only request 2
1119 // was canceled.)
1120 EXPECT_EQ(4, network_delegate()->completed_requests());
1121 EXPECT_EQ(1, network_delegate()->canceled_requests());
1122 EXPECT_EQ(0, network_delegate()->error_count());
1125 // Shows that detachable requests will timeout if the request takes too long to
1126 // complete.
1127 TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
1128 MakeTestRequestWithResourceType(filter_.get(), 0, 1,
1129 net::URLRequestTestJob::test_url_2(),
1130 ResourceType::PREFETCH); // detachable type
1131 GlobalRequestID global_request_id(filter_->child_id(), 1);
1132 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
1133 host_.GetURLRequest(global_request_id));
1134 ASSERT_TRUE(info->detachable_handler());
1135 info->detachable_handler()->set_cancel_delay(
1136 base::TimeDelta::FromMilliseconds(200));
1137 base::MessageLoop::current()->RunUntilIdle();
1139 RendererCancelRequest(1);
1141 // From the renderer's perspective, the request was cancelled.
1142 ResourceIPCAccumulator::ClassifiedMessages msgs;
1143 accum_.GetClassifiedMessages(&msgs);
1144 ASSERT_EQ(1U, msgs.size());
1145 ASSERT_EQ(2U, msgs[0].size());
1146 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
1147 CheckRequestCompleteErrorCode(msgs[0][1], net::ERR_ABORTED);
1149 // But it continues detached.
1150 EXPECT_EQ(1, host_.pending_requests());
1151 EXPECT_TRUE(info->detachable_handler()->is_detached());
1153 // Wait until after the delay timer times out before we start processing any
1154 // messages.
1155 base::OneShotTimer<base::MessageLoop> timer;
1156 timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
1157 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
1158 base::MessageLoop::current()->Run();
1160 // The prefetch should be cancelled by now.
1161 EXPECT_EQ(0, host_.pending_requests());
1162 EXPECT_EQ(1, network_delegate()->completed_requests());
1163 EXPECT_EQ(1, network_delegate()->canceled_requests());
1164 EXPECT_EQ(0, network_delegate()->error_count());
1167 // If the filter has disappeared then detachable resources should continue to
1168 // load.
1169 TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
1170 // test_url_1's data is available synchronously, so use 2 and 3.
1171 ResourceHostMsg_Request request_prefetch = CreateResourceRequest(
1172 "GET", ResourceType::PREFETCH, net::URLRequestTestJob::test_url_2());
1173 ResourceHostMsg_Request request_ping = CreateResourceRequest(
1174 "GET", ResourceType::PING, net::URLRequestTestJob::test_url_3());
1176 ResourceHostMsg_RequestResource msg_prefetch(0, 1, request_prefetch);
1177 host_.OnMessageReceived(msg_prefetch, filter_);
1178 ResourceHostMsg_RequestResource msg_ping(0, 2, request_ping);
1179 host_.OnMessageReceived(msg_ping, filter_);
1181 // Remove the filter before processing the requests by simulating channel
1182 // closure.
1183 ResourceRequestInfoImpl* info_prefetch = ResourceRequestInfoImpl::ForRequest(
1184 host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
1185 ResourceRequestInfoImpl* info_ping = ResourceRequestInfoImpl::ForRequest(
1186 host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 2)));
1187 DCHECK_EQ(filter_.get(), info_prefetch->filter());
1188 DCHECK_EQ(filter_.get(), info_ping->filter());
1189 filter_->OnChannelClosing();
1190 info_prefetch->filter_.reset();
1191 info_ping->filter_.reset();
1193 // From the renderer's perspective, the requests were cancelled.
1194 ResourceIPCAccumulator::ClassifiedMessages msgs;
1195 accum_.GetClassifiedMessages(&msgs);
1196 ASSERT_EQ(2U, msgs.size());
1197 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
1198 CheckRequestCompleteErrorCode(msgs[1][0], net::ERR_ABORTED);
1200 // But it continues detached.
1201 EXPECT_EQ(2, host_.pending_requests());
1202 EXPECT_TRUE(info_prefetch->detachable_handler()->is_detached());
1203 EXPECT_TRUE(info_ping->detachable_handler()->is_detached());
1205 KickOffRequest();
1207 // Make sure the requests weren't canceled early.
1208 EXPECT_EQ(2, host_.pending_requests());
1210 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1211 base::MessageLoop::current()->RunUntilIdle();
1213 EXPECT_EQ(0, host_.pending_requests());
1214 EXPECT_EQ(2, network_delegate()->completed_requests());
1215 EXPECT_EQ(0, network_delegate()->canceled_requests());
1216 EXPECT_EQ(0, network_delegate()->error_count());
1219 // If the filter has disappeared (original process dies) then detachable
1220 // resources should continue to load, even when redirected.
1221 TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
1222 ResourceHostMsg_Request request = CreateResourceRequest(
1223 "GET", ResourceType::PREFETCH,
1224 net::URLRequestTestJob::test_url_redirect_to_url_2());
1226 ResourceHostMsg_RequestResource msg(0, 1, request);
1227 host_.OnMessageReceived(msg, filter_);
1229 // Remove the filter before processing the request by simulating channel
1230 // closure.
1231 GlobalRequestID global_request_id(filter_->child_id(), 1);
1232 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
1233 host_.GetURLRequest(global_request_id));
1234 info->filter_->OnChannelClosing();
1235 info->filter_.reset();
1237 // From the renderer's perspective, the request was cancelled.
1238 ResourceIPCAccumulator::ClassifiedMessages msgs;
1239 accum_.GetClassifiedMessages(&msgs);
1240 ASSERT_EQ(1U, msgs.size());
1241 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
1243 // But it continues detached.
1244 EXPECT_EQ(1, host_.pending_requests());
1245 EXPECT_TRUE(info->detachable_handler()->is_detached());
1247 // Verify no redirects before resetting the filter.
1248 net::URLRequest* url_request = host_.GetURLRequest(global_request_id);
1249 EXPECT_EQ(1u, url_request->url_chain().size());
1250 KickOffRequest();
1252 // Verify that a redirect was followed.
1253 EXPECT_EQ(2u, url_request->url_chain().size());
1255 // Make sure the request wasn't canceled early.
1256 EXPECT_EQ(1, host_.pending_requests());
1258 // Finish up the request.
1259 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1260 base::MessageLoop::current()->RunUntilIdle();
1262 EXPECT_EQ(0, host_.pending_requests());
1263 EXPECT_EQ(1, network_delegate()->completed_requests());
1264 EXPECT_EQ(0, network_delegate()->canceled_requests());
1265 EXPECT_EQ(0, network_delegate()->error_count());
1268 TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
1269 bool was_deleted = false;
1271 // Arrange to have requests deferred before starting.
1272 TestResourceDispatcherHostDelegate delegate;
1273 delegate.set_flags(DEFER_STARTING_REQUEST);
1274 delegate.set_url_request_user_data(new TestUserData(&was_deleted));
1275 host_.SetDelegate(&delegate);
1277 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1278 // We cancel from the renderer because all non-renderer cancels delete
1279 // the request synchronously.
1280 RendererCancelRequest(1);
1282 // Our TestResourceThrottle should not have been deleted yet. This is to
1283 // ensure that destruction of the URLRequest happens asynchronously to
1284 // calling CancelRequest.
1285 EXPECT_FALSE(was_deleted);
1287 base::MessageLoop::current()->RunUntilIdle();
1289 EXPECT_TRUE(was_deleted);
1292 TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
1293 bool was_deleted = false;
1295 // Arrange to have requests deferred before starting.
1296 TestResourceDispatcherHostDelegate delegate;
1297 delegate.set_flags(DEFER_STARTING_REQUEST);
1298 delegate.set_url_request_user_data(new TestUserData(&was_deleted));
1299 host_.SetDelegate(&delegate);
1301 MakeTestRequestWithResourceType(filter_.get(), 0, 1,
1302 net::URLRequestTestJob::test_url_1(),
1303 ResourceType::PREFETCH); // detachable type
1304 // Cancel request must come from the renderer for a detachable resource to
1305 // detach.
1306 RendererCancelRequest(1);
1308 // Even after driving the event loop, the request has not been deleted.
1309 EXPECT_FALSE(was_deleted);
1311 // However, it is still throttled because the defer happened above the
1312 // DetachableResourceHandler.
1313 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1314 base::MessageLoop::current()->RunUntilIdle();
1315 EXPECT_FALSE(was_deleted);
1317 // Resume the request.
1318 GenericResourceThrottle* throttle =
1319 GenericResourceThrottle::active_throttle();
1320 ASSERT_TRUE(throttle);
1321 throttle->Resume();
1323 // Now, the request completes.
1324 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1325 base::MessageLoop::current()->RunUntilIdle();
1326 EXPECT_TRUE(was_deleted);
1327 EXPECT_EQ(1, network_delegate()->completed_requests());
1328 EXPECT_EQ(0, network_delegate()->canceled_requests());
1329 EXPECT_EQ(0, network_delegate()->error_count());
1332 // Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
1333 // URLRequest will not be started.
1334 TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
1335 TestResourceDispatcherHostDelegate delegate;
1336 delegate.set_flags(CANCEL_BEFORE_START);
1337 host_.SetDelegate(&delegate);
1339 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1341 // flush all the pending requests
1342 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1343 base::MessageLoop::current()->RunUntilIdle();
1345 ResourceIPCAccumulator::ClassifiedMessages msgs;
1346 accum_.GetClassifiedMessages(&msgs);
1348 // Check that request got canceled.
1349 ASSERT_EQ(1U, msgs[0].size());
1350 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ABORTED);
1352 // Make sure URLRequest is never started.
1353 EXPECT_EQ(0, job_factory_->url_request_jobs_created_count());
1356 TEST_F(ResourceDispatcherHostTest, PausedStartError) {
1357 // Arrange to have requests deferred before processing response headers.
1358 TestResourceDispatcherHostDelegate delegate;
1359 delegate.set_flags(DEFER_PROCESSING_RESPONSE);
1360 host_.SetDelegate(&delegate);
1362 job_factory_->SetDelayedStartJobGeneration(true);
1363 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_error());
1364 CompleteStartRequest(1);
1366 // flush all the pending requests
1367 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1368 base::MessageLoop::current()->RunUntilIdle();
1370 EXPECT_EQ(0, host_.pending_requests());
1373 // Test the OnBeforeNetworkStart throttle.
1374 TEST_F(ResourceDispatcherHostTest, ThrottleNetworkStart) {
1375 // Arrange to have requests deferred before processing response headers.
1376 TestResourceDispatcherHostDelegate delegate;
1377 delegate.set_flags(DEFER_NETWORK_START);
1378 host_.SetDelegate(&delegate);
1380 job_factory_->SetNetworkStartNotificationJobGeneration(true);
1381 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_2());
1383 // Should have deferred for network start.
1384 GenericResourceThrottle* first_throttle =
1385 GenericResourceThrottle::active_throttle();
1386 ASSERT_TRUE(first_throttle);
1387 EXPECT_EQ(0, network_delegate()->completed_requests());
1388 EXPECT_EQ(1, host_.pending_requests());
1390 first_throttle->Resume();
1392 // Flush all the pending requests.
1393 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1394 base::MessageLoop::current()->RunUntilIdle();
1396 EXPECT_EQ(1, network_delegate()->completed_requests());
1397 EXPECT_EQ(0, host_.pending_requests());
1400 TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
1401 // Arrange to have requests deferred before starting.
1402 TestResourceDispatcherHostDelegate delegate;
1403 delegate.set_flags(DEFER_STARTING_REQUEST);
1404 delegate.set_create_two_throttles(true);
1405 host_.SetDelegate(&delegate);
1407 // Make sure the first throttle blocked the request, and then resume.
1408 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1409 GenericResourceThrottle* first_throttle =
1410 GenericResourceThrottle::active_throttle();
1411 ASSERT_TRUE(first_throttle);
1412 first_throttle->Resume();
1414 // Make sure the second throttle blocked the request, and then resume.
1415 ASSERT_TRUE(GenericResourceThrottle::active_throttle());
1416 ASSERT_NE(first_throttle, GenericResourceThrottle::active_throttle());
1417 GenericResourceThrottle::active_throttle()->Resume();
1419 ASSERT_FALSE(GenericResourceThrottle::active_throttle());
1421 // The request is started asynchronously.
1422 base::MessageLoop::current()->RunUntilIdle();
1424 // Flush all the pending requests.
1425 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1427 EXPECT_EQ(0, host_.pending_requests());
1429 // Make sure the request completed successfully.
1430 ResourceIPCAccumulator::ClassifiedMessages msgs;
1431 accum_.GetClassifiedMessages(&msgs);
1432 ASSERT_EQ(1U, msgs.size());
1433 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1437 // Tests that the delegate can cancel a request and provide a error code.
1438 TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
1439 TestResourceDispatcherHostDelegate delegate;
1440 delegate.set_flags(CANCEL_BEFORE_START);
1441 delegate.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED);
1442 host_.SetDelegate(&delegate);
1444 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1445 // The request will get cancelled by the throttle.
1447 // flush all the pending requests
1448 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1449 base::MessageLoop::current()->RunUntilIdle();
1451 ResourceIPCAccumulator::ClassifiedMessages msgs;
1452 accum_.GetClassifiedMessages(&msgs);
1454 // Check the cancellation
1455 ASSERT_EQ(1U, msgs.size());
1456 ASSERT_EQ(1U, msgs[0].size());
1458 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED);
1461 // Tests CancelRequestsForProcess
1462 TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
1463 scoped_refptr<TestFilter> test_filter = new TestFilter(
1464 browser_context_->GetResourceContext());
1465 child_ids_.insert(test_filter->child_id());
1467 // request 1 goes to the test delegate
1468 ResourceHostMsg_Request request = CreateResourceRequest(
1469 "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
1471 MakeTestRequestWithResourceType(test_filter.get(), 0, 1,
1472 net::URLRequestTestJob::test_url_1(),
1473 ResourceType::SUB_RESOURCE);
1475 // request 2 goes to us
1476 MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
1478 // request 3 goes to the test delegate
1479 MakeTestRequestWithResourceType(test_filter.get(), 0, 3,
1480 net::URLRequestTestJob::test_url_3(),
1481 ResourceType::SUB_RESOURCE);
1483 // request 4 goes to us
1484 MakeTestRequestWithResourceType(filter_.get(), 0, 4,
1485 net::URLRequestTestJob::test_url_4(),
1486 ResourceType::PREFETCH); // detachable type
1489 // Make sure all requests have finished stage one. test_url_1 will have
1490 // finished.
1491 base::MessageLoop::current()->RunUntilIdle();
1493 // TODO(mbelshe):
1494 // Now that the async IO path is in place, the IO always completes on the
1495 // initial call; so the requests have already completed. This basically
1496 // breaks the whole test.
1497 //EXPECT_EQ(3, host_.pending_requests());
1499 // Process test_url_2 and test_url_3 for one level so one callback is called.
1500 // We'll cancel test_url_4 (detachable) before processing it to verify that it
1501 // delays the cancel.
1502 for (int i = 0; i < 2; i++)
1503 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
1505 // Cancel the requests to the test process.
1506 host_.CancelRequestsForProcess(filter_->child_id());
1507 test_filter->set_canceled(true);
1509 // The requests should all be cancelled, except request 4, which is detached.
1510 EXPECT_EQ(1, host_.pending_requests());
1511 GlobalRequestID global_request_id(filter_->child_id(), 4);
1512 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
1513 host_.GetURLRequest(global_request_id));
1514 ASSERT_TRUE(info->detachable_handler()->is_detached());
1516 // Flush all the pending requests.
1517 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1519 EXPECT_EQ(0, host_.pending_requests());
1521 // The test delegate should not have gotten any messages after being canceled.
1522 ASSERT_EQ(0, test_filter->received_after_canceled());
1524 // There should be two results.
1525 ResourceIPCAccumulator::ClassifiedMessages msgs;
1526 accum_.GetClassifiedMessages(&msgs);
1527 ASSERT_EQ(2U, msgs.size());
1528 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
1529 // The detachable request was cancelled by the renderer before it
1530 // finished. From the perspective of the renderer, it should have cancelled.
1531 ASSERT_EQ(2U, msgs[1].size());
1532 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
1533 CheckRequestCompleteErrorCode(msgs[1][1], net::ERR_ABORTED);
1534 // But it completed anyway. For the network stack, no requests were canceled.
1535 EXPECT_EQ(4, network_delegate()->completed_requests());
1536 EXPECT_EQ(0, network_delegate()->canceled_requests());
1537 EXPECT_EQ(0, network_delegate()->error_count());
1540 TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
1541 MakeTestRequestWithResourceType(filter_.get(), 0, 1,
1542 net::URLRequestTestJob::test_url_4(),
1543 ResourceType::PREFETCH); // detachable type
1544 GlobalRequestID global_request_id(filter_->child_id(), 1);
1545 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
1546 host_.GetURLRequest(global_request_id));
1547 ASSERT_TRUE(info->detachable_handler());
1548 info->detachable_handler()->set_cancel_delay(
1549 base::TimeDelta::FromMilliseconds(200));
1550 base::MessageLoop::current()->RunUntilIdle();
1552 // Cancel the requests to the test process.
1553 host_.CancelRequestsForProcess(filter_->child_id());
1554 EXPECT_EQ(1, host_.pending_requests());
1556 // Wait until after the delay timer times out before we start processing any
1557 // messages.
1558 base::OneShotTimer<base::MessageLoop> timer;
1559 timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(210),
1560 base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
1561 base::MessageLoop::current()->Run();
1563 // The prefetch should be cancelled by now.
1564 EXPECT_EQ(0, host_.pending_requests());
1566 // In case any messages are still to be processed.
1567 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1568 base::MessageLoop::current()->RunUntilIdle();
1570 ResourceIPCAccumulator::ClassifiedMessages msgs;
1571 accum_.GetClassifiedMessages(&msgs);
1573 ASSERT_EQ(1U, msgs.size());
1575 // The request should have cancelled.
1576 ASSERT_EQ(2U, msgs[0].size());
1577 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
1578 CheckRequestCompleteErrorCode(msgs[0][1], net::ERR_ABORTED);
1579 // And not run to completion.
1580 EXPECT_EQ(1, network_delegate()->completed_requests());
1581 EXPECT_EQ(1, network_delegate()->canceled_requests());
1582 EXPECT_EQ(0, network_delegate()->error_count());
1585 // Tests blocking and resuming requests.
1586 TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
1587 host_.BlockRequestsForRoute(filter_->child_id(), 1);
1588 host_.BlockRequestsForRoute(filter_->child_id(), 2);
1589 host_.BlockRequestsForRoute(filter_->child_id(), 3);
1591 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1592 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1593 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1594 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1595 MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
1596 MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
1598 // Flush all the pending requests
1599 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1601 // Sort out all the messages we saw by request
1602 ResourceIPCAccumulator::ClassifiedMessages msgs;
1603 accum_.GetClassifiedMessages(&msgs);
1605 // All requests but the 2 for the RVH 0 should have been blocked.
1606 ASSERT_EQ(2U, msgs.size());
1608 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1609 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
1611 // Resume requests for RVH 1 and flush pending requests.
1612 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 1);
1613 KickOffRequest();
1614 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1616 msgs.clear();
1617 accum_.GetClassifiedMessages(&msgs);
1618 ASSERT_EQ(2U, msgs.size());
1619 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
1620 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_1());
1622 // Test that new requests are not blocked for RVH 1.
1623 MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
1624 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1625 msgs.clear();
1626 accum_.GetClassifiedMessages(&msgs);
1627 ASSERT_EQ(1U, msgs.size());
1628 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1630 // Now resumes requests for all RVH (2 and 3).
1631 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 2);
1632 host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 3);
1633 KickOffRequest();
1634 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1636 msgs.clear();
1637 accum_.GetClassifiedMessages(&msgs);
1638 ASSERT_EQ(2U, msgs.size());
1639 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
1640 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
1643 // Tests blocking and canceling requests.
1644 TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
1645 host_.BlockRequestsForRoute(filter_->child_id(), 1);
1647 MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
1648 MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
1649 MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
1650 MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
1651 // Blocked detachable resources should not delay cancellation.
1652 MakeTestRequestWithResourceType(filter_.get(), 1, 5,
1653 net::URLRequestTestJob::test_url_4(),
1654 ResourceType::PREFETCH); // detachable type
1656 // Flush all the pending requests.
1657 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1659 // Sort out all the messages we saw by request.
1660 ResourceIPCAccumulator::ClassifiedMessages msgs;
1661 accum_.GetClassifiedMessages(&msgs);
1663 // The 2 requests for the RVH 0 should have been processed.
1664 ASSERT_EQ(2U, msgs.size());
1666 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1667 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
1669 // Cancel requests for RVH 1.
1670 host_.CancelBlockedRequestsForRoute(filter_->child_id(), 1);
1671 KickOffRequest();
1672 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1674 msgs.clear();
1675 accum_.GetClassifiedMessages(&msgs);
1676 ASSERT_EQ(0U, msgs.size());
1679 // Tests that blocked requests are canceled if their associated process dies.
1680 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
1681 // This second filter is used to emulate a second process.
1682 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
1684 host_.BlockRequestsForRoute(second_filter->child_id(), 0);
1686 MakeTestRequestWithResourceType(filter_.get(), 0, 1,
1687 net::URLRequestTestJob::test_url_1(),
1688 ResourceType::SUB_RESOURCE);
1689 MakeTestRequestWithResourceType(second_filter.get(), 0, 2,
1690 net::URLRequestTestJob::test_url_2(),
1691 ResourceType::SUB_RESOURCE);
1692 MakeTestRequestWithResourceType(filter_.get(), 0, 3,
1693 net::URLRequestTestJob::test_url_3(),
1694 ResourceType::SUB_RESOURCE);
1695 MakeTestRequestWithResourceType(second_filter.get(), 0, 4,
1696 net::URLRequestTestJob::test_url_1(),
1697 ResourceType::SUB_RESOURCE);
1698 MakeTestRequestWithResourceType(second_filter.get(), 0, 5,
1699 net::URLRequestTestJob::test_url_4(),
1700 ResourceType::PREFETCH); // detachable type
1702 // Simulate process death.
1703 host_.CancelRequestsForProcess(second_filter->child_id());
1705 // Flush all the pending requests.
1706 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1708 // Sort out all the messages we saw by request.
1709 ResourceIPCAccumulator::ClassifiedMessages msgs;
1710 accum_.GetClassifiedMessages(&msgs);
1712 // The 2 requests for the RVH 0 should have been processed. Note that
1713 // blocked detachable requests are canceled without delay.
1714 ASSERT_EQ(2U, msgs.size());
1716 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
1717 CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
1719 EXPECT_TRUE(host_.blocked_loaders_map_.empty());
1722 // Tests that blocked requests don't leak when the ResourceDispatcherHost goes
1723 // away. Note that we rely on Purify for finding the leaks if any.
1724 // If this test turns the Purify bot red, check the ResourceDispatcherHost
1725 // destructor to make sure the blocked requests are deleted.
1726 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
1727 // This second filter is used to emulate a second process.
1728 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
1730 host_.BlockRequestsForRoute(filter_->child_id(), 1);
1731 host_.BlockRequestsForRoute(filter_->child_id(), 2);
1732 host_.BlockRequestsForRoute(second_filter->child_id(), 1);
1734 MakeTestRequestWithResourceType(filter_.get(), 0, 1,
1735 net::URLRequestTestJob::test_url_1(),
1736 ResourceType::SUB_RESOURCE);
1737 MakeTestRequestWithResourceType(filter_.get(), 1, 2,
1738 net::URLRequestTestJob::test_url_2(),
1739 ResourceType::SUB_RESOURCE);
1740 MakeTestRequestWithResourceType(filter_.get(), 0, 3,
1741 net::URLRequestTestJob::test_url_3(),
1742 ResourceType::SUB_RESOURCE);
1743 MakeTestRequestWithResourceType(second_filter.get(), 1, 4,
1744 net::URLRequestTestJob::test_url_1(),
1745 ResourceType::SUB_RESOURCE);
1746 MakeTestRequestWithResourceType(filter_.get(), 2, 5,
1747 net::URLRequestTestJob::test_url_2(),
1748 ResourceType::SUB_RESOURCE);
1749 MakeTestRequestWithResourceType(filter_.get(), 2, 6,
1750 net::URLRequestTestJob::test_url_3(),
1751 ResourceType::SUB_RESOURCE);
1752 MakeTestRequestWithResourceType(filter_.get(), 0, 7,
1753 net::URLRequestTestJob::test_url_4(),
1754 ResourceType::PREFETCH); // detachable type
1755 MakeTestRequestWithResourceType(second_filter.get(), 1, 8,
1756 net::URLRequestTestJob::test_url_4(),
1757 ResourceType::PREFETCH); // detachable type
1759 host_.CancelRequestsForProcess(filter_->child_id());
1760 host_.CancelRequestsForProcess(second_filter->child_id());
1762 // Flush all the pending requests.
1763 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1766 // Test the private helper method "CalculateApproximateMemoryCost()".
1767 TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
1768 net::URLRequestContext context;
1769 net::URLRequest req(
1770 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL, &context);
1771 EXPECT_EQ(4427,
1772 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
1774 // Add 9 bytes of referrer.
1775 req.SetReferrer("123456789");
1776 EXPECT_EQ(4436,
1777 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
1779 // Add 33 bytes of upload content.
1780 std::string upload_content;
1781 upload_content.resize(33);
1782 std::fill(upload_content.begin(), upload_content.end(), 'x');
1783 scoped_ptr<net::UploadElementReader> reader(new net::UploadBytesElementReader(
1784 upload_content.data(), upload_content.size()));
1785 req.set_upload(make_scoped_ptr(
1786 net::UploadDataStream::CreateWithReader(reader.Pass(), 0)));
1788 // Since the upload throttling is disabled, this has no effect on the cost.
1789 EXPECT_EQ(4436,
1790 ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
1793 // Test that too much memory for outstanding requests for a particular
1794 // render_process_host_id causes requests to fail.
1795 TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
1796 // Expected cost of each request as measured by
1797 // ResourceDispatcherHost::CalculateApproximateMemoryCost().
1798 int kMemoryCostOfTest2Req =
1799 ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest +
1800 std::string("GET").size() +
1801 net::URLRequestTestJob::test_url_2().spec().size();
1803 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
1804 int kMaxCostPerProcess = 440000;
1805 host_.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess);
1807 // Determine how many instance of test_url_2() we can request before
1808 // throttling kicks in.
1809 size_t kMaxRequests = kMaxCostPerProcess / kMemoryCostOfTest2Req;
1811 // This second filter is used to emulate a second process.
1812 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
1814 // Saturate the number of outstanding requests for our process.
1815 for (size_t i = 0; i < kMaxRequests; ++i) {
1816 MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
1817 net::URLRequestTestJob::test_url_2(),
1818 ResourceType::SUB_RESOURCE);
1821 // Issue two more requests for our process -- these should fail immediately.
1822 MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 1,
1823 net::URLRequestTestJob::test_url_2(),
1824 ResourceType::SUB_RESOURCE);
1825 MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 2,
1826 net::URLRequestTestJob::test_url_2(),
1827 ResourceType::SUB_RESOURCE);
1829 // Issue two requests for the second process -- these should succeed since
1830 // it is just process 0 that is saturated.
1831 MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 3,
1832 net::URLRequestTestJob::test_url_2(),
1833 ResourceType::SUB_RESOURCE);
1834 MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 4,
1835 net::URLRequestTestJob::test_url_2(),
1836 ResourceType::SUB_RESOURCE);
1838 // Flush all the pending requests.
1839 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1840 base::MessageLoop::current()->RunUntilIdle();
1842 // Sorts out all the messages we saw by request.
1843 ResourceIPCAccumulator::ClassifiedMessages msgs;
1844 accum_.GetClassifiedMessages(&msgs);
1846 // We issued (kMaxRequests + 4) total requests.
1847 ASSERT_EQ(kMaxRequests + 4, msgs.size());
1849 // Check that the first kMaxRequests succeeded.
1850 for (size_t i = 0; i < kMaxRequests; ++i)
1851 CheckSuccessfulRequest(msgs[i], net::URLRequestTestJob::test_data_2());
1853 // Check that the subsequent two requests (kMaxRequests + 1) and
1854 // (kMaxRequests + 2) were failed, since the per-process bound was reached.
1855 for (int i = 0; i < 2; ++i) {
1856 // Should have sent a single RequestComplete message.
1857 int index = kMaxRequests + i;
1858 CheckFailedRequest(msgs[index], net::URLRequestTestJob::test_data_2(),
1859 net::ERR_INSUFFICIENT_RESOURCES);
1862 // The final 2 requests should have succeeded.
1863 CheckSuccessfulRequest(msgs[kMaxRequests + 2],
1864 net::URLRequestTestJob::test_data_2());
1865 CheckSuccessfulRequest(msgs[kMaxRequests + 3],
1866 net::URLRequestTestJob::test_data_2());
1869 // Test that when too many requests are outstanding for a particular
1870 // render_process_host_id, any subsequent request from it fails. Also verify
1871 // that the global limit is honored.
1872 TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
1873 // Tighten the bound on the ResourceDispatcherHost, to speed things up.
1874 const size_t kMaxRequestsPerProcess = 2;
1875 host_.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess);
1876 const size_t kMaxRequests = 3;
1877 host_.set_max_num_in_flight_requests(kMaxRequests);
1879 // Needed to emulate additional processes.
1880 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
1881 scoped_refptr<ForwardingFilter> third_filter = MakeForwardingFilter();
1883 // Saturate the number of outstanding requests for our process.
1884 for (size_t i = 0; i < kMaxRequestsPerProcess; ++i) {
1885 MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
1886 net::URLRequestTestJob::test_url_2(),
1887 ResourceType::SUB_RESOURCE);
1890 // Issue another request for our process -- this should fail immediately.
1891 MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequestsPerProcess + 1,
1892 net::URLRequestTestJob::test_url_2(),
1893 ResourceType::SUB_RESOURCE);
1895 // Issue a request for the second process -- this should succeed, because it
1896 // is just process 0 that is saturated.
1897 MakeTestRequestWithResourceType(
1898 second_filter.get(), 0, kMaxRequestsPerProcess + 2,
1899 net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
1901 // Issue a request for the third process -- this should fail, because the
1902 // global limit has been reached.
1903 MakeTestRequestWithResourceType(
1904 third_filter.get(), 0, kMaxRequestsPerProcess + 3,
1905 net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
1907 // Flush all the pending requests.
1908 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1909 base::MessageLoop::current()->RunUntilIdle();
1911 // Sorts out all the messages we saw by request.
1912 ResourceIPCAccumulator::ClassifiedMessages msgs;
1913 accum_.GetClassifiedMessages(&msgs);
1915 // The processes issued the following requests:
1916 // #1 issued kMaxRequestsPerProcess that passed + 1 that failed
1917 // #2 issued 1 request that passed
1918 // #3 issued 1 request that failed
1919 ASSERT_EQ((kMaxRequestsPerProcess + 1) + 1 + 1, msgs.size());
1921 for (size_t i = 0; i < kMaxRequestsPerProcess; ++i)
1922 CheckSuccessfulRequest(msgs[i], net::URLRequestTestJob::test_data_2());
1924 CheckFailedRequest(msgs[kMaxRequestsPerProcess + 0],
1925 net::URLRequestTestJob::test_data_2(),
1926 net::ERR_INSUFFICIENT_RESOURCES);
1927 CheckSuccessfulRequest(msgs[kMaxRequestsPerProcess + 1],
1928 net::URLRequestTestJob::test_data_2());
1929 CheckFailedRequest(msgs[kMaxRequestsPerProcess + 2],
1930 net::URLRequestTestJob::test_data_2(),
1931 net::ERR_INSUFFICIENT_RESOURCES);
1934 // Tests that we sniff the mime type for a simple request.
1935 TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
1936 std::string raw_headers("HTTP/1.1 200 OK\n\n");
1937 std::string response_data("<html><title>Test One</title></html>");
1938 SetResponse(raw_headers, response_data);
1940 HandleScheme("http");
1941 MakeTestRequest(0, 1, GURL("http:bla"));
1943 // Flush all pending requests.
1944 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1946 // Sorts out all the messages we saw by request.
1947 ResourceIPCAccumulator::ClassifiedMessages msgs;
1948 accum_.GetClassifiedMessages(&msgs);
1949 ASSERT_EQ(1U, msgs.size());
1951 ResourceResponseHead response_head;
1952 GetResponseHead(msgs[0], &response_head);
1953 ASSERT_EQ("text/html", response_head.mime_type);
1956 // Tests that we don't sniff the mime type when the server provides one.
1957 TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
1958 std::string raw_headers("HTTP/1.1 200 OK\n"
1959 "Content-type: image/jpeg\n\n");
1960 std::string response_data("<html><title>Test One</title></html>");
1961 SetResponse(raw_headers, response_data);
1963 HandleScheme("http");
1964 MakeTestRequest(0, 1, GURL("http:bla"));
1966 // Flush all pending requests.
1967 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1969 // Sorts out all the messages we saw by request.
1970 ResourceIPCAccumulator::ClassifiedMessages msgs;
1971 accum_.GetClassifiedMessages(&msgs);
1972 ASSERT_EQ(1U, msgs.size());
1974 ResourceResponseHead response_head;
1975 GetResponseHead(msgs[0], &response_head);
1976 ASSERT_EQ("image/jpeg", response_head.mime_type);
1979 // Tests that we don't sniff the mime type when there is no message body.
1980 TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
1981 SetResponse("HTTP/1.1 304 Not Modified\n\n");
1983 HandleScheme("http");
1984 MakeTestRequest(0, 1, GURL("http:bla"));
1986 // Flush all pending requests.
1987 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
1989 // Sorts out all the messages we saw by request.
1990 ResourceIPCAccumulator::ClassifiedMessages msgs;
1991 accum_.GetClassifiedMessages(&msgs);
1992 ASSERT_EQ(1U, msgs.size());
1994 ResourceResponseHead response_head;
1995 GetResponseHead(msgs[0], &response_head);
1996 ASSERT_EQ("", response_head.mime_type);
1999 TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
2000 SetResponse("HTTP/1.1 204 No Content\n\n");
2002 HandleScheme("http");
2003 MakeTestRequest(0, 1, GURL("http:bla"));
2005 // Flush all pending requests.
2006 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2008 // Sorts out all the messages we saw by request.
2009 ResourceIPCAccumulator::ClassifiedMessages msgs;
2010 accum_.GetClassifiedMessages(&msgs);
2011 ASSERT_EQ(1U, msgs.size());
2013 ResourceResponseHead response_head;
2014 GetResponseHead(msgs[0], &response_head);
2015 ASSERT_EQ("text/plain", response_head.mime_type);
2018 TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
2019 SetResponse("HTTP/1.1 200 OK\n\n");
2021 HandleScheme("http");
2022 MakeTestRequest(0, 1, GURL("http:bla"));
2024 // Flush all pending requests.
2025 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2027 // Sorts out all the messages we saw by request.
2028 ResourceIPCAccumulator::ClassifiedMessages msgs;
2029 accum_.GetClassifiedMessages(&msgs);
2030 ASSERT_EQ(1U, msgs.size());
2032 ResourceResponseHead response_head;
2033 GetResponseHead(msgs[0], &response_head);
2034 ASSERT_EQ("text/plain", response_head.mime_type);
2037 // Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
2038 TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
2039 std::string raw_headers("HTTP/1.1 403 Forbidden\n"
2040 "Content-disposition: attachment; filename=blah\n"
2041 "Content-type: application/octet-stream\n\n");
2042 std::string response_data("<html><title>Test One</title></html>");
2043 SetResponse(raw_headers, response_data);
2045 HandleScheme("http");
2047 // Only MAIN_FRAMEs can trigger a download.
2048 MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("http:bla"),
2049 ResourceType::MAIN_FRAME);
2051 // Flush all pending requests.
2052 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2053 base::MessageLoop::current()->RunUntilIdle();
2055 // Sorts out all the messages we saw by request.
2056 ResourceIPCAccumulator::ClassifiedMessages msgs;
2057 accum_.GetClassifiedMessages(&msgs);
2059 // We should have gotten one RequestComplete message.
2060 ASSERT_EQ(1U, msgs.size());
2061 ASSERT_EQ(1U, msgs[0].size());
2062 EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type());
2064 // The RequestComplete message should have had the error code of
2065 // ERR_INVALID_RESPONSE.
2066 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_INVALID_RESPONSE);
2069 // Test for http://crbug.com/76202 . We don't want to destroy a
2070 // download request prematurely when processing a cancellation from
2071 // the renderer.
2072 TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
2073 EXPECT_EQ(0, host_.pending_requests());
2075 int render_view_id = 0;
2076 int request_id = 1;
2078 std::string raw_headers("HTTP\n"
2079 "Content-disposition: attachment; filename=foo\n\n");
2080 std::string response_data("01234567890123456789\x01foobar");
2082 // Get past sniffing metrics in the BufferedResourceHandler. Note that
2083 // if we don't get past the sniffing metrics, the result will be that
2084 // the BufferedResourceHandler won't have figured out that it's a download,
2085 // won't have constructed a DownloadResourceHandler, and and the request
2086 // will be successfully canceled below, failing the test.
2087 response_data.resize(1025, ' ');
2089 SetResponse(raw_headers, response_data);
2090 job_factory_->SetDelayedCompleteJobGeneration(true);
2091 HandleScheme("http");
2093 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2094 GURL("http://example.com/blah"),
2095 ResourceType::MAIN_FRAME);
2096 // Return some data so that the request is identified as a download
2097 // and the proper resource handlers are created.
2098 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2100 // And now simulate a cancellation coming from the renderer.
2101 ResourceHostMsg_CancelRequest msg(request_id);
2102 host_.OnMessageReceived(msg, filter_.get());
2104 // Since the request had already started processing as a download,
2105 // the cancellation above should have been ignored and the request
2106 // should still be alive.
2107 EXPECT_EQ(1, host_.pending_requests());
2109 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2112 TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
2113 EXPECT_EQ(0, host_.pending_requests());
2115 int render_view_id = 0;
2116 int request_id = 1;
2118 std::string raw_headers("HTTP\n"
2119 "Content-disposition: attachment; filename=foo\n\n");
2120 std::string response_data("01234567890123456789\x01foobar");
2121 // Get past sniffing metrics.
2122 response_data.resize(1025, ' ');
2124 SetResponse(raw_headers, response_data);
2125 job_factory_->SetDelayedCompleteJobGeneration(true);
2126 HandleScheme("http");
2128 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2129 GURL("http://example.com/blah"),
2130 ResourceType::MAIN_FRAME);
2131 // Return some data so that the request is identified as a download
2132 // and the proper resource handlers are created.
2133 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2135 // And now simulate a cancellation coming from the renderer.
2136 ResourceHostMsg_CancelRequest msg(request_id);
2137 host_.OnMessageReceived(msg, filter_.get());
2139 // Since the request had already started processing as a download,
2140 // the cancellation above should have been ignored and the request
2141 // should still be alive.
2142 EXPECT_EQ(1, host_.pending_requests());
2144 // Cancelling by other methods shouldn't work either.
2145 host_.CancelRequestsForProcess(render_view_id);
2146 EXPECT_EQ(1, host_.pending_requests());
2148 // Cancelling by context should work.
2149 host_.CancelRequestsForContext(filter_->resource_context());
2150 EXPECT_EQ(0, host_.pending_requests());
2153 TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
2154 EXPECT_EQ(0, host_.pending_requests());
2156 int render_view_id = 0;
2157 int request_id = 1;
2159 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2160 net::URLRequestTestJob::test_url_4(),
2161 ResourceType::PREFETCH); // detachable type
2163 // Simulate a cancel coming from the renderer.
2164 RendererCancelRequest(request_id);
2166 // Since the request had already started processing as detachable,
2167 // the cancellation above should have been ignored and the request
2168 // should have been detached.
2169 EXPECT_EQ(1, host_.pending_requests());
2171 // Cancelling by other methods should also leave it detached.
2172 host_.CancelRequestsForProcess(render_view_id);
2173 EXPECT_EQ(1, host_.pending_requests());
2175 // Cancelling by context should work.
2176 host_.CancelRequestsForContext(filter_->resource_context());
2177 EXPECT_EQ(0, host_.pending_requests());
2180 // Test the cancelling of requests that are being transferred to a new renderer
2181 // due to a redirection.
2182 TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
2183 EXPECT_EQ(0, host_.pending_requests());
2185 int render_view_id = 0;
2186 int request_id = 1;
2188 std::string raw_headers("HTTP/1.1 200 OK\n"
2189 "Content-Type: text/html; charset=utf-8\n\n");
2190 std::string response_data("<html>foobar</html>");
2192 SetResponse(raw_headers, response_data);
2193 HandleScheme("http");
2195 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2196 GURL("http://example.com/blah"),
2197 ResourceType::MAIN_FRAME);
2200 GlobalRequestID global_request_id(filter_->child_id(), request_id);
2201 host_.MarkAsTransferredNavigation(global_request_id);
2203 // And now simulate a cancellation coming from the renderer.
2204 ResourceHostMsg_CancelRequest msg(request_id);
2205 host_.OnMessageReceived(msg, filter_.get());
2207 // Since the request is marked as being transferred,
2208 // the cancellation above should have been ignored and the request
2209 // should still be alive.
2210 EXPECT_EQ(1, host_.pending_requests());
2212 // Cancelling by other methods shouldn't work either.
2213 host_.CancelRequestsForProcess(render_view_id);
2214 EXPECT_EQ(1, host_.pending_requests());
2216 // Cancelling by context should work.
2217 host_.CancelRequestsForContext(filter_->resource_context());
2218 EXPECT_EQ(0, host_.pending_requests());
2221 // Test transferred navigations with text/html, which doesn't trigger any
2222 // content sniffing.
2223 TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
2224 // This test expects the cross site request to be leaked, so it can transfer
2225 // the request directly.
2226 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2228 EXPECT_EQ(0, host_.pending_requests());
2230 int render_view_id = 0;
2231 int request_id = 1;
2233 // Configure initial request.
2234 SetResponse("HTTP/1.1 302 Found\n"
2235 "Location: http://other.com/blech\n\n");
2237 HandleScheme("http");
2239 // Temporarily replace ContentBrowserClient with one that will trigger the
2240 // transfer navigation code paths.
2241 TransfersAllNavigationsContentBrowserClient new_client;
2242 ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
2244 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2245 GURL("http://example.com/blah"),
2246 ResourceType::MAIN_FRAME);
2248 // Now that we're blocked on the redirect, update the response and unblock by
2249 // telling the AsyncResourceHandler to follow the redirect.
2250 const std::string kResponseBody = "hello world";
2251 SetResponse("HTTP/1.1 200 OK\n"
2252 "Content-Type: text/html\n\n",
2253 kResponseBody);
2254 ResourceHostMsg_FollowRedirect redirect_msg(request_id);
2255 host_.OnMessageReceived(redirect_msg, filter_.get());
2256 base::MessageLoop::current()->RunUntilIdle();
2258 // Flush all the pending requests to get the response through the
2259 // BufferedResourceHandler.
2260 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2262 // Restore, now that we've set up a transfer.
2263 SetBrowserClientForTesting(old_client);
2265 // This second filter is used to emulate a second process.
2266 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
2268 int new_render_view_id = 1;
2269 int new_request_id = 2;
2271 ResourceHostMsg_Request request =
2272 CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
2273 GURL("http://other.com/blech"));
2274 request.transferred_request_child_id = filter_->child_id();
2275 request.transferred_request_request_id = request_id;
2277 ResourceHostMsg_RequestResource transfer_request_msg(
2278 new_render_view_id, new_request_id, request);
2279 host_.OnMessageReceived(transfer_request_msg, second_filter.get());
2280 base::MessageLoop::current()->RunUntilIdle();
2282 // Check generated messages.
2283 ResourceIPCAccumulator::ClassifiedMessages msgs;
2284 accum_.GetClassifiedMessages(&msgs);
2286 ASSERT_EQ(2U, msgs.size());
2287 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
2288 CheckSuccessfulRequest(msgs[1], kResponseBody);
2291 // Test transferred navigations with text/plain, which causes
2292 // BufferedResourceHandler to buffer the response to sniff the content
2293 // before the transfer occurs.
2294 TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
2295 // This test expects the cross site request to be leaked, so it can transfer
2296 // the request directly.
2297 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2299 EXPECT_EQ(0, host_.pending_requests());
2301 int render_view_id = 0;
2302 int request_id = 1;
2304 // Configure initial request.
2305 SetResponse("HTTP/1.1 302 Found\n"
2306 "Location: http://other.com/blech\n\n");
2308 HandleScheme("http");
2310 // Temporarily replace ContentBrowserClient with one that will trigger the
2311 // transfer navigation code paths.
2312 TransfersAllNavigationsContentBrowserClient new_client;
2313 ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
2315 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2316 GURL("http://example.com/blah"),
2317 ResourceType::MAIN_FRAME);
2319 // Now that we're blocked on the redirect, update the response and unblock by
2320 // telling the AsyncResourceHandler to follow the redirect. Use a text/plain
2321 // MIME type, which causes BufferedResourceHandler to buffer it before the
2322 // transfer occurs.
2323 const std::string kResponseBody = "hello world";
2324 SetResponse("HTTP/1.1 200 OK\n"
2325 "Content-Type: text/plain\n\n",
2326 kResponseBody);
2327 ResourceHostMsg_FollowRedirect redirect_msg(request_id);
2328 host_.OnMessageReceived(redirect_msg, filter_.get());
2329 base::MessageLoop::current()->RunUntilIdle();
2331 // Flush all the pending requests to get the response through the
2332 // BufferedResourceHandler.
2333 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2335 // Restore, now that we've set up a transfer.
2336 SetBrowserClientForTesting(old_client);
2338 // This second filter is used to emulate a second process.
2339 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
2341 int new_render_view_id = 1;
2342 int new_request_id = 2;
2344 ResourceHostMsg_Request request =
2345 CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
2346 GURL("http://other.com/blech"));
2347 request.transferred_request_child_id = filter_->child_id();
2348 request.transferred_request_request_id = request_id;
2350 ResourceHostMsg_RequestResource transfer_request_msg(
2351 new_render_view_id, new_request_id, request);
2352 host_.OnMessageReceived(transfer_request_msg, second_filter.get());
2353 base::MessageLoop::current()->RunUntilIdle();
2355 // Check generated messages.
2356 ResourceIPCAccumulator::ClassifiedMessages msgs;
2357 accum_.GetClassifiedMessages(&msgs);
2359 ASSERT_EQ(2U, msgs.size());
2360 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
2361 CheckSuccessfulRequest(msgs[1], kResponseBody);
2364 TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
2365 // This test expects the cross site request to be leaked, so it can transfer
2366 // the request directly.
2367 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2369 EXPECT_EQ(0, host_.pending_requests());
2371 int render_view_id = 0;
2372 int request_id = 1;
2373 int first_child_id = -1;
2375 // Configure initial request.
2376 SetResponse("HTTP/1.1 302 Found\n"
2377 "Location: http://other.com/blech\n\n");
2378 const std::string kResponseBody = "hello world";
2380 HandleScheme("http");
2382 // Temporarily replace ContentBrowserClient with one that will trigger the
2383 // transfer navigation code paths.
2384 TransfersAllNavigationsContentBrowserClient new_client;
2385 ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
2387 // Create a first filter that can be deleted before the second one starts.
2389 scoped_refptr<ForwardingFilter> first_filter = MakeForwardingFilter();
2390 first_child_id = first_filter->child_id();
2392 ResourceHostMsg_Request first_request =
2393 CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
2394 GURL("http://example.com/blah"));
2396 ResourceHostMsg_RequestResource first_request_msg(
2397 render_view_id, request_id, first_request);
2398 host_.OnMessageReceived(first_request_msg, first_filter.get());
2399 base::MessageLoop::current()->RunUntilIdle();
2401 // Now that we're blocked on the redirect, update the response and unblock
2402 // by telling the AsyncResourceHandler to follow the redirect.
2403 SetResponse("HTTP/1.1 200 OK\n"
2404 "Content-Type: text/html\n\n",
2405 kResponseBody);
2406 ResourceHostMsg_FollowRedirect redirect_msg(request_id);
2407 host_.OnMessageReceived(redirect_msg, first_filter.get());
2408 base::MessageLoop::current()->RunUntilIdle();
2410 // Flush all the pending requests to get the response through the
2411 // BufferedResourceHandler.
2412 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2414 // The first filter is now deleted, as if the child process died.
2416 // Restore.
2417 SetBrowserClientForTesting(old_client);
2419 // Make sure we don't hold onto the ResourceMessageFilter after it is deleted.
2420 GlobalRequestID first_global_request_id(first_child_id, request_id);
2422 // This second filter is used to emulate a second process.
2423 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
2425 int new_render_view_id = 1;
2426 int new_request_id = 2;
2428 ResourceHostMsg_Request request =
2429 CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
2430 GURL("http://other.com/blech"));
2431 request.transferred_request_child_id = first_child_id;
2432 request.transferred_request_request_id = request_id;
2434 // For cleanup.
2435 child_ids_.insert(second_filter->child_id());
2436 ResourceHostMsg_RequestResource transfer_request_msg(
2437 new_render_view_id, new_request_id, request);
2438 host_.OnMessageReceived(transfer_request_msg, second_filter.get());
2439 base::MessageLoop::current()->RunUntilIdle();
2441 // Check generated messages.
2442 ResourceIPCAccumulator::ClassifiedMessages msgs;
2443 accum_.GetClassifiedMessages(&msgs);
2445 ASSERT_EQ(2U, msgs.size());
2446 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
2447 CheckSuccessfulRequest(msgs[1], kResponseBody);
2450 TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
2451 // This test expects the cross site request to be leaked, so it can transfer
2452 // the request directly.
2453 CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
2455 EXPECT_EQ(0, host_.pending_requests());
2457 int render_view_id = 0;
2458 int request_id = 1;
2460 // Configure initial request.
2461 SetResponse("HTTP/1.1 302 Found\n"
2462 "Location: http://other.com/blech\n\n");
2464 HandleScheme("http");
2466 // Temporarily replace ContentBrowserClient with one that will trigger the
2467 // transfer navigation code paths.
2468 TransfersAllNavigationsContentBrowserClient new_client;
2469 ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
2471 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2472 GURL("http://example.com/blah"),
2473 ResourceType::MAIN_FRAME);
2475 // Now that we're blocked on the redirect, simulate hitting another redirect.
2476 SetResponse("HTTP/1.1 302 Found\n"
2477 "Location: http://other.com/blerg\n\n");
2478 ResourceHostMsg_FollowRedirect redirect_msg(request_id);
2479 host_.OnMessageReceived(redirect_msg, filter_.get());
2480 base::MessageLoop::current()->RunUntilIdle();
2482 // Now that we're blocked on the second redirect, update the response and
2483 // unblock by telling the AsyncResourceHandler to follow the redirect.
2484 // Again, use text/plain to force BufferedResourceHandler to buffer before
2485 // the transfer.
2486 const std::string kResponseBody = "hello world";
2487 SetResponse("HTTP/1.1 200 OK\n"
2488 "Content-Type: text/plain\n\n",
2489 kResponseBody);
2490 ResourceHostMsg_FollowRedirect redirect_msg2(request_id);
2491 host_.OnMessageReceived(redirect_msg2, filter_.get());
2492 base::MessageLoop::current()->RunUntilIdle();
2494 // Flush all the pending requests to get the response through the
2495 // BufferedResourceHandler.
2496 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2498 // Restore.
2499 SetBrowserClientForTesting(old_client);
2501 // This second filter is used to emulate a second process.
2502 scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
2504 int new_render_view_id = 1;
2505 int new_request_id = 2;
2507 ResourceHostMsg_Request request =
2508 CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
2509 GURL("http://other.com/blech"));
2510 request.transferred_request_child_id = filter_->child_id();
2511 request.transferred_request_request_id = request_id;
2513 // For cleanup.
2514 child_ids_.insert(second_filter->child_id());
2515 ResourceHostMsg_RequestResource transfer_request_msg(
2516 new_render_view_id, new_request_id, request);
2517 host_.OnMessageReceived(transfer_request_msg, second_filter.get());
2519 // Verify that we update the ResourceRequestInfo.
2520 GlobalRequestID global_request_id(second_filter->child_id(), new_request_id);
2521 const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
2522 host_.GetURLRequest(global_request_id));
2523 EXPECT_EQ(second_filter->child_id(), info->GetChildID());
2524 EXPECT_EQ(new_render_view_id, info->GetRouteID());
2525 EXPECT_EQ(new_request_id, info->GetRequestID());
2526 EXPECT_EQ(second_filter, info->filter());
2528 // Let request complete.
2529 base::MessageLoop::current()->RunUntilIdle();
2531 // Check generated messages.
2532 ResourceIPCAccumulator::ClassifiedMessages msgs;
2533 accum_.GetClassifiedMessages(&msgs);
2535 ASSERT_EQ(2U, msgs.size());
2536 EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
2537 CheckSuccessfulRequest(msgs[1], kResponseBody);
2540 TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
2541 EXPECT_EQ(0, host_.pending_requests());
2543 HandleScheme("http");
2545 MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("foo://bar"),
2546 ResourceType::MAIN_FRAME);
2548 // Flush all pending requests.
2549 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2551 // Sort all the messages we saw by request.
2552 ResourceIPCAccumulator::ClassifiedMessages msgs;
2553 accum_.GetClassifiedMessages(&msgs);
2555 // We should have gotten one RequestComplete message.
2556 ASSERT_EQ(1U, msgs[0].size());
2557 EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][0].type());
2559 // The RequestComplete message should have the error code of
2560 // ERR_UNKNOWN_URL_SCHEME.
2561 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_UNKNOWN_URL_SCHEME);
2564 TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
2565 EXPECT_EQ(0, host_.pending_requests());
2567 SendDataReceivedACKs(true);
2569 HandleScheme("big-job");
2570 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2572 // Sort all the messages we saw by request.
2573 ResourceIPCAccumulator::ClassifiedMessages msgs;
2574 accum_.GetClassifiedMessages(&msgs);
2576 size_t size = msgs[0].size();
2578 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
2579 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID, msgs[0][1].type());
2580 for (size_t i = 2; i < size - 1; ++i)
2581 EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
2582 EXPECT_EQ(ResourceMsg_RequestComplete::ID, msgs[0][size - 1].type());
2585 // Request a very large detachable resource and cancel part way. Some of the
2586 // data should have been sent to the renderer, but not all.
2587 TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
2588 EXPECT_EQ(0, host_.pending_requests());
2590 int render_view_id = 0;
2591 int request_id = 1;
2593 std::string raw_headers("HTTP\n"
2594 "Content-type: image/jpeg\n\n");
2595 std::string response_data("01234567890123456789\x01foobar");
2597 // Create a response larger than kMaxAllocationSize (currently 32K). Note
2598 // that if this increase beyond 512K we'll need to make the response longer.
2599 const int kAllocSize = 1024*512;
2600 response_data.resize(kAllocSize, ' ');
2602 SetResponse(raw_headers, response_data);
2603 job_factory_->SetDelayedCompleteJobGeneration(true);
2604 HandleScheme("http");
2606 MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
2607 GURL("http://example.com/blah"),
2608 ResourceType::PREFETCH);
2610 // Get a bit of data before cancelling.
2611 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
2613 // Simulate a cancellation coming from the renderer.
2614 ResourceHostMsg_CancelRequest msg(request_id);
2615 host_.OnMessageReceived(msg, filter_.get());
2617 EXPECT_EQ(1, host_.pending_requests());
2619 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
2621 // Sort all the messages we saw by request.
2622 ResourceIPCAccumulator::ClassifiedMessages msgs;
2623 accum_.GetClassifiedMessages(&msgs);
2625 EXPECT_EQ(4U, msgs[0].size());
2627 // Figure out how many bytes were received by the renderer.
2628 int data_offset;
2629 int data_length;
2630 ASSERT_TRUE(
2631 ExtractDataOffsetAndLength(msgs[0][2], &data_offset, &data_length));
2632 EXPECT_LT(0, data_length);
2633 EXPECT_GT(kAllocSize, data_length);
2635 // Verify the data that was received before cancellation. The request should
2636 // have appeared to cancel, however.
2637 CheckSuccessfulRequestWithErrorCode(
2638 msgs[0],
2639 std::string(response_data.begin(), response_data.begin() + data_length),
2640 net::ERR_ABORTED);
2643 TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
2644 EXPECT_EQ(0, host_.pending_requests());
2646 HandleScheme("big-job");
2647 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2649 // Sort all the messages we saw by request.
2650 ResourceIPCAccumulator::ClassifiedMessages msgs;
2651 accum_.GetClassifiedMessages(&msgs);
2653 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
2654 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
2655 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID, msgs[0][1].type());
2656 for (size_t i = 2; i < msgs[0].size(); ++i)
2657 EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
2659 // NOTE: If we fail the above checks then it means that we probably didn't
2660 // load a big enough response to trigger the delay mechanism we are trying to
2661 // test!
2663 msgs[0].erase(msgs[0].begin());
2664 msgs[0].erase(msgs[0].begin());
2666 // ACK all DataReceived messages until we find a RequestComplete message.
2667 bool complete = false;
2668 while (!complete) {
2669 for (size_t i = 0; i < msgs[0].size(); ++i) {
2670 if (msgs[0][i].type() == ResourceMsg_RequestComplete::ID) {
2671 complete = true;
2672 break;
2675 EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
2677 ResourceHostMsg_DataReceived_ACK msg(1);
2678 host_.OnMessageReceived(msg, filter_.get());
2681 base::MessageLoop::current()->RunUntilIdle();
2683 msgs.clear();
2684 accum_.GetClassifiedMessages(&msgs);
2688 // Flakyness of this test might indicate memory corruption issues with
2689 // for example the ResourceBuffer of AsyncResourceHandler.
2690 TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
2691 EXPECT_EQ(0, host_.pending_requests());
2693 HandleScheme("big-job");
2694 MakeTestRequest(0, 1, GURL("big-job:0123456789,1000000"));
2696 // Sort all the messages we saw by request.
2697 ResourceIPCAccumulator::ClassifiedMessages msgs;
2698 accum_.GetClassifiedMessages(&msgs);
2700 // We expect 1x ReceivedResponse, 1x SetDataBuffer, Nx ReceivedData messages.
2701 EXPECT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[0][0].type());
2702 EXPECT_EQ(ResourceMsg_SetDataBuffer::ID, msgs[0][1].type());
2703 for (size_t i = 2; i < msgs[0].size(); ++i)
2704 EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
2706 // NOTE: If we fail the above checks then it means that we probably didn't
2707 // load a big enough response to trigger the delay mechanism.
2709 // Send some unexpected ACKs.
2710 for (size_t i = 0; i < 128; ++i) {
2711 ResourceHostMsg_DataReceived_ACK msg(1);
2712 host_.OnMessageReceived(msg, filter_.get());
2715 msgs[0].erase(msgs[0].begin());
2716 msgs[0].erase(msgs[0].begin());
2718 // ACK all DataReceived messages until we find a RequestComplete message.
2719 bool complete = false;
2720 while (!complete) {
2721 for (size_t i = 0; i < msgs[0].size(); ++i) {
2722 if (msgs[0][i].type() == ResourceMsg_RequestComplete::ID) {
2723 complete = true;
2724 break;
2727 EXPECT_EQ(ResourceMsg_DataReceived::ID, msgs[0][i].type());
2729 ResourceHostMsg_DataReceived_ACK msg(1);
2730 host_.OnMessageReceived(msg, filter_.get());
2733 base::MessageLoop::current()->RunUntilIdle();
2735 msgs.clear();
2736 accum_.GetClassifiedMessages(&msgs);
2740 // Tests the dispatcher host's temporary file management.
2741 TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
2742 const int kRequestID = 1;
2744 // Create a temporary file.
2745 base::FilePath file_path;
2746 ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
2747 scoped_refptr<ShareableFileReference> deletable_file =
2748 ShareableFileReference::GetOrCreate(
2749 file_path,
2750 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
2751 BrowserThread::GetMessageLoopProxyForThread(
2752 BrowserThread::FILE).get());
2754 // Not readable.
2755 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2756 filter_->child_id(), file_path));
2758 // Register it for a resource request.
2759 host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
2761 // Should be readable now.
2762 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2763 filter_->child_id(), file_path));
2765 // The child releases from the request.
2766 ResourceHostMsg_ReleaseDownloadedFile release_msg(kRequestID);
2767 host_.OnMessageReceived(release_msg, filter_);
2769 // Still readable because there is another reference to the file. (The child
2770 // may take additional blob references.)
2771 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2772 filter_->child_id(), file_path));
2774 // Release extra references and wait for the file to be deleted. (This relies
2775 // on the delete happening on the FILE thread which is mapped to main thread
2776 // in this test.)
2777 deletable_file = NULL;
2778 base::RunLoop().RunUntilIdle();
2780 // The file is no longer readable to the child and has been deleted.
2781 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2782 filter_->child_id(), file_path));
2783 EXPECT_FALSE(base::PathExists(file_path));
2786 // Tests that temporary files held on behalf of child processes are released
2787 // when the child process dies.
2788 TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
2789 const int kRequestID = 1;
2791 // Create a temporary file.
2792 base::FilePath file_path;
2793 ASSERT_TRUE(base::CreateTemporaryFile(&file_path));
2794 scoped_refptr<ShareableFileReference> deletable_file =
2795 ShareableFileReference::GetOrCreate(
2796 file_path,
2797 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
2798 BrowserThread::GetMessageLoopProxyForThread(
2799 BrowserThread::FILE).get());
2801 // Register it for a resource request.
2802 host_.RegisterDownloadedTempFile(filter_->child_id(), kRequestID, file_path);
2803 deletable_file = NULL;
2805 // Should be readable now.
2806 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2807 filter_->child_id(), file_path));
2809 // Let the process die.
2810 filter_->OnChannelClosing();
2811 base::RunLoop().RunUntilIdle();
2813 // The file is no longer readable to the child and has been deleted.
2814 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2815 filter_->child_id(), file_path));
2816 EXPECT_FALSE(base::PathExists(file_path));
2819 TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
2820 // Make a request which downloads to file.
2821 ResourceHostMsg_Request request = CreateResourceRequest(
2822 "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
2823 request.download_to_file = true;
2824 ResourceHostMsg_RequestResource request_msg(0, 1, request);
2825 host_.OnMessageReceived(request_msg, filter_);
2827 // Running the message loop until idle does not work because
2828 // RedirectToFileResourceHandler posts things to base::WorkerPool. Instead,
2829 // wait for the ResourceMsg_RequestComplete to go out. Then run the event loop
2830 // until idle so the loader is gone.
2831 WaitForRequestComplete();
2832 base::RunLoop().RunUntilIdle();
2833 EXPECT_EQ(0, host_.pending_requests());
2835 ResourceIPCAccumulator::ClassifiedMessages msgs;
2836 accum_.GetClassifiedMessages(&msgs);
2838 ASSERT_EQ(1U, msgs.size());
2839 const std::vector<IPC::Message>& messages = msgs[0];
2841 // The request should contain the following messages:
2842 // ReceivedResponse (indicates headers received and filename)
2843 // DataDownloaded* (bytes downloaded and total length)
2844 // RequestComplete (request is done)
2846 // ReceivedResponse
2847 ResourceResponseHead response_head;
2848 GetResponseHead(messages, &response_head);
2849 ASSERT_FALSE(response_head.download_file_path.empty());
2851 // DataDownloaded
2852 size_t total_len = 0;
2853 for (size_t i = 1; i < messages.size() - 1; i++) {
2854 ASSERT_EQ(ResourceMsg_DataDownloaded::ID, messages[i].type());
2855 PickleIterator iter(messages[i]);
2856 int request_id, data_len;
2857 ASSERT_TRUE(IPC::ReadParam(&messages[i], &iter, &request_id));
2858 ASSERT_TRUE(IPC::ReadParam(&messages[i], &iter, &data_len));
2859 total_len += data_len;
2861 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), total_len);
2863 // RequestComplete
2864 CheckRequestCompleteErrorCode(messages.back(), net::OK);
2866 // Verify that the data ended up in the temporary file.
2867 std::string contents;
2868 ASSERT_TRUE(base::ReadFileToString(response_head.download_file_path,
2869 &contents));
2870 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
2872 // The file should be readable by the child.
2873 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2874 filter_->child_id(), response_head.download_file_path));
2876 // When the renderer releases the file, it should be deleted. Again,
2877 // RunUntilIdle doesn't work because base::WorkerPool is involved.
2878 ShareableFileReleaseWaiter waiter(response_head.download_file_path);
2879 ResourceHostMsg_ReleaseDownloadedFile release_msg(1);
2880 host_.OnMessageReceived(release_msg, filter_);
2881 waiter.Wait();
2882 // The release callback runs before the delete is scheduled, so pump the
2883 // message loop for the delete itself. (This relies on the delete happening on
2884 // the FILE thread which is mapped to main thread in this test.)
2885 base::RunLoop().RunUntilIdle();
2887 EXPECT_FALSE(base::PathExists(response_head.download_file_path));
2888 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
2889 filter_->child_id(), response_head.download_file_path));
2892 net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
2893 const std::string& scheme,
2894 net::URLRequest* request,
2895 net::NetworkDelegate* network_delegate) const {
2896 url_request_jobs_created_count_++;
2897 if (test_fixture_->response_headers_.empty()) {
2898 if (delay_start_) {
2899 return new URLRequestTestDelayedStartJob(request, network_delegate);
2900 } else if (delay_complete_) {
2901 return new URLRequestTestDelayedCompletionJob(request,
2902 network_delegate);
2903 } else if (network_start_notification_) {
2904 return new URLRequestTestDelayedNetworkJob(request, network_delegate);
2905 } else if (scheme == "big-job") {
2906 return new URLRequestBigJob(request, network_delegate);
2907 } else {
2908 return new net::URLRequestTestJob(request, network_delegate);
2910 } else {
2911 if (delay_start_) {
2912 return new URLRequestTestDelayedStartJob(
2913 request, network_delegate,
2914 test_fixture_->response_headers_, test_fixture_->response_data_,
2915 false);
2916 } else if (delay_complete_) {
2917 return new URLRequestTestDelayedCompletionJob(
2918 request, network_delegate,
2919 test_fixture_->response_headers_, test_fixture_->response_data_,
2920 false);
2921 } else {
2922 return new net::URLRequestTestJob(
2923 request, network_delegate,
2924 test_fixture_->response_headers_, test_fixture_->response_data_,
2925 false);
2930 } // namespace content