blob: 0d52529a9fba9ca72b488aebbec08e91381f4f8b [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/system/platform_handle_dispatcher.h"
#include <algorithm>
#include <utility>
#include "base/logging.h"
using mojo::platform::ScopedPlatformHandle;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
const size_t kInvalidPlatformHandleIndex = static_cast<size_t>(-1);
struct SerializedPlatformHandleDispatcher {
size_t platform_handle_index; // (Or |kInvalidPlatformHandleIndex|.)
};
} // namespace
// static
constexpr MojoHandleRights PlatformHandleDispatcher::kDefaultHandleRights;
ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() {
MutexLocker locker(&mutex());
return platform_handle_.Pass();
}
Dispatcher::Type PlatformHandleDispatcher::GetType() const {
return Type::PLATFORM_HANDLE;
}
bool PlatformHandleDispatcher::SupportsEntrypointClass(
EntrypointClass entrypoint_class) const {
return false;
}
// static
RefPtr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
Channel* channel,
const void* source,
size_t size,
std::vector<ScopedPlatformHandle>* platform_handles) {
if (size != sizeof(SerializedPlatformHandleDispatcher)) {
LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)";
return nullptr;
}
const SerializedPlatformHandleDispatcher* serialization =
static_cast<const SerializedPlatformHandleDispatcher*>(source);
size_t platform_handle_index = serialization->platform_handle_index;
// Starts off invalid, which is what we want.
ScopedPlatformHandle platform_handle;
if (platform_handle_index != kInvalidPlatformHandleIndex) {
if (!platform_handles ||
platform_handle_index >= platform_handles->size()) {
LOG(ERROR)
<< "Invalid serialized platform handle dispatcher (missing handles)";
return nullptr;
}
// We take ownership of the handle, so we have to invalidate the one in
// |platform_handles|.
std::swap(platform_handle, (*platform_handles)[platform_handle_index]);
}
return Create(std::move(platform_handle));
}
PlatformHandleDispatcher::PlatformHandleDispatcher(
ScopedPlatformHandle platform_handle)
: platform_handle_(platform_handle.Pass()) {}
PlatformHandleDispatcher::~PlatformHandleDispatcher() {}
void PlatformHandleDispatcher::CloseImplNoLock() {
mutex().AssertHeld();
platform_handle_.reset();
}
RefPtr<Dispatcher>
PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
MessagePipe* /*message_pipe*/,
unsigned /*port*/) {
mutex().AssertHeld();
CancelAllAwakablesNoLock();
return Create(platform_handle_.Pass());
}
void PlatformHandleDispatcher::StartSerializeImplNoLock(
Channel* /*channel*/,
size_t* max_size,
size_t* max_platform_handles) {
AssertHasOneRef(); // Only one ref => no need to take the lock.
*max_size = sizeof(SerializedPlatformHandleDispatcher);
*max_platform_handles = 1;
}
bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock(
Channel* /*channel*/,
void* destination,
size_t* actual_size,
std::vector<ScopedPlatformHandle>* platform_handles) {
AssertHasOneRef(); // Only one ref => no need to take the lock.
SerializedPlatformHandleDispatcher* serialization =
static_cast<SerializedPlatformHandleDispatcher*>(destination);
if (platform_handle_.is_valid()) {
serialization->platform_handle_index = platform_handles->size();
platform_handles->push_back(std::move(platform_handle_));
} else {
serialization->platform_handle_index = kInvalidPlatformHandleIndex;
}
*actual_size = sizeof(SerializedPlatformHandleDispatcher);
return true;
}
} // namespace system
} // namespace mojo