Chromium Code Reviews| Index: mojo/edk/system/parent_token_serializer_win.cc |
| diff --git a/mojo/edk/system/parent_token_serializer_win.cc b/mojo/edk/system/parent_token_serializer_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..16e12f68ba31000a982479c8c0f169915d3d70f4 |
| --- /dev/null |
| +++ b/mojo/edk/system/parent_token_serializer_win.cc |
| @@ -0,0 +1,170 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "mojo/edk/system/parent_token_serializer_win.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/lazy_instance.h" |
| +#include "mojo/edk/embedder/platform_channel_pair.h" |
| +#include "mojo/edk/system/configuration.h" |
| +#include "mojo/edk/system/parent_token_serializer_state_win.h" |
| +#include "mojo/edk/system/token_serializer_messages_win.h" |
| + |
| +namespace mojo { |
| +namespace edk { |
| + |
| +namespace { |
| +static const int kDefaultReadBufferSize = 256; |
| +} |
| + |
| +ParentTokenSerializer::ParentTokenSerializer(HANDLE child_process, |
| + ScopedPlatformHandle pipe) |
| + : child_process_(child_process), |
| + pipe_(pipe.Pass()), |
| + num_bytes_read_(0) { |
| + memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
| + read_context_.handler = this; |
| + memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); |
| + write_context_.handler = this; |
| + |
| + ParentTokenSerializerState::GetInstance()->token_serialize_thread()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ParentTokenSerializer::RegisterIOHandler, |
| + base::Unretained(this))); |
| + read_data_.resize(kDefaultReadBufferSize); |
|
yzshen1
2015/11/20 20:39:55
Please move this resize() above the post task. Bec
jam
2015/11/21 01:26:09
done, good catch
|
| +} |
| + |
| +ParentTokenSerializer::~ParentTokenSerializer() { |
| +} |
| + |
| +void ParentTokenSerializer::RegisterIOHandler() { |
| + base::MessageLoopForIO::current()->RegisterIOHandler( |
| + pipe_.get().handle, this); |
| + BeginRead(); |
| +} |
| + |
| +void ParentTokenSerializer::BeginRead() { |
| + BOOL rv = ReadFile(pipe_.get().handle, &read_data_[num_bytes_read_], |
| + static_cast<int>(read_data_.size() - num_bytes_read_), |
| + nullptr, &read_context_.overlapped); |
| + DCHECK(rv || |
| + GetLastError() == ERROR_IO_PENDING || |
| + GetLastError() == ERROR_BROKEN_PIPE); |
|
yzshen1
2015/11/20 20:39:55
When the result is ERROR_BROKEN_PIPE, do we still
jam
2015/11/21 01:26:09
good point, deleted for broken pipe case
|
| +} |
| + |
| +void ParentTokenSerializer::OnIOCompleted( |
| + base::MessageLoopForIO::IOContext* context, |
| + DWORD bytes_transferred, |
| + DWORD error) { |
| + if (context != &read_context_) |
| + return; |
| + |
| + if (error == ERROR_BROKEN_PIPE) { |
| + delete this; |
| + return; // Child process exited or crashed. |
| + } |
| + |
| + if (error != ERROR_SUCCESS) { |
| + NOTREACHED() << "Error " << error << " in ParentTokenSerializer."; |
| + delete this; |
| + return; |
| + } |
| + |
| + num_bytes_read_ += bytes_transferred; |
| + CHECK_GE(num_bytes_read_, sizeof(uint32_t)); |
| + TokenSerializerMessage* message = |
| + reinterpret_cast<TokenSerializerMessage*>(&read_data_[0]); |
| + if (num_bytes_read_ < message->size) { |
| + read_data_.resize(message->size); |
| + BeginRead(); |
| + return; |
| + } |
| + |
| + if (message->id == CREATE_PLATFORM_CHANNEL_PAIR) { |
| + PlatformChannelPair channel_pair; |
| + uint32_t response_size = 2 * sizeof(HANDLE); |
| + write_data_.resize(response_size); |
| + HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]); |
| + handles[0] = DuplicateToChild( |
| + channel_pair.PassServerHandle().release().handle); |
| + handles[1] = DuplicateToChild( |
| + channel_pair.PassClientHandle().release().handle); |
| + } else if (message->id == HANDLE_TO_TOKEN) { |
| + uint32_t count = |
| + (message->size - kTokenSerializerMessageHeaderSize) / sizeof(HANDLE); |
| + if (count > GetConfiguration().max_message_num_handles) { |
| + NOTREACHED() << "Too many handles from child process. Closing channel."; |
| + delete this; |
| + return; |
| + } |
| + uint32_t response_size = count * sizeof(uint64_t); |
| + write_data_.resize(response_size); |
| + uint64_t* tokens = reinterpret_cast<uint64_t*>(&write_data_[0]); |
| + std::vector<PlatformHandle> duplicated_handles(count); |
| + for (uint32_t i = 0; i < count; ++i) { |
| + duplicated_handles[i] = |
| + PlatformHandle(DuplicateFromChild(message->handles[i])); |
| + } |
| + ParentTokenSerializerState::GetInstance()->HandleToToken( |
| + &duplicated_handles[0], count, tokens); |
| + } else if (message->id == TOKEN_TO_HANDLE) { |
| + uint32_t count = |
| + (message->size - kTokenSerializerMessageHeaderSize) / |
| + sizeof(uint64_t); |
| + if (count > GetConfiguration().max_message_num_handles) { |
| + NOTREACHED() << "Too many tokens from child process. Closing channel."; |
| + delete this; |
| + return; |
| + } |
| + uint32_t response_size = count * sizeof(HANDLE); |
| + write_data_.resize(response_size); |
| + HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]); |
| + std::vector<PlatformHandle> temp_handles(count); |
| + ParentTokenSerializerState::GetInstance()->TokenToHandle( |
| + &message->tokens[0], count, &temp_handles[0]); |
| + for (uint32_t i = 0; i < count; ++i) { |
| + if (temp_handles[i].is_valid()) { |
| + handles[i] = DuplicateToChild(temp_handles[i].handle); |
| + } else { |
| + NOTREACHED() << "Unknown token"; |
| + handles[i] = INVALID_HANDLE_VALUE; |
| + } |
| + } |
| + } else { |
| + NOTREACHED() << "Unknown command. Stopping reading."; |
| + delete this; |
| + return; |
| + } |
| + |
| + BOOL rv = WriteFile(pipe_.get().handle, &write_data_[0], |
|
yzshen1
2015/11/20 20:39:55
I think it is not guaranteed that the write could
jam
2015/11/21 01:26:09
since this side uses overlapped IO (as opposed to
|
| + static_cast<int>(write_data_.size()), NULL, |
| + &write_context_.overlapped); |
| + DCHECK(rv); |
| + |
| + // Start reading again. |
| + num_bytes_read_ = 0; |
| + BeginRead(); |
| +} |
| + |
| + |
| +HANDLE ParentTokenSerializer::DuplicateToChild(HANDLE handle) { |
| + HANDLE rv = INVALID_HANDLE_VALUE; |
| + BOOL result = DuplicateHandle(base::GetCurrentProcessHandle(), handle, |
| + child_process_, &rv, 0, FALSE, |
| + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
| + DCHECK(result); |
| + return rv; |
| +} |
| + |
| +HANDLE ParentTokenSerializer::DuplicateFromChild(HANDLE handle) { |
| + HANDLE rv = INVALID_HANDLE_VALUE; |
| + BOOL result = DuplicateHandle(child_process_, handle, |
| + base::GetCurrentProcessHandle(), &rv, 0, FALSE, |
| + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
| + DCHECK(result); |
| + return rv; |
| +} |
| + |
| +} // namespace edk |
| +} // namespace mojo |