mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This updates to mojo 4e4d51ce28a and mojo sdk 711a0bcfb141b4 and updates the sky package's pubspec.yaml dependency to '>=0.1.0 <0.2.0' to be compatible with the current mojo package. This includes an update to the Mojo Dart generator to produce real classes for enums and the corresponding updates for users of the KeyboardType enum in Sky as well as one scoped_ptr->std::unique_ptr in shell corresponding to a change in the Mojo EDK. When a new version of the sky and sky_services package are pushed this will fix domokit/mojo#440.
274 lines
8.7 KiB
C++
274 lines
8.7 KiB
C++
// 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/shared_buffer_dispatcher.h"
|
|
|
|
#include <limits>
|
|
|
|
#include "base/logging.h"
|
|
#include "mojo/edk/embedder/platform_support.h"
|
|
#include "mojo/edk/system/channel.h"
|
|
#include "mojo/edk/system/configuration.h"
|
|
#include "mojo/edk/system/memory.h"
|
|
#include "mojo/edk/system/options_validation.h"
|
|
#include "mojo/public/c/system/macros.h"
|
|
|
|
namespace mojo {
|
|
namespace system {
|
|
|
|
namespace {
|
|
|
|
struct SerializedSharedBufferDispatcher {
|
|
size_t num_bytes;
|
|
size_t platform_handle_index;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// static
|
|
const MojoCreateSharedBufferOptions
|
|
SharedBufferDispatcher::kDefaultCreateOptions = {
|
|
static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
|
|
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
|
|
|
|
// static
|
|
MojoResult SharedBufferDispatcher::ValidateCreateOptions(
|
|
UserPointer<const MojoCreateSharedBufferOptions> in_options,
|
|
MojoCreateSharedBufferOptions* out_options) {
|
|
const MojoCreateSharedBufferOptionsFlags kKnownFlags =
|
|
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
|
|
|
|
*out_options = kDefaultCreateOptions;
|
|
if (in_options.IsNull())
|
|
return MOJO_RESULT_OK;
|
|
|
|
UserOptionsReader<MojoCreateSharedBufferOptions> reader(in_options);
|
|
if (!reader.is_valid())
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
|
|
if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateSharedBufferOptions, flags, reader))
|
|
return MOJO_RESULT_OK;
|
|
if ((reader.options().flags & ~kKnownFlags))
|
|
return MOJO_RESULT_UNIMPLEMENTED;
|
|
out_options->flags = reader.options().flags;
|
|
|
|
// Checks for fields beyond |flags|:
|
|
|
|
// (Nothing here yet.)
|
|
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
// static
|
|
MojoResult SharedBufferDispatcher::Create(
|
|
embedder::PlatformSupport* platform_support,
|
|
const MojoCreateSharedBufferOptions& /*validated_options*/,
|
|
uint64_t num_bytes,
|
|
scoped_refptr<SharedBufferDispatcher>* result) {
|
|
if (!num_bytes)
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
if (num_bytes > GetConfiguration().max_shared_memory_num_bytes)
|
|
return MOJO_RESULT_RESOURCE_EXHAUSTED;
|
|
|
|
scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
|
|
platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes)));
|
|
if (!shared_buffer)
|
|
return MOJO_RESULT_RESOURCE_EXHAUSTED;
|
|
|
|
*result = CreateInternal(shared_buffer.Pass());
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
Dispatcher::Type SharedBufferDispatcher::GetType() const {
|
|
return Type::SHARED_BUFFER;
|
|
}
|
|
|
|
// static
|
|
scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
|
|
Channel* channel,
|
|
const void* source,
|
|
size_t size,
|
|
embedder::PlatformHandleVector* platform_handles) {
|
|
DCHECK(channel);
|
|
|
|
if (size != sizeof(SerializedSharedBufferDispatcher)) {
|
|
LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
|
|
return nullptr;
|
|
}
|
|
|
|
const SerializedSharedBufferDispatcher* serialization =
|
|
static_cast<const SerializedSharedBufferDispatcher*>(source);
|
|
size_t num_bytes = serialization->num_bytes;
|
|
size_t platform_handle_index = serialization->platform_handle_index;
|
|
|
|
if (!num_bytes) {
|
|
LOG(ERROR)
|
|
<< "Invalid serialized shared buffer dispatcher (invalid num_bytes)";
|
|
return nullptr;
|
|
}
|
|
|
|
if (!platform_handles || platform_handle_index >= platform_handles->size()) {
|
|
LOG(ERROR)
|
|
<< "Invalid serialized shared buffer dispatcher (missing handles)";
|
|
return nullptr;
|
|
}
|
|
|
|
// Starts off invalid, which is what we want.
|
|
embedder::PlatformHandle platform_handle;
|
|
// 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]);
|
|
|
|
// Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be
|
|
// closed even if creation fails.
|
|
scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
|
|
channel->platform_support()->CreateSharedBufferFromHandle(
|
|
num_bytes, embedder::ScopedPlatformHandle(platform_handle)));
|
|
if (!shared_buffer) {
|
|
LOG(ERROR)
|
|
<< "Invalid serialized shared buffer dispatcher (invalid num_bytes?)";
|
|
return nullptr;
|
|
}
|
|
|
|
return CreateInternal(shared_buffer.Pass());
|
|
}
|
|
|
|
SharedBufferDispatcher::SharedBufferDispatcher(
|
|
scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer)
|
|
: shared_buffer_(shared_buffer) {
|
|
DCHECK(shared_buffer_);
|
|
}
|
|
|
|
SharedBufferDispatcher::~SharedBufferDispatcher() {
|
|
}
|
|
|
|
// static
|
|
MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
|
|
UserPointer<const MojoDuplicateBufferHandleOptions> in_options,
|
|
MojoDuplicateBufferHandleOptions* out_options) {
|
|
const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
|
|
MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
|
|
static const MojoDuplicateBufferHandleOptions kDefaultOptions = {
|
|
static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)),
|
|
MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
|
|
|
|
*out_options = kDefaultOptions;
|
|
if (in_options.IsNull())
|
|
return MOJO_RESULT_OK;
|
|
|
|
UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options);
|
|
if (!reader.is_valid())
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
|
|
if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags,
|
|
reader))
|
|
return MOJO_RESULT_OK;
|
|
if ((reader.options().flags & ~kKnownFlags))
|
|
return MOJO_RESULT_UNIMPLEMENTED;
|
|
out_options->flags = reader.options().flags;
|
|
|
|
// Checks for fields beyond |flags|:
|
|
|
|
// (Nothing here yet.)
|
|
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
void SharedBufferDispatcher::CloseImplNoLock() {
|
|
mutex().AssertHeld();
|
|
DCHECK(shared_buffer_);
|
|
shared_buffer_ = nullptr;
|
|
}
|
|
|
|
scoped_refptr<Dispatcher>
|
|
SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
|
|
mutex().AssertHeld();
|
|
DCHECK(shared_buffer_);
|
|
return CreateInternal(shared_buffer_.Pass());
|
|
}
|
|
|
|
MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
|
|
UserPointer<const MojoDuplicateBufferHandleOptions> options,
|
|
scoped_refptr<Dispatcher>* new_dispatcher) {
|
|
mutex().AssertHeld();
|
|
|
|
MojoDuplicateBufferHandleOptions validated_options;
|
|
MojoResult result = ValidateDuplicateOptions(options, &validated_options);
|
|
if (result != MOJO_RESULT_OK)
|
|
return result;
|
|
|
|
// Note: Since this is "duplicate", we keep our ref to |shared_buffer_|.
|
|
*new_dispatcher = CreateInternal(shared_buffer_);
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
MojoResult SharedBufferDispatcher::MapBufferImplNoLock(
|
|
uint64_t offset,
|
|
uint64_t num_bytes,
|
|
MojoMapBufferFlags flags,
|
|
std::unique_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
|
|
mutex().AssertHeld();
|
|
DCHECK(shared_buffer_);
|
|
|
|
if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
|
|
if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset),
|
|
static_cast<size_t>(num_bytes)))
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
|
|
DCHECK(mapping);
|
|
*mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
|
|
static_cast<size_t>(num_bytes));
|
|
if (!*mapping)
|
|
return MOJO_RESULT_RESOURCE_EXHAUSTED;
|
|
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
void SharedBufferDispatcher::StartSerializeImplNoLock(
|
|
Channel* /*channel*/,
|
|
size_t* max_size,
|
|
size_t* max_platform_handles) {
|
|
DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
|
|
*max_size = sizeof(SerializedSharedBufferDispatcher);
|
|
*max_platform_handles = 1;
|
|
}
|
|
|
|
bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock(
|
|
Channel* /*channel*/,
|
|
void* destination,
|
|
size_t* actual_size,
|
|
embedder::PlatformHandleVector* platform_handles) {
|
|
DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
|
|
DCHECK(shared_buffer_);
|
|
|
|
SerializedSharedBufferDispatcher* serialization =
|
|
static_cast<SerializedSharedBufferDispatcher*>(destination);
|
|
// If there's only one reference to |shared_buffer_|, then it's ours (and no
|
|
// one else can make any more references to it), so we can just take its
|
|
// handle.
|
|
embedder::ScopedPlatformHandle platform_handle(
|
|
shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle()
|
|
: shared_buffer_->DuplicatePlatformHandle());
|
|
if (!platform_handle.is_valid()) {
|
|
shared_buffer_ = nullptr;
|
|
return false;
|
|
}
|
|
|
|
serialization->num_bytes = shared_buffer_->GetNumBytes();
|
|
serialization->platform_handle_index = platform_handles->size();
|
|
platform_handles->push_back(platform_handle.release());
|
|
*actual_size = sizeof(SerializedSharedBufferDispatcher);
|
|
|
|
shared_buffer_ = nullptr;
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace system
|
|
} // namespace mojo
|