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 16 matching lines...) Expand all Loading... | |
162 for (int i = 1; i < static_cast<int>(messages_.size()); i++) { | 193 for (int i = 1; i < static_cast<int>(messages_.size()); i++) { |
163 int id = RequestIDForMessage(messages_[i]); | 194 int id = RequestIDForMessage(messages_[i]); |
164 if (id == cur_id) { | 195 if (id == cur_id) { |
165 cur_requests.push_back(messages_[i]); | 196 cur_requests.push_back(messages_[i]); |
166 messages_.erase(messages_.begin() + i); | 197 messages_.erase(messages_.begin() + i); |
167 i--; | 198 i--; |
168 } | 199 } |
169 } | 200 } |
170 msgs->push_back(cur_requests); | 201 msgs->push_back(cur_requests); |
171 } | 202 } |
172 messages_.erase(messages_.begin()); | 203 messages_.erase(messages_.begin()); |
mmenke
2014/04/28 20:52:08
Aren't we completely skipping the cleanup here?
davidben
2014/04/28 21:20:47
Oh hrm. Looks like it ends up being fine because t
| |
173 } | 204 } |
174 } | 205 } |
175 | 206 |
176 // This class forwards the incoming messages to the ResourceDispatcherHostTest. | |
177 // This is used to emulate different sub-processes, since this filter will | 207 // This is used to emulate different sub-processes, since this filter will |
178 // have a different ID than the original. For the test, we want all the incoming | 208 // have a different ID than the original. |
179 // messages to go to the same place, which is why this forwards. | 209 class TestFilter : public ResourceMessageFilter { |
180 class ForwardingFilter : public ResourceMessageFilter { | |
181 public: | 210 public: |
182 explicit ForwardingFilter(IPC::Sender* dest, | 211 explicit TestFilter(ResourceContext* resource_context) |
183 ResourceContext* resource_context) | |
184 : ResourceMessageFilter( | 212 : ResourceMessageFilter( |
mmenke
2014/04/28 20:52:08
nit: +2 indent (Know this was wrong before)
davidben
2014/04/28 21:20:47
Bounced on tab in emacs a bit.
| |
185 ChildProcessHostImpl::GenerateChildProcessUniqueId(), | 213 ChildProcessHostImpl::GenerateChildProcessUniqueId(), |
186 PROCESS_TYPE_RENDERER, NULL, NULL, NULL, NULL, | 214 PROCESS_TYPE_RENDERER, NULL, NULL, NULL, NULL, |
187 base::Bind(&ForwardingFilter::GetContexts, | 215 base::Bind(&TestFilter::GetContexts, base::Unretained(this))), |
188 base::Unretained(this))), | 216 resource_context_(resource_context), |
189 dest_(dest), | 217 canceled_(false), |
190 resource_context_(resource_context) { | 218 received_after_canceled_(0) { |
191 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id()); | 219 ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id()); |
192 set_peer_pid_for_testing(base::GetCurrentProcId()); | 220 set_peer_pid_for_testing(base::GetCurrentProcId()); |
193 } | 221 } |
194 | 222 |
223 void set_canceled(bool canceled) { canceled_ = canceled; } | |
224 int received_after_canceled() const { return received_after_canceled_; } | |
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 // No messages should be received when the process has been canceled. |
198 return false; | 229 if (canceled_) |
199 return dest_->Send(msg); | 230 received_after_canceled_++; |
231 ReleaseHandlesInMessage(*msg); | |
232 delete msg; | |
233 return true; | |
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 ~TestFilter() {} |
206 | 240 |
207 private: | 241 private: |
208 void GetContexts(const ResourceHostMsg_Request& request, | 242 void GetContexts(const ResourceHostMsg_Request& request, |
209 ResourceContext** resource_context, | 243 ResourceContext** resource_context, |
210 net::URLRequestContext** request_context) { | 244 net::URLRequestContext** request_context) { |
211 *resource_context = resource_context_; | 245 *resource_context = resource_context_; |
212 *request_context = resource_context_->GetRequestContext(); | 246 *request_context = resource_context_->GetRequestContext(); |
213 } | 247 } |
214 | 248 |
249 ResourceContext* resource_context_; | |
250 bool canceled_; | |
251 int received_after_canceled_; | |
252 | |
253 DISALLOW_COPY_AND_ASSIGN(TestFilter); | |
254 }; | |
255 | |
256 | |
257 // This class forwards the incoming messages to the ResourceDispatcherHostTest. | |
258 // For the test, we want all the incoming messages to go to the same place, | |
259 // which is why this forwards. | |
260 class ForwardingFilter : public TestFilter { | |
261 public: | |
262 explicit ForwardingFilter(IPC::Sender* dest, | |
263 ResourceContext* resource_context) | |
264 : TestFilter(resource_context), | |
265 dest_(dest) { | |
266 } | |
267 | |
268 // TestFilter override | |
269 virtual bool Send(IPC::Message* msg) OVERRIDE { | |
270 return dest_->Send(msg); | |
271 } | |
272 | |
273 private: | |
274 virtual ~ForwardingFilter() {} | |
275 | |
215 IPC::Sender* dest_; | 276 IPC::Sender* dest_; |
216 ResourceContext* resource_context_; | |
217 | 277 |
218 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter); | 278 DISALLOW_COPY_AND_ASSIGN(ForwardingFilter); |
219 }; | 279 }; |
220 | 280 |
221 // This class is a variation on URLRequestTestJob that will call | 281 // This class is a variation on URLRequestTestJob that will call |
222 // URLRequest::OnBeforeNetworkStart before starting. | 282 // URLRequest::OnBeforeNetworkStart before starting. |
223 class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob { | 283 class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob { |
224 public: | 284 public: |
225 URLRequestTestDelayedNetworkJob(net::URLRequest* request, | 285 URLRequestTestDelayedNetworkJob(net::URLRequest* request, |
226 net::NetworkDelegate* network_delegate) | 286 net::NetworkDelegate* network_delegate) |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
615 if (send_data_received_acks_ && | 675 if (send_data_received_acks_ && |
616 msg->type() == ResourceMsg_DataReceived::ID) { | 676 msg->type() == ResourceMsg_DataReceived::ID) { |
617 GenerateDataReceivedACK(*msg); | 677 GenerateDataReceivedACK(*msg); |
618 } | 678 } |
619 | 679 |
620 if (wait_for_request_complete_loop_ && | 680 if (wait_for_request_complete_loop_ && |
621 msg->type() == ResourceMsg_RequestComplete::ID) { | 681 msg->type() == ResourceMsg_RequestComplete::ID) { |
622 wait_for_request_complete_loop_->Quit(); | 682 wait_for_request_complete_loop_->Quit(); |
623 } | 683 } |
624 | 684 |
685 // Do not release handles in it yet; the accumulator owns them now. | |
625 delete msg; | 686 delete msg; |
626 return true; | 687 return true; |
627 } | 688 } |
628 | 689 |
629 protected: | 690 protected: |
630 // testing::Test | 691 // testing::Test |
631 virtual void SetUp() OVERRIDE { | 692 virtual void SetUp() OVERRIDE { |
632 DCHECK(!test_fixture_); | 693 DCHECK(!test_fixture_); |
633 test_fixture_ = this; | 694 test_fixture_ = this; |
634 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); | 695 ChildProcessSecurityPolicyImpl::GetInstance()->Add(0); |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1413 ResourceIPCAccumulator::ClassifiedMessages msgs; | 1474 ResourceIPCAccumulator::ClassifiedMessages msgs; |
1414 accum_.GetClassifiedMessages(&msgs); | 1475 accum_.GetClassifiedMessages(&msgs); |
1415 | 1476 |
1416 // Check the cancellation | 1477 // Check the cancellation |
1417 ASSERT_EQ(1U, msgs.size()); | 1478 ASSERT_EQ(1U, msgs.size()); |
1418 ASSERT_EQ(1U, msgs[0].size()); | 1479 ASSERT_EQ(1U, msgs[0].size()); |
1419 | 1480 |
1420 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED); | 1481 CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_ACCESS_DENIED); |
1421 } | 1482 } |
1422 | 1483 |
1423 // The host delegate acts as a second one so we can have some requests | |
1424 // pending and some canceled. | |
1425 class TestFilter : public ForwardingFilter { | |
1426 public: | |
1427 explicit TestFilter(ResourceContext* resource_context) | |
1428 : ForwardingFilter(NULL, resource_context), | |
1429 has_canceled_(false), | |
1430 received_after_canceled_(0) { | |
1431 } | |
1432 | |
1433 // ForwardingFilter override | |
1434 virtual bool Send(IPC::Message* msg) OVERRIDE { | |
1435 // no messages should be received when the process has been canceled | |
1436 if (has_canceled_) | |
1437 received_after_canceled_++; | |
1438 delete msg; | |
1439 return true; | |
1440 } | |
1441 | |
1442 bool has_canceled_; | |
1443 int received_after_canceled_; | |
1444 | |
1445 private: | |
1446 virtual ~TestFilter() {} | |
1447 }; | |
1448 | |
1449 // Tests CancelRequestsForProcess | 1484 // Tests CancelRequestsForProcess |
1450 TEST_F(ResourceDispatcherHostTest, TestProcessCancel) { | 1485 TEST_F(ResourceDispatcherHostTest, TestProcessCancel) { |
1451 scoped_refptr<TestFilter> test_filter = new TestFilter( | 1486 scoped_refptr<TestFilter> test_filter = new TestFilter( |
1452 browser_context_->GetResourceContext()); | 1487 browser_context_->GetResourceContext()); |
1453 child_ids_.insert(test_filter->child_id()); | 1488 child_ids_.insert(test_filter->child_id()); |
1454 | 1489 |
1455 // request 1 goes to the test delegate | 1490 // request 1 goes to the test delegate |
1456 ResourceHostMsg_Request request = CreateResourceRequest( | 1491 ResourceHostMsg_Request request = CreateResourceRequest( |
1457 "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1()); | 1492 "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1()); |
1458 | 1493 |
(...skipping 26 matching lines...) Expand all Loading... | |
1485 //EXPECT_EQ(3, host_.pending_requests()); | 1520 //EXPECT_EQ(3, host_.pending_requests()); |
1486 | 1521 |
1487 // Process test_url_2 and test_url_3 for one level so one callback is called. | 1522 // Process test_url_2 and test_url_3 for one level so one callback is called. |
1488 // We'll cancel test_url_4 (detachable) before processing it to verify that it | 1523 // We'll cancel test_url_4 (detachable) before processing it to verify that it |
1489 // delays the cancel. | 1524 // delays the cancel. |
1490 for (int i = 0; i < 2; i++) | 1525 for (int i = 0; i < 2; i++) |
1491 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage()); | 1526 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage()); |
1492 | 1527 |
1493 // Cancel the requests to the test process. | 1528 // Cancel the requests to the test process. |
1494 host_.CancelRequestsForProcess(filter_->child_id()); | 1529 host_.CancelRequestsForProcess(filter_->child_id()); |
1495 test_filter->has_canceled_ = true; | 1530 test_filter->set_canceled(true); |
1496 | 1531 |
1497 // The requests should all be cancelled, except request 4, which is detached. | 1532 // The requests should all be cancelled, except request 4, which is detached. |
1498 EXPECT_EQ(1, host_.pending_requests()); | 1533 EXPECT_EQ(1, host_.pending_requests()); |
1499 GlobalRequestID global_request_id(filter_->child_id(), 4); | 1534 GlobalRequestID global_request_id(filter_->child_id(), 4); |
1500 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest( | 1535 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest( |
1501 host_.GetURLRequest(global_request_id)); | 1536 host_.GetURLRequest(global_request_id)); |
1502 ASSERT_TRUE(info->detachable_handler()->is_detached()); | 1537 ASSERT_TRUE(info->detachable_handler()->is_detached()); |
1503 | 1538 |
1504 // Flush all the pending requests. | 1539 // Flush all the pending requests. |
1505 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} | 1540 while (net::URLRequestTestJob::ProcessOnePendingMessage()) {} |
1506 | 1541 |
1507 EXPECT_EQ(0, host_.pending_requests()); | 1542 EXPECT_EQ(0, host_.pending_requests()); |
1508 | 1543 |
1509 // The test delegate should not have gotten any messages after being canceled. | 1544 // The test delegate should not have gotten any messages after being canceled. |
1510 ASSERT_EQ(0, test_filter->received_after_canceled_); | 1545 ASSERT_EQ(0, test_filter->received_after_canceled()); |
1511 | 1546 |
1512 // There should be two results. | 1547 // There should be two results. |
1513 ResourceIPCAccumulator::ClassifiedMessages msgs; | 1548 ResourceIPCAccumulator::ClassifiedMessages msgs; |
1514 accum_.GetClassifiedMessages(&msgs); | 1549 accum_.GetClassifiedMessages(&msgs); |
1515 ASSERT_EQ(2U, msgs.size()); | 1550 ASSERT_EQ(2U, msgs.size()); |
1516 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2()); | 1551 CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2()); |
1517 // The detachable request was cancelled by the renderer before it | 1552 // The detachable request was cancelled by the renderer before it |
1518 // finished. From the perspective of the renderer, it should have cancelled. | 1553 // finished. From the perspective of the renderer, it should have cancelled. |
1519 ASSERT_EQ(2U, msgs[1].size()); | 1554 ASSERT_EQ(2U, msgs[1].size()); |
1520 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type()); | 1555 ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type()); |
(...skipping 1372 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 | 2928 // 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.) | 2929 // the FILE thread which is mapped to main thread in this test.) |
2895 base::RunLoop().RunUntilIdle(); | 2930 base::RunLoop().RunUntilIdle(); |
2896 | 2931 |
2897 EXPECT_FALSE(base::PathExists(response_head.download_file_path)); | 2932 EXPECT_FALSE(base::PathExists(response_head.download_file_path)); |
2898 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( | 2933 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( |
2899 filter_->child_id(), response_head.download_file_path)); | 2934 filter_->child_id(), response_head.download_file_path)); |
2900 } | 2935 } |
2901 | 2936 |
2902 } // namespace content | 2937 } // namespace content |
OLD | NEW |