| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "build/build_config.h" | 5 #include "build/build_config.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| 11 #include <memory> | 11 #include <memory> |
| 12 #include <set> | 12 #include <set> |
| 13 | 13 |
| 14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
| 15 #include "ipc/attachment_broker.h" | |
| 16 #include "ipc/brokerable_attachment.h" | 15 #include "ipc/brokerable_attachment.h" |
| 17 #include "ipc/ipc_channel_reader.h" | 16 #include "ipc/ipc_channel_reader.h" |
| 18 #include "ipc/placeholder_brokerable_attachment.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 18 |
| 21 // Whether IPC::Message::FindNext() can determine message size for | |
| 22 // partial messages. The condition is from FindNext() implementation. | |
| 23 #if USE_ATTACHMENT_BROKER | |
| 24 #define MESSAGE_FINDNEXT_PARTIAL 0 | |
| 25 #else | |
| 26 #define MESSAGE_FINDNEXT_PARTIAL 1 | |
| 27 #endif | |
| 28 | |
| 29 namespace IPC { | 19 namespace IPC { |
| 30 namespace internal { | 20 namespace internal { |
| 31 | 21 |
| 32 namespace { | 22 namespace { |
| 33 | 23 |
| 34 #if USE_ATTACHMENT_BROKER | |
| 35 | |
| 36 class MockAttachment : public BrokerableAttachment { | |
| 37 public: | |
| 38 MockAttachment() {} | |
| 39 MockAttachment(BrokerableAttachment::AttachmentId id) | |
| 40 : BrokerableAttachment(id) {} | |
| 41 | |
| 42 #if defined(OS_POSIX) | |
| 43 base::PlatformFile TakePlatformFile() override { | |
| 44 return base::PlatformFile(); | |
| 45 } | |
| 46 #endif // OS_POSIX | |
| 47 | |
| 48 BrokerableType GetBrokerableType() const override { return WIN_HANDLE; } | |
| 49 | |
| 50 private: | |
| 51 ~MockAttachment() override {} | |
| 52 }; | |
| 53 | |
| 54 class MockAttachmentBroker : public AttachmentBroker { | |
| 55 public: | |
| 56 typedef std::set<scoped_refptr<BrokerableAttachment>> AttachmentSet; | |
| 57 | |
| 58 bool SendAttachmentToProcess( | |
| 59 const scoped_refptr<BrokerableAttachment>& attachment, | |
| 60 base::ProcessId destination_process) override { | |
| 61 return false; | |
| 62 } | |
| 63 | |
| 64 bool OnMessageReceived(const Message& message) override { return false; } | |
| 65 | |
| 66 void AddAttachment(scoped_refptr<BrokerableAttachment> attachment) { | |
| 67 get_attachments()->push_back(attachment); | |
| 68 NotifyObservers(attachment->GetIdentifier()); | |
| 69 } | |
| 70 }; | |
| 71 | |
| 72 #endif // USE_ATTACHMENT_BROKER | |
| 73 | |
| 74 class MockChannelReader : public ChannelReader { | 24 class MockChannelReader : public ChannelReader { |
| 75 public: | 25 public: |
| 76 MockChannelReader() | 26 MockChannelReader() |
| 77 : ChannelReader(nullptr), last_dispatched_message_(nullptr) {} | 27 : ChannelReader(nullptr), last_dispatched_message_(nullptr) {} |
| 78 | 28 |
| 79 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override { | 29 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override { |
| 80 if (data_.empty()) | 30 if (data_.empty()) |
| 81 return READ_PENDING; | 31 return READ_PENDING; |
| 82 | 32 |
| 83 size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size()); | 33 size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size()); |
| 84 memcpy(buffer, data_.data(), read_len); | 34 memcpy(buffer, data_.data(), read_len); |
| 85 *bytes_read = static_cast<int>(read_len); | 35 *bytes_read = static_cast<int>(read_len); |
| 86 data_.erase(0, read_len); | 36 data_.erase(0, read_len); |
| 87 return READ_SUCCEEDED; | 37 return READ_SUCCEEDED; |
| 88 } | 38 } |
| 89 | 39 |
| 90 bool ShouldDispatchInputMessage(Message* msg) override { return true; } | 40 bool ShouldDispatchInputMessage(Message* msg) override { return true; } |
| 91 | 41 |
| 92 bool GetNonBrokeredAttachments(Message* msg) override { return true; } | 42 bool GetNonBrokeredAttachments(Message* msg) override { return true; } |
| 93 | 43 |
| 94 bool DidEmptyInputBuffers() override { return true; } | 44 bool DidEmptyInputBuffers() override { return true; } |
| 95 | 45 |
| 96 void HandleInternalMessage(const Message& msg) override {} | 46 void HandleInternalMessage(const Message& msg) override {} |
| 97 | 47 |
| 98 void DispatchMessage(Message* m) override { last_dispatched_message_ = m; } | 48 void DispatchMessage(Message* m) override { last_dispatched_message_ = m; } |
| 99 | 49 |
| 100 base::ProcessId GetSenderPID() override { return base::kNullProcessId; } | 50 base::ProcessId GetSenderPID() override { return base::kNullProcessId; } |
| 101 | 51 |
| 102 bool IsAttachmentBrokerEndpoint() override { return false; } | |
| 103 | |
| 104 AttachmentBroker* GetAttachmentBroker() override { return broker_; } | |
| 105 | |
| 106 // This instance takes ownership of |m|. | |
| 107 void AddMessageForDispatch(Message* m) { | |
| 108 get_queued_messages()->push_back(m); | |
| 109 } | |
| 110 | |
| 111 Message* get_last_dispatched_message() { return last_dispatched_message_; } | 52 Message* get_last_dispatched_message() { return last_dispatched_message_; } |
| 112 | 53 |
| 113 void set_broker(AttachmentBroker* broker) { broker_ = broker; } | |
| 114 | |
| 115 void AppendData(const void* data, size_t size) { | 54 void AppendData(const void* data, size_t size) { |
| 116 data_.append(static_cast<const char*>(data), size); | 55 data_.append(static_cast<const char*>(data), size); |
| 117 } | 56 } |
| 118 | 57 |
| 119 void AppendMessageData(const Message& message) { | 58 void AppendMessageData(const Message& message) { |
| 120 AppendData(message.data(), message.size()); | 59 AppendData(message.data(), message.size()); |
| 121 } | 60 } |
| 122 | 61 |
| 123 private: | 62 private: |
| 124 Message* last_dispatched_message_; | 63 Message* last_dispatched_message_; |
| 125 AttachmentBroker* broker_; | |
| 126 std::string data_; | 64 std::string data_; |
| 127 }; | 65 }; |
| 128 | 66 |
| 129 class ExposedMessage: public Message { | 67 class ExposedMessage: public Message { |
| 130 public: | 68 public: |
| 131 using Message::Header; | 69 using Message::Header; |
| 132 using Message::header; | 70 using Message::header; |
| 133 }; | 71 }; |
| 134 | 72 |
| 135 // Payload that makes messages large | 73 // Payload that makes messages large |
| 136 const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2; | 74 const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2; |
| 137 | 75 |
| 138 } // namespace | 76 } // namespace |
| 139 | 77 |
| 140 #if USE_ATTACHMENT_BROKER | |
| 141 | |
| 142 TEST(ChannelReaderTest, AttachmentAlreadyBrokered) { | |
| 143 MockAttachmentBroker broker; | |
| 144 MockChannelReader reader; | |
| 145 reader.set_broker(&broker); | |
| 146 scoped_refptr<MockAttachment> attachment(new MockAttachment); | |
| 147 broker.AddAttachment(attachment); | |
| 148 | |
| 149 Message* m = new Message; | |
| 150 PlaceholderBrokerableAttachment* needs_brokering_attachment = | |
| 151 new PlaceholderBrokerableAttachment(attachment->GetIdentifier()); | |
| 152 EXPECT_TRUE(m->WriteAttachment(needs_brokering_attachment)); | |
| 153 reader.AddMessageForDispatch(m); | |
| 154 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, reader.DispatchMessages()); | |
| 155 EXPECT_EQ(m, reader.get_last_dispatched_message()); | |
| 156 } | |
| 157 | |
| 158 TEST(ChannelReaderTest, AttachmentNotYetBrokered) { | |
| 159 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoopForIO()); | |
| 160 | |
| 161 MockAttachmentBroker broker; | |
| 162 MockChannelReader reader; | |
| 163 reader.set_broker(&broker); | |
| 164 scoped_refptr<MockAttachment> attachment(new MockAttachment); | |
| 165 | |
| 166 Message* m = new Message; | |
| 167 PlaceholderBrokerableAttachment* needs_brokering_attachment = | |
| 168 new PlaceholderBrokerableAttachment(attachment->GetIdentifier()); | |
| 169 EXPECT_TRUE(m->WriteAttachment(needs_brokering_attachment)); | |
| 170 reader.AddMessageForDispatch(m); | |
| 171 EXPECT_EQ(ChannelReader::DISPATCH_WAITING_ON_BROKER, | |
| 172 reader.DispatchMessages()); | |
| 173 EXPECT_EQ(nullptr, reader.get_last_dispatched_message()); | |
| 174 | |
| 175 broker.AddAttachment(attachment); | |
| 176 base::RunLoop run_loop; | |
| 177 run_loop.RunUntilIdle(); | |
| 178 | |
| 179 EXPECT_EQ(m, reader.get_last_dispatched_message()); | |
| 180 } | |
| 181 | |
| 182 #endif // USE_ATTACHMENT_BROKER | |
| 183 | |
| 184 #if !USE_ATTACHMENT_BROKER | |
| 185 | |
| 186 // We can determine message size from its header (and hence resize the buffer) | 78 // We can determine message size from its header (and hence resize the buffer) |
| 187 // only when attachment broker is not used, see IPC::Message::FindNext(). | 79 // only when attachment broker is not used, see IPC::Message::FindNext(). |
| 188 | 80 |
| 189 TEST(ChannelReaderTest, ResizeOverflowBuffer) { | 81 TEST(ChannelReaderTest, ResizeOverflowBuffer) { |
| 190 MockChannelReader reader; | 82 MockChannelReader reader; |
| 191 | 83 |
| 192 ExposedMessage::Header header = {}; | 84 ExposedMessage::Header header = {}; |
| 193 | 85 |
| 194 header.payload_size = 128 * 1024; | 86 header.payload_size = 128 * 1024; |
| 195 EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size); | 87 EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 220 reinterpret_cast<const char*>(&header), sizeof(header))); | 112 reinterpret_cast<const char*>(&header), sizeof(header))); |
| 221 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before); | 113 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before); |
| 222 | 114 |
| 223 // Payload size is maximum int32_t value | 115 // Payload size is maximum int32_t value |
| 224 header.payload_size = std::numeric_limits<int32_t>::max(); | 116 header.payload_size = std::numeric_limits<int32_t>::max(); |
| 225 EXPECT_FALSE(reader.TranslateInputData( | 117 EXPECT_FALSE(reader.TranslateInputData( |
| 226 reinterpret_cast<const char*>(&header), sizeof(header))); | 118 reinterpret_cast<const char*>(&header), sizeof(header))); |
| 227 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before); | 119 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before); |
| 228 } | 120 } |
| 229 | 121 |
| 230 #endif // !USE_ATTACHMENT_BROKER | |
| 231 | |
| 232 TEST(ChannelReaderTest, TrimBuffer) { | 122 TEST(ChannelReaderTest, TrimBuffer) { |
| 233 // ChannelReader uses std::string as a buffer, and calls reserve() | 123 // ChannelReader uses std::string as a buffer, and calls reserve() |
| 234 // to trim it to kMaximumReadBufferSize. However, an implementation | 124 // to trim it to kMaximumReadBufferSize. However, an implementation |
| 235 // is free to actually reserve a larger amount. | 125 // is free to actually reserve a larger amount. |
| 236 size_t trimmed_buffer_size; | 126 size_t trimmed_buffer_size; |
| 237 { | 127 { |
| 238 std::string buf; | 128 std::string buf; |
| 239 buf.reserve(Channel::kMaximumReadBufferSize); | 129 buf.reserve(Channel::kMaximumReadBufferSize); |
| 240 trimmed_buffer_size = buf.capacity(); | 130 trimmed_buffer_size = buf.capacity(); |
| 241 } | 131 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 267 MockChannelReader reader; | 157 MockChannelReader reader; |
| 268 | 158 |
| 269 ExposedMessage message; | 159 ExposedMessage message; |
| 270 message.WriteString(std::string(LargePayloadSize, 'X')); | 160 message.WriteString(std::string(LargePayloadSize, 'X')); |
| 271 | 161 |
| 272 // Write and process message header | 162 // Write and process message header |
| 273 reader.AppendData(message.header(), sizeof(ExposedMessage::Header)); | 163 reader.AppendData(message.header(), sizeof(ExposedMessage::Header)); |
| 274 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, | 164 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, |
| 275 reader.ProcessIncomingMessages()); | 165 reader.ProcessIncomingMessages()); |
| 276 | 166 |
| 277 #if MESSAGE_FINDNEXT_PARTIAL | |
| 278 // We determined message size for the message from its header, so | 167 // We determined message size for the message from its header, so |
| 279 // we resized the buffer to fit. | 168 // we resized the buffer to fit. |
| 280 EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size()); | 169 EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size()); |
| 281 #else | |
| 282 // We couldn't determine message size, so we didn't resize the buffer. | |
| 283 #endif | |
| 284 | 170 |
| 285 // Write and process payload | 171 // Write and process payload |
| 286 reader.AppendData(message.payload(), message.payload_size()); | 172 reader.AppendData(message.payload(), message.payload_size()); |
| 287 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, | 173 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, |
| 288 reader.ProcessIncomingMessages()); | 174 reader.ProcessIncomingMessages()); |
| 289 | 175 |
| 290 // But once we process the message, we trim the buffer | 176 // But once we process the message, we trim the buffer |
| 291 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); | 177 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); |
| 292 } | 178 } |
| 293 | 179 |
| 294 // Buffer is not trimmed if the next message is also large. | 180 // Buffer is not trimmed if the next message is also large. |
| 295 { | 181 { |
| 296 MockChannelReader reader; | 182 MockChannelReader reader; |
| 297 | 183 |
| 298 // Write large message | 184 // Write large message |
| 299 Message message1; | 185 Message message1; |
| 300 message1.WriteString(std::string(LargePayloadSize * 2, 'X')); | 186 message1.WriteString(std::string(LargePayloadSize * 2, 'X')); |
| 301 reader.AppendMessageData(message1); | 187 reader.AppendMessageData(message1); |
| 302 | 188 |
| 303 // Write header for the next large message | 189 // Write header for the next large message |
| 304 ExposedMessage message2; | 190 ExposedMessage message2; |
| 305 message2.WriteString(std::string(LargePayloadSize, 'Y')); | 191 message2.WriteString(std::string(LargePayloadSize, 'Y')); |
| 306 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); | 192 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); |
| 307 | 193 |
| 308 // Process messages | 194 // Process messages |
| 309 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, | 195 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, |
| 310 reader.ProcessIncomingMessages()); | 196 reader.ProcessIncomingMessages()); |
| 311 | 197 |
| 312 #if MESSAGE_FINDNEXT_PARTIAL | |
| 313 // We determined message size for the second (partial) message, so | 198 // We determined message size for the second (partial) message, so |
| 314 // we resized the buffer to fit. | 199 // we resized the buffer to fit. |
| 315 EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size()); | 200 EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size()); |
| 316 #else | |
| 317 // We couldn't determine message size for the second (partial) message, | |
| 318 // so we trimmed the buffer. | |
| 319 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); | |
| 320 #endif | |
| 321 } | 201 } |
| 322 | 202 |
| 323 // Buffer resized appropriately if next message is larger than the first. | 203 // Buffer resized appropriately if next message is larger than the first. |
| 324 // (Similar to the test above except for the order of messages.) | 204 // (Similar to the test above except for the order of messages.) |
| 325 { | 205 { |
| 326 MockChannelReader reader; | 206 MockChannelReader reader; |
| 327 | 207 |
| 328 // Write large message | 208 // Write large message |
| 329 Message message1; | 209 Message message1; |
| 330 message1.WriteString(std::string(LargePayloadSize, 'Y')); | 210 message1.WriteString(std::string(LargePayloadSize, 'Y')); |
| 331 reader.AppendMessageData(message1); | 211 reader.AppendMessageData(message1); |
| 332 | 212 |
| 333 // Write header for the next even larger message | 213 // Write header for the next even larger message |
| 334 ExposedMessage message2; | 214 ExposedMessage message2; |
| 335 message2.WriteString(std::string(LargePayloadSize * 2, 'X')); | 215 message2.WriteString(std::string(LargePayloadSize * 2, 'X')); |
| 336 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); | 216 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); |
| 337 | 217 |
| 338 // Process messages | 218 // Process messages |
| 339 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, | 219 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, |
| 340 reader.ProcessIncomingMessages()); | 220 reader.ProcessIncomingMessages()); |
| 341 | 221 |
| 342 #if MESSAGE_FINDNEXT_PARTIAL | |
| 343 // We determined message size for the second (partial) message, and | 222 // We determined message size for the second (partial) message, and |
| 344 // resized the buffer to fit it. | 223 // resized the buffer to fit it. |
| 345 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); | 224 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); |
| 346 #else | |
| 347 // We couldn't determine message size for the second (partial) message, | |
| 348 // so we trimmed the buffer. | |
| 349 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size); | |
| 350 #endif | |
| 351 } | 225 } |
| 352 | 226 |
| 353 // Buffer is not trimmed if we've just resized it to accommodate large | 227 // Buffer is not trimmed if we've just resized it to accommodate large |
| 354 // incoming message. | 228 // incoming message. |
| 355 { | 229 { |
| 356 MockChannelReader reader; | 230 MockChannelReader reader; |
| 357 | 231 |
| 358 // Write small message | 232 // Write small message |
| 359 Message message1; | 233 Message message1; |
| 360 message1.WriteString(std::string(11, 'X')); | 234 message1.WriteString(std::string(11, 'X')); |
| 361 reader.AppendMessageData(message1); | 235 reader.AppendMessageData(message1); |
| 362 | 236 |
| 363 // Write header for the next large message | 237 // Write header for the next large message |
| 364 ExposedMessage message2; | 238 ExposedMessage message2; |
| 365 message2.WriteString(std::string(LargePayloadSize, 'Y')); | 239 message2.WriteString(std::string(LargePayloadSize, 'Y')); |
| 366 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); | 240 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header)); |
| 367 | 241 |
| 368 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, | 242 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED, |
| 369 reader.ProcessIncomingMessages()); | 243 reader.ProcessIncomingMessages()); |
| 370 | 244 |
| 371 #if MESSAGE_FINDNEXT_PARTIAL | |
| 372 // We determined message size for the second (partial) message, so | 245 // We determined message size for the second (partial) message, so |
| 373 // we resized the buffer to fit. | 246 // we resized the buffer to fit. |
| 374 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); | 247 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size()); |
| 375 #else | |
| 376 // We couldn't determine size for the second (partial) message, and | |
| 377 // first message was small, so we did nothing. | |
| 378 #endif | |
| 379 } | 248 } |
| 380 } | 249 } |
| 381 | 250 |
| 382 } // namespace internal | 251 } // namespace internal |
| 383 } // namespace IPC | 252 } // namespace IPC |
| OLD | NEW |