1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file.
4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/system/shared_buffer_dispatcher.h"
6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <limits>
8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/logging.h"
10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/scoped_ptr.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/embedder/platform_support.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/c/system/macros.h"
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "mojo/system/channel.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/system/constants.h"
15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/system/memory.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/system/options_validation.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace mojo {
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace system {
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct SerializedSharedBufferDispatcher {
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t num_bytes;
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t platform_handle_index;
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const MojoCreateSharedBufferOptions
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SharedBufferDispatcher::kDefaultCreateOptions = {
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)MojoResult SharedBufferDispatcher::ValidateCreateOptions(
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UserPointer<const MojoCreateSharedBufferOptions> in_options,
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MojoCreateSharedBufferOptions* out_options) {
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const MojoCreateSharedBufferOptionsFlags kKnownFlags =
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *out_options = kDefaultCreateOptions;
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (in_options.IsNull())
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_OK;
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UserOptionsReader<MojoCreateSharedBufferOptions> reader(in_options);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!reader.is_valid())
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_INVALID_ARGUMENT;
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateSharedBufferOptions, flags, reader))
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_OK;
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((reader.options().flags & ~kKnownFlags))
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_UNIMPLEMENTED;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  out_options->flags = reader.options().flags;
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Checks for fields beyond |flags|:
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // (Nothing here yet.)
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return MOJO_RESULT_OK;
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
65effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochMojoResult SharedBufferDispatcher::Create(
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    embedder::PlatformSupport* platform_support,
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const MojoCreateSharedBufferOptions& /*validated_options*/,
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    uint64_t num_bytes,
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_refptr<SharedBufferDispatcher>* result) {
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!num_bytes)
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_INVALID_ARGUMENT;
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (num_bytes > kMaxSharedMemoryNumBytes)
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_RESOURCE_EXHAUSTED;
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes)));
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!shared_buffer.get())
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_RESOURCE_EXHAUSTED;
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  *result = new SharedBufferDispatcher(shared_buffer);
81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return MOJO_RESULT_OK;
82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
84effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDispatcher::Type SharedBufferDispatcher::GetType() const {
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return kTypeSharedBuffer;
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Channel* channel,
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const void* source,
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t size,
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    embedder::PlatformHandleVector* platform_handles) {
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(channel);
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (size != sizeof(SerializedSharedBufferDispatcher)) {
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_refptr<SharedBufferDispatcher>();
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const SerializedSharedBufferDispatcher* serialization =
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<const SerializedSharedBufferDispatcher*>(source);
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t num_bytes = serialization->num_bytes;
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t platform_handle_index = serialization->platform_handle_index;
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!num_bytes) {
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        << "Invalid serialized shared buffer dispatcher (invalid num_bytes)";
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_refptr<SharedBufferDispatcher>();
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!platform_handles || platform_handle_index >= platform_handles->size()) {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        << "Invalid serialized shared buffer dispatcher (missing handles)";
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_refptr<SharedBufferDispatcher>();
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Starts off invalid, which is what we want.
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  embedder::PlatformHandle platform_handle;
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We take ownership of the handle, so we have to invalidate the one in
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |platform_handles|.
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::swap(platform_handle, (*platform_handles)[platform_handle_index]);
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // closed even if creation fails.
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      channel->platform_support()->CreateSharedBufferFromHandle(
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          num_bytes, embedder::ScopedPlatformHandle(platform_handle)));
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!shared_buffer.get()) {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)";
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_refptr<SharedBufferDispatcher>();
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return scoped_refptr<SharedBufferDispatcher>(
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new SharedBufferDispatcher(shared_buffer));
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
139effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSharedBufferDispatcher::SharedBufferDispatcher(
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer)
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : shared_buffer_(shared_buffer) {
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(shared_buffer_.get());
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
145effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSharedBufferDispatcher::~SharedBufferDispatcher() {
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UserPointer<const MojoDuplicateBufferHandleOptions> in_options,
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    MojoDuplicateBufferHandleOptions* out_options) {
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  static const MojoDuplicateBufferHandleOptions kDefaultOptions = {
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)),
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  *out_options = kDefaultOptions;
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (in_options.IsNull())
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return MOJO_RESULT_OK;
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options);
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!reader.is_valid())
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_INVALID_ARGUMENT;
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!OPTIONS_STRUCT_HAS_MEMBER(
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          MojoDuplicateBufferHandleOptions, flags, reader))
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_OK;
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((reader.options().flags & ~kKnownFlags))
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return MOJO_RESULT_UNIMPLEMENTED;
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  out_options->flags = reader.options().flags;
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Checks for fields beyond |flags|:
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // (Nothing here yet.)
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return MOJO_RESULT_OK;
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid SharedBufferDispatcher::CloseImplNoLock() {
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  lock().AssertAcquired();
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(shared_buffer_.get());
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  shared_buffer_ = nullptr;
184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_refptr<Dispatcher>
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  lock().AssertAcquired();
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(shared_buffer_.get());
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer;
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  shared_buffer.swap(shared_buffer_);
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer));
193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
195effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochMojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UserPointer<const MojoDuplicateBufferHandleOptions> options,
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_refptr<Dispatcher>* new_dispatcher) {
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  lock().AssertAcquired();
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MojoDuplicateBufferHandleOptions validated_options;
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MojoResult result = ValidateDuplicateOptions(options, &validated_options);
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (result != MOJO_RESULT_OK)
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return result;
204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  *new_dispatcher = new SharedBufferDispatcher(shared_buffer_);
206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return MOJO_RESULT_OK;
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
209effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochMojoResult SharedBufferDispatcher::MapBufferImplNoLock(
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    uint64_t offset,
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    uint64_t num_bytes,
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    MojoMapBufferFlags flags,
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  lock().AssertAcquired();
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(shared_buffer_.get());
216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_INVALID_ARGUMENT;
219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_INVALID_ARGUMENT;
221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset),
223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  static_cast<size_t>(num_bytes)))
224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_INVALID_ARGUMENT;
225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(mapping);
227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        static_cast<size_t>(num_bytes));
229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!*mapping)
230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return MOJO_RESULT_RESOURCE_EXHAUSTED;
231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return MOJO_RESULT_OK;
233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SharedBufferDispatcher::StartSerializeImplNoLock(
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Channel* /*channel*/,
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t* max_size,
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t* max_platform_handles) {
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *max_size = sizeof(SerializedSharedBufferDispatcher);
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *max_platform_handles = 1;
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock(
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Channel* /*channel*/,
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void* destination,
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t* actual_size,
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    embedder::PlatformHandleVector* platform_handles) {
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(HasOneRef());  // Only one ref => no need to take the lock.
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(shared_buffer_.get());
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SerializedSharedBufferDispatcher* serialization =
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<SerializedSharedBufferDispatcher*>(destination);
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If there's only one reference to |shared_buffer_|, then it's ours (and no
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // one else can make any more references to it), so we can just take its
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // handle.
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  embedder::ScopedPlatformHandle platform_handle(
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle()
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  : shared_buffer_->DuplicatePlatformHandle());
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!platform_handle.is_valid()) {
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    shared_buffer_ = nullptr;
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  serialization->num_bytes = shared_buffer_->GetNumBytes();
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  serialization->platform_handle_index = platform_handles->size();
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  platform_handles->push_back(platform_handle.release());
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *actual_size = sizeof(SerializedSharedBufferDispatcher);
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  shared_buffer_ = nullptr;
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}  // namespace system
276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}  // namespace mojo
277