Chromium Code Reviews| 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 |