| Index: content/browser/loader/resource_dispatcher_host_unittest.cc
|
| diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| index 7717431928dee5c20fc1d62e747c5998e2ddbe4d..08e5f4d17e040b7706ada50493dc550197b71656 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/file_util.h"
|
| #include "base/files/file_path.h"
|
| #include "base/memory/scoped_vector.h"
|
| +#include "base/memory/shared_memory.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/pickle.h"
|
| #include "base/run_loop.h"
|
| @@ -82,6 +83,29 @@ void GenerateIPCMessage(
|
| *message, filter.get(), &msg_is_ok);
|
| }
|
|
|
| +// On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not
|
| +// automatically released.
|
| +//
|
| +// See ResourceDispatcher::ReleaseResourcesInDataMessage.
|
| +//
|
| +// TODO(davidben): It would be nice if the behavior for base::SharedMemoryHandle
|
| +// were more like it is in POSIX where the received fds are tracked in a
|
| +// ref-counted core that closes them if not extracted.
|
| +void ReleaseHandlesInMessage(const IPC::Message& message) {
|
| + if (message.type() == ResourceMsg_SetDataBuffer::ID) {
|
| + PickleIterator iter(message);
|
| + int request_id;
|
| + CHECK(message.ReadInt(&iter, &request_id));
|
| + base::SharedMemoryHandle shm_handle;
|
| + if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message,
|
| + &iter,
|
| + &shm_handle)) {
|
| + if (base::SharedMemory::IsHandleValid(shm_handle))
|
| + base::SharedMemory::CloseHandle(shm_handle);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| static int RequestIDForMessage(const IPC::Message& msg) {
|
| @@ -133,6 +157,13 @@ static void KickOffRequest() {
|
| // We may want to move this to a shared space if it is useful for something else
|
| class ResourceIPCAccumulator {
|
| public:
|
| + ~ResourceIPCAccumulator() {
|
| + for (size_t i = 0; i < messages_.size(); i++) {
|
| + ReleaseHandlesInMessage(messages_[i]);
|
| + }
|
| + }
|
| +
|
| + // On Windows, takes ownership of SharedMemoryHandles in |msg|.
|
| void AddMessage(const IPC::Message& msg) {
|
| messages_.push_back(msg);
|
| }
|
| @@ -140,7 +171,8 @@ class ResourceIPCAccumulator {
|
| // This groups the messages by their request ID. The groups will be in order
|
| // that the first message for each request ID was received, and the messages
|
| // within the groups will be in the order that they appeared.
|
| - // Note that this clears messages_.
|
| + // Note that this clears messages_. The caller takes ownership of any
|
| + // SharedMemoryHandles in messages placed into |msgs|.
|
| typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages;
|
| void GetClassifiedMessages(ClassifiedMessages* msgs);
|
|
|
| @@ -173,36 +205,39 @@ void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) {
|
| }
|
| }
|
|
|
| -// This class forwards the incoming messages to the ResourceDispatcherHostTest.
|
| // This is used to emulate different sub-processes, since this filter will
|
| -// have a different ID than the original. For the test, we want all the incoming
|
| -// messages to go to the same place, which is why this forwards.
|
| -class ForwardingFilter : public ResourceMessageFilter {
|
| +// have a different ID than the original.
|
| +class TestFilter : public ResourceMessageFilter {
|
| public:
|
| - explicit ForwardingFilter(IPC::Sender* dest,
|
| - ResourceContext* resource_context)
|
| - : ResourceMessageFilter(
|
| - ChildProcessHostImpl::GenerateChildProcessUniqueId(),
|
| - PROCESS_TYPE_RENDERER, NULL, NULL, NULL, NULL,
|
| - base::Bind(&ForwardingFilter::GetContexts,
|
| - base::Unretained(this))),
|
| - dest_(dest),
|
| - resource_context_(resource_context) {
|
| + explicit TestFilter(ResourceContext* resource_context)
|
| + : ResourceMessageFilter(
|
| + ChildProcessHostImpl::GenerateChildProcessUniqueId(),
|
| + PROCESS_TYPE_RENDERER, NULL, NULL, NULL, NULL,
|
| + base::Bind(&TestFilter::GetContexts, base::Unretained(this))),
|
| + resource_context_(resource_context),
|
| + canceled_(false),
|
| + received_after_canceled_(0) {
|
| ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
|
| set_peer_pid_for_testing(base::GetCurrentProcId());
|
| }
|
|
|
| + void set_canceled(bool canceled) { canceled_ = canceled; }
|
| + int received_after_canceled() const { return received_after_canceled_; }
|
| +
|
| // ResourceMessageFilter override
|
| virtual bool Send(IPC::Message* msg) OVERRIDE {
|
| - if (!dest_)
|
| - return false;
|
| - return dest_->Send(msg);
|
| + // No messages should be received when the process has been canceled.
|
| + if (canceled_)
|
| + received_after_canceled_++;
|
| + ReleaseHandlesInMessage(*msg);
|
| + delete msg;
|
| + return true;
|
| }
|
|
|
| ResourceContext* resource_context() { return resource_context_; }
|
|
|
| protected:
|
| - virtual ~ForwardingFilter() {}
|
| + virtual ~TestFilter() {}
|
|
|
| private:
|
| void GetContexts(const ResourceHostMsg_Request& request,
|
| @@ -212,8 +247,34 @@ class ForwardingFilter : public ResourceMessageFilter {
|
| *request_context = resource_context_->GetRequestContext();
|
| }
|
|
|
| - IPC::Sender* dest_;
|
| ResourceContext* resource_context_;
|
| + bool canceled_;
|
| + int received_after_canceled_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestFilter);
|
| +};
|
| +
|
| +
|
| +// This class forwards the incoming messages to the ResourceDispatcherHostTest.
|
| +// For the test, we want all the incoming messages to go to the same place,
|
| +// which is why this forwards.
|
| +class ForwardingFilter : public TestFilter {
|
| + public:
|
| + explicit ForwardingFilter(IPC::Sender* dest,
|
| + ResourceContext* resource_context)
|
| + : TestFilter(resource_context),
|
| + dest_(dest) {
|
| + }
|
| +
|
| + // TestFilter override
|
| + virtual bool Send(IPC::Message* msg) OVERRIDE {
|
| + return dest_->Send(msg);
|
| + }
|
| +
|
| + private:
|
| + virtual ~ForwardingFilter() {}
|
| +
|
| + IPC::Sender* dest_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ForwardingFilter);
|
| };
|
| @@ -622,6 +683,7 @@ class ResourceDispatcherHostTest : public testing::Test,
|
| wait_for_request_complete_loop_->Quit();
|
| }
|
|
|
| + // Do not release handles in it yet; the accumulator owns them now.
|
| delete msg;
|
| return true;
|
| }
|
| @@ -1420,32 +1482,6 @@ TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
|
| CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED);
|
| }
|
|
|
| -// The host delegate acts as a second one so we can have some requests
|
| -// pending and some canceled.
|
| -class TestFilter : public ForwardingFilter {
|
| - public:
|
| - explicit TestFilter(ResourceContext* resource_context)
|
| - : ForwardingFilter(NULL, resource_context),
|
| - has_canceled_(false),
|
| - received_after_canceled_(0) {
|
| - }
|
| -
|
| - // ForwardingFilter override
|
| - virtual bool Send(IPC::Message* msg) OVERRIDE {
|
| - // no messages should be received when the process has been canceled
|
| - if (has_canceled_)
|
| - received_after_canceled_++;
|
| - delete msg;
|
| - return true;
|
| - }
|
| -
|
| - bool has_canceled_;
|
| - int received_after_canceled_;
|
| -
|
| - private:
|
| - virtual ~TestFilter() {}
|
| -};
|
| -
|
| // Tests CancelRequestsForProcess
|
| TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
|
| scoped_refptr<TestFilter> test_filter = new TestFilter(
|
| @@ -1492,7 +1528,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
|
|
|
| // Cancel the requests to the test process.
|
| host_.CancelRequestsForProcess(filter_->child_id());
|
| - test_filter->has_canceled_ = true;
|
| + test_filter->set_canceled(true);
|
|
|
| // The requests should all be cancelled, except request 4, which is detached.
|
| EXPECT_EQ(1, host_.pending_requests());
|
| @@ -1507,7 +1543,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
|
| EXPECT_EQ(0, host_.pending_requests());
|
|
|
| // The test delegate should not have gotten any messages after being canceled.
|
| - ASSERT_EQ(0, test_filter->received_after_canceled_);
|
| + ASSERT_EQ(0, test_filter->received_after_canceled());
|
|
|
| // There should be two results.
|
| ResourceIPCAccumulator::ClassifiedMessages msgs;
|
|
|