diff options
Diffstat (limited to 'chromium/mojo/embedder/platform_channel_pair_win.cc')
-rw-r--r-- | chromium/mojo/embedder/platform_channel_pair_win.cc | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/chromium/mojo/embedder/platform_channel_pair_win.cc b/chromium/mojo/embedder/platform_channel_pair_win.cc new file mode 100644 index 00000000000..f3eee9277b3 --- /dev/null +++ b/chromium/mojo/embedder/platform_channel_pair_win.cc @@ -0,0 +1,117 @@ +// Copyright 2014 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/embedder/platform_channel_pair.h" + +#include <windows.h> + +#include <string> + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/win/windows_version.h" +#include "mojo/embedder/platform_handle.h" + +namespace mojo { +namespace embedder { + +namespace { + +std::wstring GeneratePipeName() { + return base::StringPrintf( + L"\\\\.\\pipe\\mojo.%u.%u.%I64u", + GetCurrentProcessId(), GetCurrentThreadId(), base::RandUint64()); +} + +} // namespace + +PlatformChannelPair::PlatformChannelPair() { + std::wstring pipe_name = GeneratePipeName(); + + const DWORD kOpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | + FILE_FLAG_FIRST_PIPE_INSTANCE; + const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE; + server_handle_.reset(PlatformHandle( + CreateNamedPipeW(pipe_name.c_str(), + kOpenMode, + kPipeMode, + 1, // Max instances. + 4096, // Out buffer size. + 4096, // In buffer size. + 5000, // Timeout in milliseconds. + NULL))); // Default security descriptor. + PCHECK(server_handle_.is_valid()); + + const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; + // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate + // the client. + const DWORD kFlags = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | + FILE_FLAG_OVERLAPPED; + // Allow the handle to be inherited by child processes. + SECURITY_ATTRIBUTES security_attributes = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE + }; + client_handle_.reset(PlatformHandle( + CreateFileW(pipe_name.c_str(), + kDesiredAccess, + 0, // No sharing. + &security_attributes, + OPEN_EXISTING, + kFlags, + NULL))); // No template file. + PCHECK(client_handle_.is_valid()); + + // Since a client has connected, ConnectNamedPipe() should return zero and + // GetLastError() should return ERROR_PIPE_CONNECTED. + CHECK(!ConnectNamedPipe(server_handle_.get().handle, NULL)); + PCHECK(GetLastError() == ERROR_PIPE_CONNECTED); +} + +// static +ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( + const base::CommandLine& command_line) { + std::string client_handle_string = + command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); + + int client_handle_value = 0; + if (client_handle_string.empty() || + !base::StringToInt(client_handle_string, &client_handle_value)) { + LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; + return ScopedPlatformHandle(); + } + + return ScopedPlatformHandle( + PlatformHandle(LongToHandle(client_handle_value))); +} + +void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( + base::CommandLine* command_line, + base::HandlesToInheritVector* handle_passing_info) const { + DCHECK(command_line); + DCHECK(handle_passing_info); + DCHECK(client_handle_.is_valid()); + + CHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA); + + handle_passing_info->push_back(client_handle_.get().handle); + + // Log a warning if the command line already has the switch, but "clobber" it + // anyway, since it's reasonably likely that all the switches were just copied + // from the parent. + LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) + << "Child command line already has switch --" + << kMojoPlatformChannelHandleSwitch << "=" + << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); + // (Any existing switch won't actually be removed from the command line, but + // the last one appended takes precedence.) + command_line->AppendSwitchASCII( + kMojoPlatformChannelHandleSwitch, + base::IntToString(HandleToLong(client_handle_.get().handle))); +} + +} // namespace embedder +} // namespace mojo |