blob: e0f31b900aa46ab647caba391125b1a91c76e0b7 [file] [log] [blame]
// 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/edk/embedder/platform_channel_pair.h"
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "mojo/edk/embedder/platform_handle.h"
namespace mojo {
namespace edk {
namespace {
std::string PrepareToPassHandleToChildProcessAsString(
const PlatformHandle& handle,
HandlePassingInformation* handle_passing_info) {
DCHECK(handle.is_valid());
const uint32_t id = PA_HND(PA_USER0, 0);
handle_passing_info->push_back({id, handle.as_handle()});
return base::UintToString(id);
}
} // namespace
PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) {
zx_handle_t handles[2] = {};
zx_status_t result = zx_channel_create(0, &handles[0], &handles[1]);
CHECK_EQ(ZX_OK, result);
server_handle_.reset(PlatformHandle::ForHandle(handles[0]));
DCHECK(server_handle_.is_valid());
client_handle_.reset(PlatformHandle::ForHandle(handles[1]));
DCHECK(client_handle_.is_valid());
}
// static
ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess(
const base::CommandLine& command_line) {
std::string handle_string =
command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
return PassClientHandleFromParentProcessFromString(handle_string);
}
ScopedPlatformHandle
PlatformChannelPair::PassClientHandleFromParentProcessFromString(
const std::string& value) {
unsigned int id = 0;
if (value.empty() || !base::StringToUint(value, &id)) {
LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
return ScopedPlatformHandle();
}
return ScopedPlatformHandle(PlatformHandle::ForHandle(
zx_get_startup_handle(base::checked_cast<uint32_t>(id))));
}
void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
base::CommandLine* command_line,
HandlePassingInformation* handle_passing_info) const {
return PrepareToPassHandleToChildProcess(client_handle_.get(), command_line,
handle_passing_info);
}
// static
void PlatformChannelPair::PrepareToPassHandleToChildProcess(
const PlatformHandle& handle,
base::CommandLine* command_line,
HandlePassingInformation* handle_passing_info) {
DCHECK(command_line);
// 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,
PrepareToPassHandleToChildProcessAsString(handle, handle_passing_info));
}
} // namespace edk
} // namespace mojo