Added PlatformHandle thunks. Added thunks for exchanging PlatformHandles (file descriptors) between mojo services as MojoHandles. Basically a port of https://codereview.chromium.org/1113393002 plus some testing code. This is intended to be used to allow cross-process sharing of GPU buffers Change-Id: I5c77f0ed0381c0b03ce0280314f7fbef3551d895 BUG= R=viettrungluu@chromium.org Review URL: https://codereview.chromium.org/1578423002 .
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn index 1909cb3..16fdbba 100644 --- a/mojo/BUILD.gn +++ b/mojo/BUILD.gn
@@ -67,6 +67,7 @@ "//mojo/file_utils:file_utils_apptests", "//mojo/gles2:mgl_unittests", "//mojo/public/cpp/bindings/tests:versioning_apptests", + "//mojo/public/platform/native:tests", "//mojo/services/files/c:apptests", "//mojo/services/files/cpp:files_impl_apptests", "//mojo/services/log/cpp:log_client_apptests",
diff --git a/mojo/public/platform/native/BUILD.gn b/mojo/public/platform/native/BUILD.gn index e9c6034..e88ac01 100644 --- a/mojo/public/platform/native/BUILD.gn +++ b/mojo/public/platform/native/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("../../mojo_sdk.gni") +import("../../mojo_application.gni") mojo_sdk_source_set("system") { sources = [ @@ -125,3 +126,51 @@ mojo_sdk_deps = [ "mojo/public/c/gpu:MGL_onscreen" ] } + +mojo_sdk_source_set("platform_handle") { + sources = [ + "platform_handle_private_thunks.c", + "platform_handle_private_thunks.h", + ] + + mojo_sdk_deps = [ + "mojo/public/platform/native:platform_handle_api", + "mojo/public/c/system", + ] +} + +# Only targets that are calling the thunks should depend upon this. +mojo_sdk_source_set("platform_handle_api") { + sources = [ + "platform_handle_private.h", + ] + mojo_sdk_deps = [ "mojo/public/c/system:system" ] +} + +mojo_native_application("platform_handle_private_apptest") { + output_name = "platform_handle_private_apptests" + + testonly = true + + sources = [ + "platform_handle_private_apptest.cc", + ] + + deps = [ + ":platform_handle", + ":platform_handle_api", + "../../cpp/application:standalone", + "../../cpp/application:test_support_standalone", + "../../cpp/environment", + "../../cpp/system", + ] +} + +group("tests") { + testonly = true + + deps = [ + ":platform_handle_private_apptest", + ":system_impl_private_tests", + ] +}
diff --git a/mojo/public/platform/native/platform_handle_private.h b/mojo/public/platform/native/platform_handle_private.h new file mode 100644 index 0000000..e81d572 --- /dev/null +++ b/mojo/public/platform/native/platform_handle_private.h
@@ -0,0 +1,35 @@ +// Copyright 2016 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. + +#ifndef MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_H_ +#define MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_H_ + +#include "mojo/public/c/system/types.h" + +typedef int MojoPlatformHandle; // Unix file descriptor + +#ifdef __cplusplus +extern "C" { +#endif + +// Wraps |platform_handle| in a MojoHandle so that it can transported. Returns +// MOJO_RESULT_OK on success, all other results indicate failure. This takes +// ownership of |platform_handle|, regardless of whether this succeeds. +MojoResult MojoCreatePlatformHandleWrapper(MojoPlatformHandle platform_handle, + MojoHandle* wrapper); + +// Extracts |platform_handle| from |wrapper|. Returns MOJO_RESULT_OK on success, +// all other results indicate failure. If this succeeds, it causes |wrapper| to +// relinquish ownership of |platform_handle|, so MojoClose'ing |wrapper| will no +// longer close the underlying |platform_handle|. Never the less, it is still +// neccessary to MojoClose |wrapper|, but this will not affect the underlying +// descriptor after this call. +MojoResult MojoExtractPlatformHandle(MojoHandle wrapper, + MojoPlatformHandle* platform_handle); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_H_
diff --git a/mojo/public/platform/native/platform_handle_private_apptest.cc b/mojo/public/platform/native/platform_handle_private_apptest.cc new file mode 100644 index 0000000..28e1b47 --- /dev/null +++ b/mojo/public/platform/native/platform_handle_private_apptest.cc
@@ -0,0 +1,66 @@ +// Copyright 2016 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/public/platform/native/platform_handle_private.h" + +#include <stdint.h> +#include <sys/types.h> +#include <unistd.h> + +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/application_test_base.h" +#include "mojo/public/cpp/environment/logging.h" +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { +namespace { + +class PlatformHandlePrivateApplicationTest : public test::ApplicationTestBase { + public: + PlatformHandlePrivateApplicationTest() : ApplicationTestBase() {} + ~PlatformHandlePrivateApplicationTest() override {} + + private: + MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformHandlePrivateApplicationTest); +}; + +TEST_F(PlatformHandlePrivateApplicationTest, WrapAndUnwrapFileDescriptor) { + MojoPlatformHandle original_handle = -1; + MojoPlatformHandle unwrapped_handle = -1; + MojoHandle wrapper = MOJO_HANDLE_INVALID; + + int pipe_fds[2] = {-1, -1}; + + uint64_t write_buffer = 0xDEADBEEF; + uint64_t read_buffer = 0; + + ASSERT_EQ(0, pipe(pipe_fds)); + + // Pass second FD through wrapper. + original_handle = pipe_fds[1]; + + EXPECT_EQ(MOJO_RESULT_OK, + MojoCreatePlatformHandleWrapper(original_handle, &wrapper)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoExtractPlatformHandle(wrapper, &unwrapped_handle)); + + // Write to wrapped/unwrapped FD. + ssize_t bytes_written = + write(unwrapped_handle, &write_buffer, sizeof(write_buffer)); + ASSERT_EQ(sizeof(write_buffer), static_cast<size_t>(bytes_written)); + + // Read from other end of pipe. + ssize_t bytes_read = read(pipe_fds[0], &read_buffer, sizeof(read_buffer)); + ASSERT_EQ(sizeof(read_buffer), static_cast<size_t>(bytes_read)); + + EXPECT_EQ(bytes_read, bytes_written); + EXPECT_EQ(write_buffer, read_buffer); + + EXPECT_EQ(0, close(pipe_fds[0])); + EXPECT_EQ(0, close(unwrapped_handle)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(wrapper)); +} + +} // namespace +} // namespace mojo
diff --git a/mojo/public/platform/native/platform_handle_private_thunks.c b/mojo/public/platform/native/platform_handle_private_thunks.c new file mode 100644 index 0000000..9c0b35b --- /dev/null +++ b/mojo/public/platform/native/platform_handle_private_thunks.c
@@ -0,0 +1,30 @@ +// Copyright 2016 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/public/platform/native/platform_handle_private_thunks.h" + +#include "mojo/public/platform/native/thunk_export.h" + +#include <assert.h> + +static struct MojoPlatformHandlePrivateThunks g_thunks = {0}; + +MojoResult MojoCreatePlatformHandleWrapper(MojoPlatformHandle platform_handle, + MojoHandle* wrapper) { + assert(g_thunks.CreatePlatformHandleWrapper); + return g_thunks.CreatePlatformHandleWrapper(platform_handle, wrapper); +} + +MojoResult MojoExtractPlatformHandle(MojoHandle wrapper, + MojoPlatformHandle* platform_handle) { + assert(g_thunks.ExtractPlatformHandle); + return g_thunks.ExtractPlatformHandle(wrapper, platform_handle); +} + +THUNK_EXPORT size_t MojoSetPlatformHandlePrivateThunks( + const struct MojoPlatformHandlePrivateThunks* thunks) { + if (thunks->size >= sizeof(g_thunks)) + g_thunks = *thunks; + return sizeof(g_thunks); +} \ No newline at end of file
diff --git a/mojo/public/platform/native/platform_handle_private_thunks.h b/mojo/public/platform/native/platform_handle_private_thunks.h new file mode 100644 index 0000000..0a19b0d --- /dev/null +++ b/mojo/public/platform/native/platform_handle_private_thunks.h
@@ -0,0 +1,33 @@ +// Copyright 2016 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. + +#ifndef MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_THUNKS_H_ +#define MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_THUNKS_H_ + +#include <stddef.h> + +#include "mojo/public/platform/native/platform_handle_private.h" + +#pragma pack(push, 8) +struct MojoPlatformHandlePrivateThunks { + size_t size; // Should be set to sizeof(PlatformHandleThunks). + MojoResult (*CreatePlatformHandleWrapper)(MojoPlatformHandle, MojoHandle*); + MojoResult (*ExtractPlatformHandle)(MojoHandle, MojoPlatformHandle*); +}; +#pragma pack(pop) + +#ifdef __cplusplus +inline struct MojoPlatformHandlePrivateThunks +MojoMakePlatformHandlePrivateThunks() { + struct MojoPlatformHandlePrivateThunks system_thunks = { + sizeof(struct MojoPlatformHandlePrivateThunks), + MojoCreatePlatformHandleWrapper, MojoExtractPlatformHandle}; + return system_thunks; +} +#endif // __cplusplus + +typedef size_t (*MojoSetPlatformHandlePrivateThunksFn)( + const struct MojoPlatformHandlePrivateThunks* thunks); + +#endif // MOJO_PUBLIC_PLATFORM_NATIVE_PLATFORM_HANDLE_PRIVATE_THUNKS_H_
diff --git a/shell/BUILD.gn b/shell/BUILD.gn index 3068cff..3732d0a 100644 --- a/shell/BUILD.gn +++ b/shell/BUILD.gn
@@ -269,6 +269,7 @@ sources = [ "native_application_support.cc", "native_application_support.h", + "platform_handle_impl.cc", ] public_deps = [ @@ -280,6 +281,7 @@ "//mojo/gles2:control_thunks", "//mojo/gles2:gles2", "//mojo/gles2:mgl", + "//mojo/public/platform/native:platform_handle_api", ] # This target has to include the public thunk headers, which generally
diff --git a/shell/native_application_support.cc b/shell/native_application_support.cc index ce171dc..11482fe 100644 --- a/shell/native_application_support.cc +++ b/shell/native_application_support.cc
@@ -24,6 +24,7 @@ #include "mojo/public/platform/native/mgl_onscreen_thunks.h" #include "mojo/public/platform/native/mgl_signal_sync_point_thunks.h" #include "mojo/public/platform/native/mgl_thunks.h" +#include "mojo/public/platform/native/platform_handle_private_thunks.h" #include "mojo/public/platform/native/system_impl_private_thunks.h" #include "mojo/public/platform/native/system_thunks.h" @@ -74,6 +75,10 @@ return false; } + // TODO(freiling): enforce the private nature of this API, somehow? + SetThunks(&MojoMakePlatformHandlePrivateThunks, + "MojoSetPlatformHandlePrivateThunks", app_library); + // TODO(ncbray): enforce the private nature of this API, somehow? SetThunks(&MojoMakeSystemImplControlThunksPrivate, "MojoSetSystemImplControlThunksPrivate", app_library);
diff --git a/shell/platform_handle_impl.cc b/shell/platform_handle_impl.cc new file mode 100644 index 0000000..1c1cfea --- /dev/null +++ b/shell/platform_handle_impl.cc
@@ -0,0 +1,34 @@ +// Copyright 2016 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. + +// This file contains implementations for the platform handle thunks +// (see //mojo/public/platform/native/platform_handle_private.h) + +#include "base/logging.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/public/platform/native/platform_handle_private.h" + +using mojo::platform::PlatformHandle; +using mojo::platform::ScopedPlatformHandle; + +MojoResult MojoCreatePlatformHandleWrapper(MojoPlatformHandle platform_handle, + MojoHandle* wrapper) { + PlatformHandle platform_handle_wrapper(platform_handle); + ScopedPlatformHandle scoped_platform_handle(platform_handle_wrapper); + return mojo::embedder::CreatePlatformHandleWrapper( + scoped_platform_handle.Pass(), wrapper); +} + +MojoResult MojoExtractPlatformHandle(MojoHandle wrapper, + MojoPlatformHandle* platform_handle) { + ScopedPlatformHandle scoped_platform_handle; + MojoResult result = mojo::embedder::PassWrappedPlatformHandle( + wrapper, &scoped_platform_handle); + if (result != MOJO_RESULT_OK) + return result; + + DCHECK(scoped_platform_handle.is_valid()); + *platform_handle = scoped_platform_handle.release().fd; + return MOJO_RESULT_OK; +}