OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/memory/scoped_vector.h" | 11 #include "base/memory/scoped_vector.h" |
12 #include "base/memory/shared_memory.h" | |
12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
13 #include "base/pickle.h" | 14 #include "base/pickle.h" |
14 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
17 #include "content/browser/browser_thread_impl.h" | 18 #include "content/browser/browser_thread_impl.h" |
18 #include "content/browser/child_process_security_policy_impl.h" | 19 #include "content/browser/child_process_security_policy_impl.h" |
19 #include "content/browser/loader/cross_site_resource_handler.h" | 20 #include "content/browser/loader/cross_site_resource_handler.h" |
20 #include "content/browser/loader/detachable_resource_handler.h" | 21 #include "content/browser/loader/detachable_resource_handler.h" |
21 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 22 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 } | 76 } |
76 | 77 |
77 void GenerateIPCMessage( | 78 void GenerateIPCMessage( |
78 scoped_refptr<ResourceMessageFilter> filter, | 79 scoped_refptr<ResourceMessageFilter> filter, |
79 scoped_ptr<IPC::Message> message) { | 80 scoped_ptr<IPC::Message> message) { |
80 bool msg_is_ok; | 81 bool msg_is_ok; |
81 ResourceDispatcherHostImpl::Get()->OnMessageReceived( | 82 ResourceDispatcherHostImpl::Get()->OnMessageReceived( |
82 *message, filter.get(), &msg_is_ok); | 83 *message, filter.get(), &msg_is_ok); |
83 } | 84 } |
84 | 85 |
86 // On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not | |
87 // automatically released. | |
88 // | |
89 // See ResourceDispatcher::ReleaseResourcesInDataMessage. | |
90 // | |
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); | |
105 } | |
106 } | |
107 } | |
108 | |
85 } // namespace | 109 } // namespace |
86 | 110 |
87 static int RequestIDForMessage(const IPC::Message& msg) { | 111 static int RequestIDForMessage(const IPC::Message& msg) { |
88 int request_id = -1; | 112 int request_id = -1; |
89 switch (msg.type()) { | 113 switch (msg.type()) { |
90 case ResourceMsg_UploadProgress::ID: | 114 case ResourceMsg_UploadProgress::ID: |
91 case ResourceMsg_ReceivedResponse::ID: | 115 case ResourceMsg_ReceivedResponse::ID: |
92 case ResourceMsg_ReceivedRedirect::ID: | 116 case ResourceMsg_ReceivedRedirect::ID: |
93 case ResourceMsg_SetDataBuffer::ID: | 117 case ResourceMsg_SetDataBuffer::ID: |
94 case ResourceMsg_DataReceived::ID: | 118 case ResourceMsg_DataReceived::ID: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 } | 150 } |
127 | 151 |
128 // Spin up the message loop to kick off the request. | 152 // Spin up the message loop to kick off the request. |
129 static void KickOffRequest() { | 153 static void KickOffRequest() { |
130 base::MessageLoop::current()->RunUntilIdle(); | 154 base::MessageLoop::current()->RunUntilIdle(); |
131 } | 155 } |
132 | 156 |
133 // We may want to move this to a shared space if it is useful for something else | 157 // We may want to move this to a shared space if it is useful for something else |
134 class ResourceIPCAccumulator { | 158 class ResourceIPCAccumulator { |
135 public: | 159 public: |
160 ~ResourceIPCAccumulator() { | |
161 for (size_t i = 0; i < messages_.size(); i++) { | |
162 ReleaseHandlesInMessage(messages_[i]); | |
163 } | |
164 } | |
165 | |
166 // On Windows, takes ownership of SharedMemoryHandles in |msg|. | |
136 void AddMessage(const IPC::Message& msg) { | 167 void AddMessage(const IPC::Message& msg) { |
137 messages_.push_back(msg); | 168 messages_.push_back(msg); |
138 } | 169 } |
139 | 170 |
140 // This groups the messages by their request ID. The groups will be in order | 171 // This groups the messages by their request ID. The groups will be in order |
141 // that the first message for each request ID was received, and the messages | 172 // that the first message for each request ID was received, and the messages |
142 // within the groups will be in the order that they appeared. | 173 // within the groups will be in the order that they appeared. |
143 // Note that this clears messages_. | 174 // Note that this clears messages_. |
144 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; | 175 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; |
145 void GetClassifiedMessages(ClassifiedMessages* msgs); | 176 void GetClassifiedMessages(ClassifiedMessages* msgs); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 base::Bind(&ForwardingFilter::GetContexts, | 218 base::Bind(&ForwardingFilter::GetContexts, |
188 base::Unretained(this))), | 219 base::Unretained(this))), |
189 dest_(dest), | 220 dest_(dest), |
190 resource_context_(resource_context) { | 221 resource_context_(resource_context) { |
191 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id()); | 222 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id()); |
192 set_peer_pid_for_testing(base::GetCurrentProcId()); | 223 set_peer_pid_for_testing(base::GetCurrentProcId()); |
193 } | 224 } |
194 | 225 |
195 // ResourceMessageFilter override | 226 // ResourceMessageFilter override |
196 virtual bool Send(IPC::Message* msg) OVERRIDE { | 227 virtual bool Send(IPC::Message* msg) OVERRIDE { |
197 if (!dest_) | 228 if (!dest_) { |
229 ReleaseHandlesInMessage(*msg); | |
230 delete msg; | |
198 return false; | 231 return false; |
mmenke
2014/04/25 16:07:24
Shouldn't this be return true, because we ate the
mmenke
2014/04/25 16:09:20
Oops...this is send, not receive...nevermind.
davidben
2014/04/25 16:24:37
This arrangement is kind of silly anyway. This cod
| |
232 } | |
199 return dest_->Send(msg); | 233 return dest_->Send(msg); |
200 } | 234 } |
201 | 235 |
202 ResourceContext* resource_context() { return resource_context_; } | 236 ResourceContext* resource_context() { return resource_context_; } |
203 | 237 |
204 protected: | 238 protected: |
205 virtual ~ForwardingFilter() {} | 239 virtual ~ForwardingFilter() {} |
206 | 240 |
207 private: | 241 private: |
208 void GetContexts(const ResourceHostMsg_Request& request, | 242 void GetContexts(const ResourceHostMsg_Request& request, |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
615 if (send_data_received_acks_ && | 649 if (send_data_received_acks_ && |
616 msg->type() == ResourceMsg_DataReceived::ID) { | 650 msg->type() == ResourceMsg_DataReceived::ID) { |
617 GenerateDataReceivedACK(*msg); | 651 GenerateDataReceivedACK(*msg); |
618 } | 652 } |
619 | 653 |
620 if (wait_for_request_complete_loop_ && | 654 if (wait_for_request_complete_loop_ && |
621 msg->type() == ResourceMsg_RequestComplete::ID) { | 655 msg->type() == ResourceMsg_RequestComplete::ID) { |
622 wait_for_request_complete_loop_->Quit(); | 656 wait_for_request_complete_loop_->Quit(); |
623 } | 657 } |
624 | 658 |
659 // Do not release handles in it yet; the accumulator owns them now. | |
625 delete msg; | 660 delete msg; |
626 return true; | 661 return true; |
627 } | 662 } |
628 | 663 |
629 protected: | 664 protected: |
630 // testing::Test | 665 // testing::Test |
631 virtual void SetUp() OVERRIDE { | 666 virtual void SetUp() OVERRIDE { |
632 DCHECK(!test_fixture_); | 667 DCHECK(!test_fixture_); |
633 test_fixture_ = this; | 668 test_fixture_ = this; |
634 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); | 669 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1428 : ForwardingFilter(NULL, resource_context), | 1463 : ForwardingFilter(NULL, resource_context), |
1429 has_canceled_(false), | 1464 has_canceled_(false), |
1430 received_after_canceled_(0) { | 1465 received_after_canceled_(0) { |
1431 } | 1466 } |
1432 | 1467 |
1433 // ForwardingFilter override | 1468 // ForwardingFilter override |
1434 virtual bool Send(IPC::Message* msg) OVERRIDE { | 1469 virtual bool Send(IPC::Message* msg) OVERRIDE { |
1435 // no messages should be received when the process has been canceled | 1470 // no messages should be received when the process has been canceled |
1436 if (has_canceled_) | 1471 if (has_canceled_) |
1437 received_after_canceled_++; | 1472 received_after_canceled_++; |
1473 ReleaseHandlesInMessage(*msg); | |
1438 delete msg; | 1474 delete msg; |
1439 return true; | 1475 return true; |
1440 } | 1476 } |
1441 | 1477 |
1442 bool has_canceled_; | 1478 bool has_canceled_; |
1443 int received_after_canceled_; | 1479 int received_after_canceled_; |
1444 | 1480 |
1445 private: | 1481 private: |
1446 virtual ~TestFilter() {} | 1482 virtual ~TestFilter() {} |
1447 }; | 1483 }; |
(...skipping 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2893 // message loop for the delete itself. (This relies on the delete happening on | 2929 // message loop for the delete itself. (This relies on the delete happening on |
2894 // the FILE thread which is mapped to main thread in this test.) | 2930 // the FILE thread which is mapped to main thread in this test.) |
2895 base::RunLoop().RunUntilIdle(); | 2931 base::RunLoop().RunUntilIdle(); |
2896 | 2932 |
2897 EXPECT_FALSE(base::PathExists(response_head.download_file_path)); | 2933 EXPECT_FALSE(base::PathExists(response_head.download_file_path)); |
2898 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( | 2934 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( |
2899 filter_->child_id(), response_head.download_file_path)); | 2935 filter_->child_id(), response_head.download_file_path)); |
2900 } | 2936 } |
2901 | 2937 |
2902 } // namespace content | 2938 } // namespace content |
OLD | NEW |