| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ipc/ipc_message_attachment_set.h" | 5 #include "ipc/ipc_message_attachment_set.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/posix/eintr_wrapper.h" | 9 #include "base/posix/eintr_wrapper.h" |
| 10 #include "ipc/ipc_message_attachment.h" | 10 #include "ipc/ipc_message_attachment.h" |
| 11 #include "ipc/ipc_platform_file_attachment.h" | |
| 12 | 11 |
| 13 #if defined(OS_POSIX) | 12 #if defined(OS_POSIX) |
| 14 #include <sys/types.h> | 13 #include <sys/types.h> |
| 15 #include <sys/stat.h> | 14 #include <sys/stat.h> |
| 16 #include <unistd.h> | 15 #include <unistd.h> |
| 16 #include "ipc/ipc_platform_file_attachment_posix.h" |
| 17 #endif // OS_POSIX | 17 #endif // OS_POSIX |
| 18 | 18 |
| 19 namespace IPC { | 19 namespace IPC { |
| 20 | 20 |
| 21 MessageAttachmentSet::MessageAttachmentSet() | 21 MessageAttachmentSet::MessageAttachmentSet() |
| 22 : consumed_descriptor_highwater_(0) { | 22 : consumed_descriptor_highwater_(0) { |
| 23 } | 23 } |
| 24 | 24 |
| 25 MessageAttachmentSet::~MessageAttachmentSet() { | 25 MessageAttachmentSet::~MessageAttachmentSet() { |
| 26 if (consumed_descriptor_highwater_ == size()) | 26 if (consumed_descriptor_highwater_ == size()) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 42 return std::count_if(attachments_.begin(), attachments_.end(), | 42 return std::count_if(attachments_.begin(), attachments_.end(), |
| 43 [](scoped_refptr<MessageAttachment> i) { | 43 [](scoped_refptr<MessageAttachment> i) { |
| 44 return i->GetType() == MessageAttachment::TYPE_PLATFORM_FILE; | 44 return i->GetType() == MessageAttachment::TYPE_PLATFORM_FILE; |
| 45 }); | 45 }); |
| 46 } | 46 } |
| 47 | 47 |
| 48 unsigned MessageAttachmentSet::size() const { | 48 unsigned MessageAttachmentSet::size() const { |
| 49 return static_cast<unsigned>(attachments_.size()); | 49 return static_cast<unsigned>(attachments_.size()); |
| 50 } | 50 } |
| 51 | 51 |
| 52 void MessageAttachmentSet::AddAttachment( | 52 bool MessageAttachmentSet::AddAttachment( |
| 53 scoped_refptr<MessageAttachment> attachment) { | 53 scoped_refptr<MessageAttachment> attachment) { |
| 54 #if defined(OS_POSIX) |
| 55 if (attachment->GetType() != MessageAttachment::TYPE_PLATFORM_FILE || |
| 56 num_descriptors() == kMaxDescriptorsPerMessage) { |
| 57 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; |
| 58 return false; |
| 59 } |
| 60 #endif |
| 61 |
| 54 attachments_.push_back(attachment); | 62 attachments_.push_back(attachment); |
| 63 return true; |
| 55 } | 64 } |
| 56 | 65 |
| 57 scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt( | 66 scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt( |
| 58 unsigned index) { | 67 unsigned index) { |
| 59 if (index >= size()) { | 68 if (index >= size()) { |
| 60 DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size(); | 69 DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size(); |
| 61 return scoped_refptr<MessageAttachment>(); | 70 return scoped_refptr<MessageAttachment>(); |
| 62 } | 71 } |
| 63 | 72 |
| 64 // We should always walk the descriptors in order, so it's reasonable to | 73 // We should always walk the descriptors in order, so it's reasonable to |
| (...skipping 23 matching lines...) Expand all Loading... |
| 88 if (index != consumed_descriptor_highwater_) | 97 if (index != consumed_descriptor_highwater_) |
| 89 return scoped_refptr<MessageAttachment>(); | 98 return scoped_refptr<MessageAttachment>(); |
| 90 | 99 |
| 91 consumed_descriptor_highwater_ = index + 1; | 100 consumed_descriptor_highwater_ = index + 1; |
| 92 | 101 |
| 93 return attachments_[index]; | 102 return attachments_[index]; |
| 94 } | 103 } |
| 95 | 104 |
| 96 #if defined(OS_POSIX) | 105 #if defined(OS_POSIX) |
| 97 | 106 |
| 98 bool MessageAttachmentSet::AddToBorrow(base::PlatformFile fd) { | |
| 99 DCHECK_EQ(consumed_descriptor_highwater_, 0u); | |
| 100 | |
| 101 if (num_descriptors() == kMaxDescriptorsPerMessage) { | |
| 102 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; | |
| 103 return false; | |
| 104 } | |
| 105 | |
| 106 AddAttachment(new internal::PlatformFileAttachment(fd)); | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 bool MessageAttachmentSet::AddToOwn(base::ScopedFD fd) { | |
| 111 DCHECK_EQ(consumed_descriptor_highwater_, 0u); | |
| 112 | |
| 113 if (num_descriptors() == kMaxDescriptorsPerMessage) { | |
| 114 DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 AddAttachment(new internal::PlatformFileAttachment(fd.get())); | |
| 119 owned_descriptors_.push_back(new base::ScopedFD(fd.Pass())); | |
| 120 DCHECK(num_descriptors() <= kMaxDescriptorsPerMessage); | |
| 121 return true; | |
| 122 } | |
| 123 | |
| 124 base::PlatformFile MessageAttachmentSet::TakeDescriptorAt(unsigned index) { | |
| 125 scoped_refptr<MessageAttachment> attachment = GetAttachmentAt(index); | |
| 126 if (!attachment) | |
| 127 return -1; | |
| 128 | |
| 129 base::PlatformFile file = internal::GetPlatformFile(attachment); | |
| 130 | |
| 131 // TODO(morrita): In production, attachments_.size() should be same as | |
| 132 // owned_descriptors_.size() as all read descriptors are owned by Message. | |
| 133 // We have to do this because unit test breaks this assumption. It should be | |
| 134 // changed to exercise with own-able descriptors. | |
| 135 for (ScopedVector<base::ScopedFD>::const_iterator i = | |
| 136 owned_descriptors_.begin(); | |
| 137 i != owned_descriptors_.end(); ++i) { | |
| 138 if ((*i)->get() == file) { | |
| 139 ignore_result((*i)->release()); | |
| 140 break; | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 return file; | |
| 145 } | |
| 146 | |
| 147 void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const { | 107 void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const { |
| 148 for (size_t i = 0; i != attachments_.size(); ++i) | 108 for (size_t i = 0; i != attachments_.size(); ++i) |
| 149 buffer[i] = internal::GetPlatformFile(attachments_[i]); | 109 buffer[i] = internal::GetPlatformFile(attachments_[i]); |
| 150 } | 110 } |
| 151 | 111 |
| 152 bool MessageAttachmentSet::ContainsDirectoryDescriptor() const { | 112 bool MessageAttachmentSet::ContainsDirectoryDescriptor() const { |
| 153 struct stat st; | 113 struct stat st; |
| 154 | 114 |
| 155 for (auto i = attachments_.begin(); i != attachments_.end(); ++i) { | 115 for (auto i = attachments_.begin(); i != attachments_.end(); ++i) { |
| 156 if (fstat(internal::GetPlatformFile(*i), &st) == 0 && S_ISDIR(st.st_mode)) | 116 if (fstat(internal::GetPlatformFile(*i), &st) == 0 && S_ISDIR(st.st_mode)) |
| 157 return true; | 117 return true; |
| 158 } | 118 } |
| 159 | 119 |
| 160 return false; | 120 return false; |
| 161 } | 121 } |
| 162 | 122 |
| 163 void MessageAttachmentSet::CommitAll() { | 123 void MessageAttachmentSet::CommitAll() { |
| 164 attachments_.clear(); | 124 attachments_.clear(); |
| 165 owned_descriptors_.clear(); | |
| 166 consumed_descriptor_highwater_ = 0; | 125 consumed_descriptor_highwater_ = 0; |
| 167 } | 126 } |
| 168 | 127 |
| 169 void MessageAttachmentSet::ReleaseFDsToClose( | 128 void MessageAttachmentSet::ReleaseFDsToClose( |
| 170 std::vector<base::PlatformFile>* fds) { | 129 std::vector<base::PlatformFile>* fds) { |
| 171 for (ScopedVector<base::ScopedFD>::iterator i = owned_descriptors_.begin(); | 130 for (size_t i = 0; i < attachments_.size(); ++i) { |
| 172 i != owned_descriptors_.end(); ++i) { | 131 internal::PlatformFileAttachment* file = |
| 173 fds->push_back((*i)->release()); | 132 static_cast<internal::PlatformFileAttachment*>(attachments_[i].get()); |
| 133 if (file->Owns()) |
| 134 fds->push_back(file->TakePlatformFile()); |
| 174 } | 135 } |
| 175 | 136 |
| 176 CommitAll(); | 137 CommitAll(); |
| 177 } | 138 } |
| 178 | 139 |
| 179 void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer, | 140 void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer, |
| 180 unsigned count) { | 141 unsigned count) { |
| 181 DCHECK(count <= kMaxDescriptorsPerMessage); | 142 DCHECK(count <= kMaxDescriptorsPerMessage); |
| 182 DCHECK_EQ(num_descriptors(), 0u); | 143 DCHECK_EQ(num_descriptors(), 0u); |
| 183 DCHECK_EQ(consumed_descriptor_highwater_, 0u); | 144 DCHECK_EQ(consumed_descriptor_highwater_, 0u); |
| 184 | 145 |
| 185 attachments_.reserve(count); | 146 attachments_.reserve(count); |
| 186 owned_descriptors_.reserve(count); | 147 for (unsigned i = 0; i < count; ++i) |
| 187 for (unsigned i = 0; i < count; ++i) { | 148 AddAttachment( |
| 188 AddAttachment(new internal::PlatformFileAttachment(buffer[i])); | 149 new internal::PlatformFileAttachment(base::ScopedFD(buffer[i]))); |
| 189 owned_descriptors_.push_back(new base::ScopedFD(buffer[i])); | |
| 190 } | |
| 191 } | 150 } |
| 192 | 151 |
| 193 #endif // OS_POSIX | 152 #endif // OS_POSIX |
| 194 | 153 |
| 195 } // namespace IPC | 154 } // namespace IPC |
| 196 | 155 |
| 197 | 156 |
| OLD | NEW |