summaryrefslogtreecommitdiffstats
path: root/mojo/edk
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/edk')
-rw-r--r--mojo/edk/DEPS7
-rw-r--r--mojo/edk/embedder/BUILD.gn114
-rw-r--r--mojo/edk/embedder/DEPS11
-rw-r--r--mojo/edk/embedder/README.md13
-rw-r--r--mojo/edk/embedder/channel_info_forward.h22
-rw-r--r--mojo/edk/embedder/channel_init.cc55
-rw-r--r--mojo/edk/embedder/channel_init.h60
-rw-r--r--mojo/edk/embedder/configuration.h68
-rw-r--r--mojo/edk/embedder/embedder.cc207
-rw-r--r--mojo/edk/embedder/embedder.h132
-rw-r--r--mojo/edk/embedder/embedder_internal.h53
-rw-r--r--mojo/edk/embedder/embedder_unittest.cc639
-rw-r--r--mojo/edk/embedder/entrypoints.cc155
-rw-r--r--mojo/edk/embedder/platform_channel_pair.cc32
-rw-r--r--mojo/edk/embedder/platform_channel_pair.h94
-rw-r--r--mojo/edk/embedder/platform_channel_pair_posix.cc111
-rw-r--r--mojo/edk/embedder/platform_channel_pair_posix_unittest.cc253
-rw-r--r--mojo/edk/embedder/platform_channel_pair_win.cc111
-rw-r--r--mojo/edk/embedder/platform_channel_utils_posix.cc186
-rw-r--r--mojo/edk/embedder/platform_channel_utils_posix.h76
-rw-r--r--mojo/edk/embedder/platform_handle.cc40
-rw-r--r--mojo/edk/embedder/platform_handle.h47
-rw-r--r--mojo/edk/embedder/platform_handle_utils.h33
-rw-r--r--mojo/edk/embedder/platform_handle_utils_posix.cc22
-rw-r--r--mojo/edk/embedder/platform_handle_utils_win.cc27
-rw-r--r--mojo/edk/embedder/platform_handle_vector.h35
-rw-r--r--mojo/edk/embedder/platform_shared_buffer.h102
-rw-r--r--mojo/edk/embedder/platform_support.h40
-rw-r--r--mojo/edk/embedder/scoped_platform_handle.h59
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer.cc108
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer.h101
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer_android.cc74
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer_posix.cc159
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc187
-rw-r--r--mojo/edk/embedder/simple_platform_shared_buffer_win.cc89
-rw-r--r--mojo/edk/embedder/simple_platform_support.cc25
-rw-r--r--mojo/edk/embedder/simple_platform_support.h37
-rw-r--r--mojo/edk/embedder/test_embedder.cc63
-rw-r--r--mojo/edk/embedder/test_embedder.h32
-rw-r--r--mojo/edk/js/BUILD.gn56
-rw-r--r--mojo/edk/js/DEPS5
-rw-r--r--mojo/edk/js/core.cc381
-rw-r--r--mojo/edk/js/core.h22
-rw-r--r--mojo/edk/js/drain_data.cc131
-rw-r--r--mojo/edk/js/drain_data.h64
-rw-r--r--mojo/edk/js/handle.cc83
-rw-r--r--mojo/edk/js/handle.h98
-rw-r--r--mojo/edk/js/handle_close_observer.h22
-rw-r--r--mojo/edk/js/handle_unittest.cc90
-rw-r--r--mojo/edk/js/mojo_runner_delegate.cc78
-rw-r--r--mojo/edk/js/mojo_runner_delegate.h33
-rw-r--r--mojo/edk/js/support.cc60
-rw-r--r--mojo/edk/js/support.h22
-rw-r--r--mojo/edk/js/test/BUILD.gn41
-rw-r--r--mojo/edk/js/test/hexdump.js34
-rw-r--r--mojo/edk/js/test/run_js_integration_tests.cc57
-rw-r--r--mojo/edk/js/test/run_js_tests.cc62
-rw-r--r--mojo/edk/js/tests/BUILD.gn36
-rw-r--r--mojo/edk/js/tests/connection_tests.js264
-rw-r--r--mojo/edk/js/tests/js_to_cpp.mojom53
-rw-r--r--mojo/edk/js/tests/js_to_cpp_tests.cc418
-rw-r--r--mojo/edk/js/tests/js_to_cpp_tests.js226
-rw-r--r--mojo/edk/js/tests/sample_service_tests.js171
-rw-r--r--mojo/edk/js/threading.cc47
-rw-r--r--mojo/edk/js/threading.h25
-rw-r--r--mojo/edk/js/waiting_callback.cc115
-rw-r--r--mojo/edk/js/waiting_callback.h68
-rw-r--r--mojo/edk/mojo_edk.gni95
-rw-r--r--mojo/edk/system/BUILD.gn209
-rw-r--r--mojo/edk/system/DEPS3
-rw-r--r--mojo/edk/system/async_waiter.cc23
-rw-r--r--mojo/edk/system/async_waiter.h38
-rw-r--r--mojo/edk/system/awakable.h34
-rw-r--r--mojo/edk/system/awakable_list.cc64
-rw-r--r--mojo/edk/system/awakable_list.h58
-rw-r--r--mojo/edk/system/awakable_list_unittest.cc358
-rw-r--r--mojo/edk/system/channel.cc604
-rw-r--r--mojo/edk/system/channel.h260
-rw-r--r--mojo/edk/system/channel_endpoint.cc202
-rw-r--r--mojo/edk/system/channel_endpoint.h210
-rw-r--r--mojo/edk/system/channel_endpoint_client.h63
-rw-r--r--mojo/edk/system/channel_endpoint_id.cc30
-rw-r--r--mojo/edk/system/channel_endpoint_id.h147
-rw-r--r--mojo/edk/system/channel_endpoint_id_unittest.cc155
-rw-r--r--mojo/edk/system/channel_info.cc31
-rw-r--r--mojo/edk/system/channel_info.h33
-rw-r--r--mojo/edk/system/channel_manager.cc78
-rw-r--r--mojo/edk/system/channel_manager.h83
-rw-r--r--mojo/edk/system/channel_manager_unittest.cc183
-rw-r--r--mojo/edk/system/channel_unittest.cc210
-rw-r--r--mojo/edk/system/configuration.cc26
-rw-r--r--mojo/edk/system/configuration.h31
-rw-r--r--mojo/edk/system/core.cc609
-rw-r--r--mojo/edk/system/core.h165
-rw-r--r--mojo/edk/system/core_test_base.cc380
-rw-r--r--mojo/edk/system/core_test_base.h116
-rw-r--r--mojo/edk/system/core_unittest.cc1317
-rw-r--r--mojo/edk/system/data_pipe.cc483
-rw-r--r--mojo/edk/system/data_pipe.h219
-rw-r--r--mojo/edk/system/data_pipe_consumer_dispatcher.cc135
-rw-r--r--mojo/edk/system/data_pipe_consumer_dispatcher.h64
-rw-r--r--mojo/edk/system/data_pipe_producer_dispatcher.cc108
-rw-r--r--mojo/edk/system/data_pipe_producer_dispatcher.h64
-rw-r--r--mojo/edk/system/data_pipe_unittest.cc375
-rw-r--r--mojo/edk/system/dispatcher.cc492
-rw-r--r--mojo/edk/system/dispatcher.h405
-rw-r--r--mojo/edk/system/dispatcher_unittest.cc307
-rw-r--r--mojo/edk/system/endpoint_relayer.cc70
-rw-r--r--mojo/edk/system/endpoint_relayer.h49
-rw-r--r--mojo/edk/system/handle_signals_state.h50
-rw-r--r--mojo/edk/system/handle_table.cc243
-rw-r--r--mojo/edk/system/handle_table.h144
-rw-r--r--mojo/edk/system/incoming_endpoint.cc59
-rw-r--r--mojo/edk/system/incoming_endpoint.h54
-rw-r--r--mojo/edk/system/local_data_pipe.cc350
-rw-r--r--mojo/edk/system/local_data_pipe.h89
-rw-r--r--mojo/edk/system/local_data_pipe_unittest.cc2071
-rw-r--r--mojo/edk/system/local_message_pipe_endpoint.cc183
-rw-r--r--mojo/edk/system/local_message_pipe_endpoint.h67
-rw-r--r--mojo/edk/system/mapping_table.cc48
-rw-r--r--mojo/edk/system/mapping_table.h62
-rw-r--r--mojo/edk/system/memory.cc89
-rw-r--r--mojo/edk/system/memory.h377
-rw-r--r--mojo/edk/system/memory_unittest.cc294
-rw-r--r--mojo/edk/system/message_in_transit.cc223
-rw-r--r--mojo/edk/system/message_in_transit.h265
-rw-r--r--mojo/edk/system/message_in_transit_queue.cc32
-rw-r--r--mojo/edk/system/message_in_transit_queue.h61
-rw-r--r--mojo/edk/system/message_pipe.cc384
-rw-r--r--mojo/edk/system/message_pipe.h148
-rw-r--r--mojo/edk/system/message_pipe_dispatcher.cc230
-rw-r--r--mojo/edk/system/message_pipe_dispatcher.h133
-rw-r--r--mojo/edk/system/message_pipe_dispatcher_unittest.cc691
-rw-r--r--mojo/edk/system/message_pipe_endpoint.cc52
-rw-r--r--mojo/edk/system/message_pipe_endpoint.h90
-rw-r--r--mojo/edk/system/message_pipe_perftest.cc172
-rw-r--r--mojo/edk/system/message_pipe_test_utils.cc109
-rw-r--r--mojo/edk/system/message_pipe_test_utils.h73
-rw-r--r--mojo/edk/system/message_pipe_unittest.cc574
-rw-r--r--mojo/edk/system/multiprocess_message_pipe_unittest.cc520
-rw-r--r--mojo/edk/system/options_validation.h102
-rw-r--r--mojo/edk/system/options_validation_unittest.cc130
-rw-r--r--mojo/edk/system/platform_handle_dispatcher.cc118
-rw-r--r--mojo/edk/system/platform_handle_dispatcher.h61
-rw-r--r--mojo/edk/system/platform_handle_dispatcher_unittest.cc111
-rw-r--r--mojo/edk/system/proxy_message_pipe_endpoint.cc65
-rw-r--r--mojo/edk/system/proxy_message_pipe_endpoint.h61
-rw-r--r--mojo/edk/system/raw_channel.cc514
-rw-r--r--mojo/edk/system/raw_channel.h329
-rw-r--r--mojo/edk/system/raw_channel_posix.cc469
-rw-r--r--mojo/edk/system/raw_channel_unittest.cc805
-rw-r--r--mojo/edk/system/raw_channel_win.cc576
-rw-r--r--mojo/edk/system/remote_message_pipe_unittest.cc1376
-rw-r--r--mojo/edk/system/run_all_unittests.cc24
-rw-r--r--mojo/edk/system/shared_buffer_dispatcher.cc276
-rw-r--r--mojo/edk/system/shared_buffer_dispatcher.h103
-rw-r--r--mojo/edk/system/shared_buffer_dispatcher_unittest.cc279
-rw-r--r--mojo/edk/system/simple_dispatcher.cc61
-rw-r--r--mojo/edk/system/simple_dispatcher.h51
-rw-r--r--mojo/edk/system/simple_dispatcher_unittest.cc609
-rw-r--r--mojo/edk/system/system_impl_export.h29
-rw-r--r--mojo/edk/system/test_utils.cc32
-rw-r--r--mojo/edk/system/test_utils.h43
-rw-r--r--mojo/edk/system/transport_data.cc337
-rw-r--r--mojo/edk/system/transport_data.h189
-rw-r--r--mojo/edk/system/unique_identifier.cc29
-rw-r--r--mojo/edk/system/unique_identifier.h92
-rw-r--r--mojo/edk/system/unique_identifier_unittest.cc106
-rw-r--r--mojo/edk/system/waiter.cc100
-rw-r--r--mojo/edk/system/waiter.h79
-rw-r--r--mojo/edk/system/waiter_test_utils.cc70
-rw-r--r--mojo/edk/system/waiter_test_utils.h105
-rw-r--r--mojo/edk/system/waiter_unittest.cc302
-rw-r--r--mojo/edk/test/BUILD.gn119
-rw-r--r--mojo/edk/test/multiprocess_test_helper.cc84
-rw-r--r--mojo/edk/test/multiprocess_test_helper.h92
-rw-r--r--mojo/edk/test/multiprocess_test_helper_unittest.cc194
-rw-r--r--mojo/edk/test/run_all_perftests.cc14
-rw-r--r--mojo/edk/test/run_all_unittests.cc26
-rw-r--r--mojo/edk/test/test_support_impl.cc83
-rw-r--r--mojo/edk/test/test_support_impl.h34
-rw-r--r--mojo/edk/test/test_utils.h57
-rw-r--r--mojo/edk/test/test_utils_posix.cc100
-rw-r--r--mojo/edk/test/test_utils_win.cc124
184 files changed, 0 insertions, 31524 deletions
diff --git a/mojo/edk/DEPS b/mojo/edk/DEPS
deleted file mode 100644
index 9a51b60..0000000
--- a/mojo/edk/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
- "-mojo",
- "+mojo/edk",
- "+mojo/public",
-
- "+third_party/ashmem",
-]
diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn
deleted file mode 100644
index d9a6e69..0000000
--- a/mojo/edk/embedder/BUILD.gn
+++ /dev/null
@@ -1,114 +0,0 @@
-# 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.
-
-import("../mojo_edk.gni")
-
-mojo_edk_source_set("embedder") {
- # This isn't really a standalone target; it must be linked into the
- # mojo_system_impl component.
- mojo_edk_visibility = [ "mojo/edk/system" ]
-
- sources = [
- "channel_info_forward.h",
- "channel_init.cc",
- "channel_init.h",
- "configuration.h",
- "embedder.cc",
- "embedder.h",
- "embedder_internal.h",
- "entrypoints.cc",
-
- # Test-only code:
- # TODO(vtl): It's a little unfortunate that these end up in the same
- # component as non-test-only code. In the static build, this code should
- # hopefully be dead-stripped.
- "test_embedder.cc",
- "test_embedder.h",
- ]
-
- defines = [
- "MOJO_SYSTEM_IMPL_IMPLEMENTATION",
- "MOJO_SYSTEM_IMPLEMENTATION",
- ]
-
- mojo_edk_configs = [ "mojo/edk/system:system_config" ]
-
- public_deps = [
- ":platform",
- ]
-
- mojo_sdk_public_deps = [ "mojo/public/cpp/system" ]
-
- deps = [
- "//base",
- ]
-}
-
-mojo_edk_source_set("platform") {
- # This isn't really a standalone target; it must be linked into the
- # mojo_system_impl component.
- visibility = [ ":embedder" ]
-
- mojo_edk_visibility = [ "mojo/edk/system" ]
-
- sources = [
- "platform_channel_pair.cc",
- "platform_channel_pair.h",
- "platform_channel_pair_posix.cc",
- "platform_channel_pair_win.cc",
- "platform_channel_utils_posix.cc",
- "platform_channel_utils_posix.h",
- "platform_handle.cc",
- "platform_handle.h",
- "platform_handle_utils.h",
- "platform_handle_utils_posix.cc",
- "platform_handle_utils_win.cc",
- "platform_handle_vector.h",
- "platform_shared_buffer.h",
- "platform_support.h",
- "scoped_platform_handle.h",
- "simple_platform_shared_buffer.cc",
- "simple_platform_shared_buffer.h",
- "simple_platform_shared_buffer_android.cc",
- "simple_platform_shared_buffer_posix.cc",
- "simple_platform_shared_buffer_win.cc",
- "simple_platform_support.cc",
- "simple_platform_support.h",
- ]
-
- defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
-
- mojo_edk_configs = [ "mojo/edk/system:system_config" ]
-
- deps = [
- "//base",
- ]
-
- if (is_android) {
- deps += [ "//third_party/ashmem" ]
- }
-}
-
-mojo_edk_source_set("embedder_unittests") {
- testonly = true
- mojo_edk_visibility = [ "mojo/edk/system:mojo_system_unittests" ]
-
- sources = [
- "embedder_unittest.cc",
- "platform_channel_pair_posix_unittest.cc",
- "simple_platform_shared_buffer_unittest.cc",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-
- mojo_edk_deps = [
- "mojo/edk/test:test_support",
- "mojo/edk/system",
- "mojo/edk/system:test_utils",
- ]
-}
diff --git a/mojo/edk/embedder/DEPS b/mojo/edk/embedder/DEPS
deleted file mode 100644
index c3a0d22..0000000
--- a/mojo/edk/embedder/DEPS
+++ /dev/null
@@ -1,11 +0,0 @@
-include_rules = [
- "+mojo/edk/system/system_impl_export.h",
-]
-
-specific_include_rules = {
- # Implementation files may freely access mojo/edk/system, but we don't want to
- # leak implementation details through the headers.
- ".*\.cc": [
- "+mojo/edk/system",
- ]
-}
diff --git a/mojo/edk/embedder/README.md b/mojo/edk/embedder/README.md
deleted file mode 100644
index f976fcb..0000000
--- a/mojo/edk/embedder/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-Mojo Embedder API
-=================
-
-The Mojo Embedder API is an unstable, internal API to the Mojo system
-implementation. It should be used by code running on top of the system-level
-APIs to set up the Mojo environment (instead of directly instantiating things
-from src/mojo/edk/system).
-
-Example uses: Mojo shell, to set up the Mojo environment for Mojo apps; Chromium
-code, to set up the Mojo IPC system for use between processes. Note that most
-code should use the Mojo Public API (under src/mojo/public) instead. The
-Embedder API should only be used to initialize the environment, set up the
-initial MessagePipe between two processes, etc.
diff --git a/mojo/edk/embedder/channel_info_forward.h b/mojo/edk/embedder/channel_info_forward.h
deleted file mode 100644
index 8d23836..0000000
--- a/mojo/edk/embedder/channel_info_forward.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-// This file simply (forward) declares |mojo::embedder::ChannelInfo|, which is
-// meant to be opaque to users of the embedder API.
-
-#ifndef MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_
-#define MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_
-
-namespace mojo {
-namespace embedder {
-
-// This is an opaque type. The embedder API uses (returns and takes as
-// arguments) pointers to this type. (We don't simply use |void*|, so that
-// custom deleters and such can be used without additional wrappers.
-struct ChannelInfo;
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_CHANNEL_INFO_FORWARD_H_
diff --git a/mojo/edk/embedder/channel_init.cc b/mojo/edk/embedder/channel_init.cc
deleted file mode 100644
index 9a0bfce..0000000
--- a/mojo/edk/embedder/channel_init.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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/channel_init.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/embedder.h"
-
-namespace mojo {
-namespace embedder {
-
-ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {
-}
-
-ChannelInit::~ChannelInit() {
- if (channel_info_)
- DestroyChannel(channel_info_);
-}
-
-ScopedMessagePipeHandle ChannelInit::Init(
- base::PlatformFile file,
- scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- DCHECK(!io_thread_task_runner_); // Should only init once.
- io_thread_task_runner_ = io_thread_task_runner;
- ScopedMessagePipeHandle message_pipe =
- CreateChannel(
- ScopedPlatformHandle(PlatformHandle(file)), io_thread_task_runner,
- base::Bind(&ChannelInit::OnCreatedChannel, weak_factory_.GetWeakPtr(),
- io_thread_task_runner),
- base::MessageLoop::current()->message_loop_proxy()).Pass();
- return message_pipe.Pass();
-}
-
-void ChannelInit::WillDestroySoon() {
- if (channel_info_)
- WillDestroyChannelSoon(channel_info_);
-}
-
-// static
-void ChannelInit::OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- scoped_refptr<base::TaskRunner> io_thread,
- ChannelInfo* channel) {
- // If |self| was already destroyed, shut the channel down.
- if (!self) {
- DestroyChannel(channel);
- return;
- }
-
- self->channel_info_ = channel;
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/channel_init.h b/mojo/edk/embedder/channel_init.h
deleted file mode 100644
index 59b6694..0000000
--- a/mojo/edk/embedder/channel_init.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_CHANNEL_INIT_H_
-#define MOJO_EDK_EMBEDDER_CHANNEL_INIT_H_
-
-#include "base/files/file.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/edk/embedder/channel_info_forward.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace base {
-class MessageLoopProxy;
-class TaskRunner;
-}
-
-namespace mojo {
-namespace embedder {
-
-// |ChannelInit| handles creation (and destruction) of the Mojo channel. It is
-// not thread-safe, but may be used on any single thread (with a |MessageLoop|).
-class MOJO_SYSTEM_IMPL_EXPORT ChannelInit {
- public:
- ChannelInit();
- ~ChannelInit();
-
- // Initializes the channel. This takes ownership of |file|. Returns the
- // primordial MessagePipe for the channel.
- mojo::ScopedMessagePipeHandle Init(
- base::PlatformFile file,
- scoped_refptr<base::TaskRunner> io_thread_task_runner);
-
- // Notifies the channel that we (hence it) will soon be destroyed.
- void WillDestroySoon();
-
- private:
- // Invoked on the thread on which this object lives once the channel has been
- // established. (This is a static method that takes a weak pointer to self,
- // since we want to destroy the channel even if we're destroyed.)
- static void OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- scoped_refptr<base::TaskRunner> io_thread,
- ChannelInfo* channel);
-
- scoped_refptr<base::TaskRunner> io_thread_task_runner_;
-
- // If non-null the channel has been established.
- ChannelInfo* channel_info_;
-
- base::WeakPtrFactory<ChannelInit> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelInit);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_CHANNEL_INIT_H_
diff --git a/mojo/edk/embedder/configuration.h b/mojo/edk/embedder/configuration.h
deleted file mode 100644
index 0f99e1f..0000000
--- a/mojo/edk/embedder/configuration.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_CONFIGURATION_H_
-#define MOJO_EDK_EMBEDDER_CONFIGURATION_H_
-
-#include <stddef.h>
-
-namespace mojo {
-namespace embedder {
-
-// A set of constants that the Mojo system internally uses. These values should
-// be consistent across all processes on the same system.
-//
-// In general, there should be no need to change these values from their
-// defaults. However, if you do change them, you must do so before
-// initialization.
-struct Configuration {
- // Maximum number of open (Mojo) handles. The default is 1,000,000.
- //
- // TODO(vtl): This doesn't count "live" handles, some of which may live in
- // messages.
- size_t max_handle_table_size;
-
- // Maximum number of active memory mappings. The default is 1,000,000.
- size_t max_mapping_table_sze;
-
- // Upper limit of |MojoWaitMany()|'s |num_handles|. The default is 1,000,000.
- // Must be same as or smaller than |max_handle_table_size|.
- size_t max_wait_many_num_handles;
-
- // Maximum data size of messages sent over message pipes, in bytes. The
- // default is 4MB.
- size_t max_message_num_bytes;
-
- // Maximum number of handles that can be attached to messages sent over
- // message pipes. The default is 10,000.
- size_t max_message_num_handles;
-
- // Maximum capacity of a data pipe, in bytes. The default is 256MB. This value
- // must fit into a |uint32_t|. WARNING: If you bump it closer to 2^32, you
- // must audit all the code to check that we don't overflow (2^31 would
- // definitely be risky; up to 2^30 is probably okay).
- size_t max_data_pipe_capacity_bytes;
-
- // Default data pipe capacity, if not specified explicitly in the creation
- // options. The default is 1MB.
- size_t default_data_pipe_capacity_bytes;
-
- // Alignment for the "start" of the data buffer used by data pipes. (The
- // alignment of elements will depend on this and the element size.) The
- // default is 16 bytes.
- size_t data_pipe_buffer_alignment_bytes;
-
- // Maximum size of a single shared memory segment, in bytes. The default is
- // 1GB.
- //
- // TODO(vtl): Set this hard limit appropriately (e.g., higher on 64-bit).
- // (This will also entail some auditing to make sure I'm not messing up my
- // checks anywhere.)
- size_t max_shared_memory_num_bytes;
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_CONFIGURATION_H_
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc
deleted file mode 100644
index 1d12c1e..0000000
--- a/mojo/edk/embedder/embedder.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-// 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/embedder.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/embedder/platform_support.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/channel_manager.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/raw_channel.h"
-
-namespace mojo {
-namespace embedder {
-
-namespace {
-
-// Helper for |CreateChannel...()|. Returns 0 on failure. Called on the channel
-// creation thread.
-system::ChannelId MakeChannel(
- ScopedPlatformHandle platform_handle,
- scoped_refptr<system::ChannelEndpoint> channel_endpoint) {
- DCHECK(platform_handle.is_valid());
-
- // Create and initialize a |system::Channel|.
- DCHECK(internal::g_core);
- scoped_refptr<system::Channel> channel =
- new system::Channel(internal::g_core->platform_support());
- channel->Init(system::RawChannel::Create(platform_handle.Pass()));
- channel->SetBootstrapEndpoint(channel_endpoint);
-
- DCHECK(internal::g_channel_manager);
- return internal::g_channel_manager->AddChannel(
- channel, base::MessageLoopProxy::current());
-}
-
-// Helper for |CreateChannel()|. Called on the channel creation thread.
-void CreateChannelHelper(
- ScopedPlatformHandle platform_handle,
- scoped_ptr<ChannelInfo> channel_info,
- scoped_refptr<system::ChannelEndpoint> channel_endpoint,
- DidCreateChannelCallback callback,
- scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
- channel_info->channel_id =
- MakeChannel(platform_handle.Pass(), channel_endpoint);
-
- // Hand the channel back to the embedder.
- if (callback_thread_task_runner) {
- callback_thread_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, channel_info.release()));
- } else {
- callback.Run(channel_info.release());
- }
-}
-
-} // namespace
-
-namespace internal {
-
-// Declared in embedder_internal.h.
-system::Core* g_core = nullptr;
-system::ChannelManager* g_channel_manager = nullptr;
-
-} // namespace internal
-
-void Init(scoped_ptr<PlatformSupport> platform_support) {
- DCHECK(!internal::g_core);
- internal::g_core = new system::Core(platform_support.Pass());
- DCHECK(!internal::g_channel_manager);
- internal::g_channel_manager = new system::ChannelManager();
-}
-
-Configuration* GetConfiguration() {
- return system::GetMutableConfiguration();
-}
-
-// TODO(vtl): Write tests for this.
-ScopedMessagePipeHandle CreateChannelOnIOThread(
- ScopedPlatformHandle platform_handle,
- ChannelInfo** channel_info) {
- DCHECK(platform_handle.is_valid());
- DCHECK(channel_info);
-
- scoped_refptr<system::ChannelEndpoint> channel_endpoint;
- scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
-
- DCHECK(internal::g_core);
- ScopedMessagePipeHandle rv(
- MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
-
- *channel_info =
- new ChannelInfo(MakeChannel(platform_handle.Pass(), channel_endpoint));
-
- return rv.Pass();
-}
-
-ScopedMessagePipeHandle CreateChannel(
- ScopedPlatformHandle platform_handle,
- scoped_refptr<base::TaskRunner> io_thread_task_runner,
- DidCreateChannelCallback callback,
- scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
- DCHECK(platform_handle.is_valid());
- DCHECK(io_thread_task_runner);
- DCHECK(!callback.is_null());
-
- scoped_refptr<system::ChannelEndpoint> channel_endpoint;
- scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- system::MessagePipeDispatcher::CreateRemoteMessagePipe(&channel_endpoint);
-
- DCHECK(internal::g_core);
- ScopedMessagePipeHandle rv(
- MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
-
- // We'll have to set |channel_info->channel_id| on the I/O thread.
- scoped_ptr<ChannelInfo> channel_info(new ChannelInfo());
-
- if (rv.is_valid()) {
- io_thread_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&CreateChannelHelper, base::Passed(&platform_handle),
- base::Passed(&channel_info), channel_endpoint, callback,
- callback_thread_task_runner));
- } else {
- (callback_thread_task_runner.get() ? callback_thread_task_runner
- : io_thread_task_runner)
- ->PostTask(FROM_HERE, base::Bind(callback, channel_info.release()));
- }
-
- return rv.Pass();
-}
-
-// TODO(vtl): Write tests for this.
-void DestroyChannel(ChannelInfo* channel_info) {
- DCHECK(channel_info);
- DCHECK(channel_info->channel_id);
- DCHECK(internal::g_channel_manager);
- // This will destroy the channel synchronously if called from the channel
- // thread.
- internal::g_channel_manager->ShutdownChannel(channel_info->channel_id);
- delete channel_info;
-}
-
-void WillDestroyChannelSoon(ChannelInfo* channel_info) {
- DCHECK(channel_info);
- DCHECK(internal::g_channel_manager);
- internal::g_channel_manager->WillShutdownChannel(channel_info->channel_id);
-}
-
-MojoResult CreatePlatformHandleWrapper(
- ScopedPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle) {
- DCHECK(platform_handle_wrapper_handle);
-
- scoped_refptr<system::Dispatcher> dispatcher(
- new system::PlatformHandleDispatcher(platform_handle.Pass()));
-
- DCHECK(internal::g_core);
- MojoHandle h = internal::g_core->AddDispatcher(dispatcher);
- if (h == MOJO_HANDLE_INVALID) {
- LOG(ERROR) << "Handle table full";
- dispatcher->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
-
- *platform_handle_wrapper_handle = h;
- return MOJO_RESULT_OK;
-}
-
-MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
- ScopedPlatformHandle* platform_handle) {
- DCHECK(platform_handle);
-
- DCHECK(internal::g_core);
- scoped_refptr<system::Dispatcher> dispatcher(
- internal::g_core->GetDispatcher(platform_handle_wrapper_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- *platform_handle =
- static_cast<system::PlatformHandleDispatcher*>(dispatcher.get())
- ->PassPlatformHandle()
- .Pass();
- return MOJO_RESULT_OK;
-}
-
-MojoResult AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback) {
- return internal::g_core->AsyncWait(handle, signals, callback);
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h
deleted file mode 100644
index 987c6879..0000000
--- a/mojo/edk/embedder/embedder.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_H_
-#define MOJO_EDK_EMBEDDER_EMBEDDER_H_
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/task_runner.h"
-#include "mojo/edk/embedder/channel_info_forward.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace mojo {
-namespace embedder {
-
-struct Configuration;
-class PlatformSupport;
-
-// Must be called first, or just after setting configuration parameters,
-// to initialize the (global, singleton) system.
-MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr<PlatformSupport> platform_support);
-
-// Returns the global configuration. In general there should be no need to
-// change the configuration, but if you do so this must be done before calling
-// |Init()|.
-MOJO_SYSTEM_IMPL_EXPORT Configuration* GetConfiguration();
-
-// A "channel" is a connection on top of an OS "pipe", on top of which Mojo
-// message pipes (etc.) can be multiplexed. It must "live" on some I/O thread.
-//
-// There are two channel creation APIs: |CreateChannelOnIOThread()| creates a
-// channel synchronously and must be called from the I/O thread, while
-// |CreateChannel()| is asynchronous and may be called from any thread.
-// |DestroyChannel()| is used to destroy the channel in either case and may be
-// called from any thread, but completes synchronously when called from the I/O
-// thread.
-//
-// Both creation functions have a |platform_handle| argument, which should be an
-// OS-dependent handle to one side of a suitable bidirectional OS "pipe" (e.g.,
-// a file descriptor to a socket on POSIX, a handle to a named pipe on Windows);
-// this "pipe" should be connected and ready for operation (e.g., to be written
-// to or read from).
-//
-// Both (synchronously) return a handle to the bootstrap message pipe on the
-// channel that was (or is to be) created, or |MOJO_HANDLE_INVALID| on error
-// (but note that this will happen only if, e.g., the handle table is full).
-// This message pipe may be used immediately, but since channel operation
-// actually begins asynchronously, other errors may still occur (e.g., if the
-// other end of the "pipe" is closed) and be reported in the usual way to the
-// returned handle.
-//
-// (E.g., a message written immediately to the returned handle will be queued
-// and the handle immediately closed, before the channel begins operation. In
-// this case, the channel should connect as usual, send the queued message, and
-// report that the handle was closed to the other side. The message sent may
-// have other handles, so there may still be message pipes "on" this channel.)
-//
-// Both also produce a |ChannelInfo*| (a pointer to an opaque object) -- the
-// first synchronously and second asynchronously.
-//
-// The destruction functions are similarly synchronous and asynchronous,
-// respectively, and take the |ChannelInfo*| produced by the creation functions.
-//
-// TODO(vtl): Figure out channel teardown.
-
-// Creates a channel; must only be called from the I/O thread. |platform_handle|
-// should be a handle to a connected OS "pipe". Eventually (even on failure),
-// the "out" value |*channel_info| should be passed to |DestoryChannel()| to
-// tear down the channel. Returns a handle to the bootstrap message pipe.
-MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle
-CreateChannelOnIOThread(ScopedPlatformHandle platform_handle,
- ChannelInfo** channel_info);
-
-typedef base::Callback<void(ChannelInfo*)> DidCreateChannelCallback;
-// Creates a channel asynchronously; may be called from any thread.
-// |platform_handle| should be a handle to a connected OS "pipe".
-// |io_thread_task_runner| should be the |TaskRunner| for the I/O thread.
-// |callback| should be the callback to call with the |ChannelInfo*|, which
-// should eventually be passed to |DestroyChannel()| to tear down the channel;
-// the callback will be called using |callback_thread_task_runner| if that is
-// non-null, or otherwise it will be called using |io_thread_task_runner|.
-// Returns a handle to the bootstrap message pipe.
-MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle
-CreateChannel(ScopedPlatformHandle platform_handle,
- scoped_refptr<base::TaskRunner> io_thread_task_runner,
- DidCreateChannelCallback callback,
- scoped_refptr<base::TaskRunner> callback_thread_task_runner);
-
-// Destroys a channel that was created using |CreateChannel()| (or
-// |CreateChannelOnIOThread()|); may be called from any thread. |channel_info|
-// should be the value provided to the callback to |CreateChannel()| (or
-// returned by |CreateChannelOnIOThread()|). If called from the I/O thread, this
-// will complete synchronously (in particular, it will post no tasks).
-MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel(ChannelInfo* channel_info);
-
-// Inform the channel that it will soon be destroyed (doing so is optional).
-// This may be called from any thread, but the caller must ensure that this is
-// called before |DestroyChannel()|.
-MOJO_SYSTEM_IMPL_EXPORT void WillDestroyChannelSoon(ChannelInfo* channel_info);
-
-// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking
-// ownership of it). This |MojoHandle| can then, e.g., be passed through message
-// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on
-// failure, which is different from what you'd expect from a Mojo API, but it
-// makes for a more convenient embedder API.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle);
-// Retrieves the |PlatformHandle| that was wrapped into a |MojoHandle| (using
-// |CreatePlatformHandleWrapper()| above). Note that the |MojoHandle| must still
-// be closed separately.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
- ScopedPlatformHandle* platform_handle);
-
-// Start waiting the handle asynchronously. On success, |callback| will be
-// called exactly once, when |handle| satisfies a signal in |signals| or it
-// becomes known that it will never do so. |callback| will be executed on an
-// arbitrary thread. It must not call any Mojo system or embedder functions.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback);
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_EMBEDDER_H_
diff --git a/mojo/edk/embedder/embedder_internal.h b/mojo/edk/embedder/embedder_internal.h
deleted file mode 100644
index ab8388a..0000000
--- a/mojo/edk/embedder/embedder_internal.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.
-
-// This header contains internal details for the *implementation* of the
-// embedder API. It should not be included by any public header (nor by users of
-// the embedder API).
-
-#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
-#define MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
-
-#include <stdint.h>
-
-namespace mojo {
-
-namespace system {
-
-class ChannelManager;
-class Core;
-
-// Repeat a typedef in mojo/edk/system/channel_manager.h, to avoid including it.
-typedef uintptr_t ChannelId;
-
-} // namespace system
-
-namespace embedder {
-
-// This is a type that's opaque to users of the embedder API (which only
-// gives/takes |ChannelInfo*|s). We make it a struct to make it
-// template-friendly.
-struct ChannelInfo {
- explicit ChannelInfo(system::ChannelId channel_id = 0)
- : channel_id(channel_id) {}
-
- system::ChannelId channel_id;
-};
-
-namespace internal {
-
-// Instance of |Core| used by the system functions (|Mojo...()|).
-extern system::Core* g_core;
-
-// Instance of |ChannelManager| used by the channel management functions
-// (|mojo::embedder::CreateChannel()|, etc.).
-extern system::ChannelManager* g_channel_manager;
-
-} // namespace internal
-
-} // namepace embedder
-
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc
deleted file mode 100644
index ed4ea2e..0000000
--- a/mojo/edk/embedder/embedder_unittest.cc
+++ /dev/null
@@ -1,639 +0,0 @@
-// 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/embedder.h"
-
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_io_thread.h"
-#include "base/test/test_timeouts.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/test_embedder.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/multiprocess_test_helper.h"
-#include "mojo/public/c/system/core.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace embedder {
-namespace {
-
-const MojoHandleSignals kSignalReadadableWritable =
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE;
-
-const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED;
-
-class ScopedTestChannel {
- public:
- // Creates a channel that lives on a given I/O thread (determined by the given
- // |TaskRunner|) attached to the given |platform_handle|. After construction,
- // |bootstrap_message_pipe()| gives the Mojo handle for the bootstrap message
- // pipe on this channel; it is up to the caller to close this handle.
- // Note: The I/O thread must outlive this object (and its message loop must
- // continue pumping messages while this object is alive).
- ScopedTestChannel(scoped_refptr<base::TaskRunner> io_thread_task_runner,
- ScopedPlatformHandle platform_handle)
- : io_thread_task_runner_(io_thread_task_runner),
- bootstrap_message_pipe_(MOJO_HANDLE_INVALID),
- did_create_channel_event_(true, false),
- channel_info_(nullptr) {
- bootstrap_message_pipe_ =
- CreateChannel(platform_handle.Pass(), io_thread_task_runner_,
- base::Bind(&ScopedTestChannel::DidCreateChannel,
- base::Unretained(this)),
- nullptr)
- .release()
- .value();
- CHECK_NE(bootstrap_message_pipe_, MOJO_HANDLE_INVALID);
- }
-
- // Destructor: Shuts down the channel. (As noted above, for this to happen,
- // the I/O thread must be alive and pumping messages.)
- ~ScopedTestChannel() { DestroyChannel(channel_info_); }
-
- // Waits for channel creation to be completed.
- void WaitForChannelCreationCompletion() { did_create_channel_event_.Wait(); }
-
- MojoHandle bootstrap_message_pipe() const { return bootstrap_message_pipe_; }
-
- // Call only after |WaitForChannelCreationCompletion()|. Use only to check
- // that it's not null.
- const ChannelInfo* channel_info() const { return channel_info_; }
-
- private:
- void DidCreateChannel(ChannelInfo* channel_info) {
- CHECK(channel_info);
- CHECK(!channel_info_);
- channel_info_ = channel_info;
- did_create_channel_event_.Signal();
- }
-
- scoped_refptr<base::TaskRunner> io_thread_task_runner_;
-
- // Valid from creation until whenever it gets closed (by the "owner" of this
- // object).
- // Note: We don't want use the C++ wrappers here, since we want to test the
- // API at the lowest level.
- MojoHandle bootstrap_message_pipe_;
-
- // Set after channel creation has been completed (i.e., the callback to
- // |CreateChannel()| has been called).
- base::WaitableEvent did_create_channel_event_;
-
- // Valid after channel creation completion until destruction.
- ChannelInfo* channel_info_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedTestChannel);
-};
-
-class EmbedderTest : public testing::Test {
- public:
- EmbedderTest() : test_io_thread_(base::TestIOThread::kAutoStart) {}
- ~EmbedderTest() override {}
-
- protected:
- base::TestIOThread* test_io_thread() { return &test_io_thread_; }
-
- private:
- base::TestIOThread test_io_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(EmbedderTest);
-};
-
-TEST_F(EmbedderTest, ChannelsBasic) {
- mojo::embedder::test::InitWithSimplePlatformSupport();
-
- {
- PlatformChannelPair channel_pair;
- ScopedTestChannel server_channel(test_io_thread()->task_runner(),
- channel_pair.PassServerHandle());
- MojoHandle server_mp = server_channel.bootstrap_message_pipe();
- EXPECT_NE(server_mp, MOJO_HANDLE_INVALID);
- ScopedTestChannel client_channel(test_io_thread()->task_runner(),
- channel_pair.PassClientHandle());
- MojoHandle client_mp = client_channel.bootstrap_message_pipe();
- EXPECT_NE(client_mp, MOJO_HANDLE_INVALID);
-
- // We can write to a message pipe handle immediately.
- const char kHello[] = "hello";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(server_mp, kHello,
- static_cast<uint32_t>(sizeof(kHello)), nullptr,
- 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Now wait for the other side to become readable.
- MojoHandleSignalsState state;
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- char buffer[1000] = {};
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), num_bytes);
- EXPECT_STREQ(kHello, buffer);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp));
-
- // By this point, these waits should basically be no-ops (since we've waited
- // for the client message pipe to become readable, which implies that both
- // the server and client channels were completely created).
- server_channel.WaitForChannelCreationCompletion();
- client_channel.WaitForChannelCreationCompletion();
- EXPECT_TRUE(server_channel.channel_info());
- EXPECT_TRUE(client_channel.channel_info());
- }
-
- EXPECT_TRUE(test::Shutdown());
-}
-
-class TestAsyncWaiter {
- public:
- TestAsyncWaiter() : event_(true, false), wait_result_(MOJO_RESULT_UNKNOWN) {}
-
- void Awake(MojoResult result) {
- base::AutoLock l(wait_result_lock_);
- wait_result_ = result;
- event_.Signal();
- }
-
- bool TryWait() { return event_.TimedWait(TestTimeouts::action_timeout()); }
-
- MojoResult wait_result() const {
- base::AutoLock l(wait_result_lock_);
- return wait_result_;
- }
-
- private:
- base::WaitableEvent event_;
-
- mutable base::Lock wait_result_lock_;
- MojoResult wait_result_;
-
- DISALLOW_COPY_AND_ASSIGN(TestAsyncWaiter);
-};
-
-void WriteHello(MessagePipeHandle pipe) {
- static const char kHello[] = "hello";
- CHECK_EQ(MOJO_RESULT_OK,
- WriteMessageRaw(pipe, kHello, static_cast<uint32_t>(sizeof(kHello)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-}
-
-void CloseScopedHandle(ScopedMessagePipeHandle handle) {
- // Do nothing and the destructor will close it.
-}
-
-TEST_F(EmbedderTest, AsyncWait) {
- mojo::embedder::test::InitWithSimplePlatformSupport();
-
- {
- ScopedMessagePipeHandle client_mp;
- ScopedMessagePipeHandle server_mp;
- EXPECT_EQ(MOJO_RESULT_OK,
- mojo::CreateMessagePipe(nullptr, &client_mp, &server_mp));
-
- TestAsyncWaiter waiter;
- EXPECT_EQ(MOJO_RESULT_OK,
- AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter))));
-
- test_io_thread()->task_runner()->PostTask(
- FROM_HERE, base::Bind(&WriteHello, server_mp.get()));
- EXPECT_TRUE(waiter.TryWait());
- EXPECT_EQ(MOJO_RESULT_OK, waiter.wait_result());
-
- // If message is in the queue, it does't allow us to wait.
- TestAsyncWaiter waiter_that_doesnt_wait;
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter_that_doesnt_wait))));
-
- char buffer[1000];
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- CHECK_EQ(MOJO_RESULT_OK,
- ReadMessageRaw(client_mp.get(), buffer, &num_bytes, nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
-
- TestAsyncWaiter unsatisfiable_waiter;
- EXPECT_EQ(MOJO_RESULT_OK,
- AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&unsatisfiable_waiter))));
-
- test_io_thread()->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&CloseScopedHandle, base::Passed(server_mp.Pass())));
-
- EXPECT_TRUE(unsatisfiable_waiter.TryWait());
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- unsatisfiable_waiter.wait_result());
- }
-
- EXPECT_TRUE(test::Shutdown());
-}
-
-TEST_F(EmbedderTest, ChannelsHandlePassing) {
- mojo::embedder::test::InitWithSimplePlatformSupport();
-
- {
- PlatformChannelPair channel_pair;
- ScopedTestChannel server_channel(test_io_thread()->task_runner(),
- channel_pair.PassServerHandle());
- MojoHandle server_mp = server_channel.bootstrap_message_pipe();
- EXPECT_NE(server_mp, MOJO_HANDLE_INVALID);
- ScopedTestChannel client_channel(test_io_thread()->task_runner(),
- channel_pair.PassClientHandle());
- MojoHandle client_mp = client_channel.bootstrap_message_pipe();
- EXPECT_NE(client_mp, MOJO_HANDLE_INVALID);
-
- MojoHandle h0, h1;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1));
-
- // Write a message to |h0| (attaching nothing).
- const char kHello[] = "hello";
- EXPECT_EQ(
- MOJO_RESULT_OK,
- MojoWriteMessage(h0, kHello, static_cast<uint32_t>(sizeof(kHello)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Write one message to |server_mp|, attaching |h1|.
- const char kWorld[] = "world!!!";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(server_mp, kWorld,
- static_cast<uint32_t>(sizeof(kWorld)), &h1, 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- h1 = MOJO_HANDLE_INVALID;
-
- // Write another message to |h0|.
- const char kFoo[] = "foo";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(h0, kFoo, static_cast<uint32_t>(sizeof(kFoo)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait for |client_mp| to become readable.
- MojoHandleSignalsState state;
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- // Read a message from |client_mp|.
- char buffer[1000] = {};
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- MojoHandle handles[10] = {};
- uint32_t num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(client_mp, buffer, &num_bytes, handles,
- &num_handles, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), num_bytes);
- EXPECT_STREQ(kWorld, buffer);
- EXPECT_EQ(1u, num_handles);
- EXPECT_NE(handles[0], MOJO_HANDLE_INVALID);
- h1 = handles[0];
-
- // Wait for |h1| to become readable.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- // Read a message from |h1|.
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- memset(handles, 0, sizeof(handles));
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(h1, buffer, &num_bytes, handles, &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(0u, num_handles);
-
- // Wait for |h1| to become readable (again).
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- // Read the second message from |h1|.
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(h1, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kFoo), num_bytes);
- EXPECT_STREQ(kFoo, buffer);
-
- // Write a message to |h1|.
- const char kBarBaz[] = "barbaz";
- EXPECT_EQ(
- MOJO_RESULT_OK,
- MojoWriteMessage(h1, kBarBaz, static_cast<uint32_t>(sizeof(kBarBaz)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait for |h0| to become readable.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- // Read a message from |h0|.
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(h0, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kBarBaz), num_bytes);
- EXPECT_STREQ(kBarBaz, buffer);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
-
- server_channel.WaitForChannelCreationCompletion();
- client_channel.WaitForChannelCreationCompletion();
- EXPECT_TRUE(server_channel.channel_info());
- EXPECT_TRUE(client_channel.channel_info());
- }
-
- EXPECT_TRUE(test::Shutdown());
-}
-
-// The sequence of messages sent is:
-// server_mp client_mp mp0 mp1 mp2 mp3
-// 1. "hello"
-// 2. "world!"
-// 3. "FOO"
-// 4. "Bar"+mp1
-// 5. (close)
-// 6. (close)
-// 7. "baz"
-// 8. (closed)
-// 9. "quux"+mp2
-// 10. (close)
-// 11. (wait/cl.)
-// 12. (wait/cl.)
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels
-#else
-#define MAYBE_MultiprocessChannels MultiprocessChannels
-#endif // defined(OS_ANDROID)
-TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) {
- mojo::embedder::test::InitWithSimplePlatformSupport();
- mojo::test::MultiprocessTestHelper multiprocess_test_helper;
- multiprocess_test_helper.StartChild("MultiprocessChannelsClient");
-
- {
- ScopedTestChannel server_channel(
- test_io_thread()->task_runner(),
- multiprocess_test_helper.server_platform_handle.Pass());
- MojoHandle server_mp = server_channel.bootstrap_message_pipe();
- EXPECT_NE(server_mp, MOJO_HANDLE_INVALID);
- server_channel.WaitForChannelCreationCompletion();
- EXPECT_TRUE(server_channel.channel_info());
-
- // 1. Write a message to |server_mp| (attaching nothing).
- const char kHello[] = "hello";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(server_mp, kHello,
- static_cast<uint32_t>(sizeof(kHello)), nullptr,
- 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // TODO(vtl): If the scope were ended immediately here (maybe after closing
- // |server_mp|), we die with a fatal error in |Channel::HandleLocalError()|.
-
- // 2. Read a message from |server_mp|.
- MojoHandleSignalsState state;
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- char buffer[1000] = {};
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(server_mp, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kWorld[] = "world!";
- EXPECT_EQ(sizeof(kWorld), num_bytes);
- EXPECT_STREQ(kWorld, buffer);
-
- // Create a new message pipe (endpoints |mp0| and |mp1|).
- MojoHandle mp0, mp1;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp0, &mp1));
-
- // 3. Write something to |mp0|.
- const char kFoo[] = "FOO";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(mp0, kFoo, static_cast<uint32_t>(sizeof(kFoo)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // 4. Write a message to |server_mp|, attaching |mp1|.
- const char kBar[] = "Bar";
- EXPECT_EQ(
- MOJO_RESULT_OK,
- MojoWriteMessage(server_mp, kBar, static_cast<uint32_t>(sizeof(kBar)),
- &mp1, 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
- mp1 = MOJO_HANDLE_INVALID;
-
- // 5. Close |server_mp|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp));
-
- // 9. Read a message from |mp0|, which should have |mp2| attached.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp0, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- MojoHandle mp2 = MOJO_HANDLE_INVALID;
- uint32_t num_handles = 1;
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(mp0, buffer, &num_bytes, &mp2, &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kQuux[] = "quux";
- EXPECT_EQ(sizeof(kQuux), num_bytes);
- EXPECT_STREQ(kQuux, buffer);
- EXPECT_EQ(1u, num_handles);
- EXPECT_NE(mp2, MOJO_HANDLE_INVALID);
-
- // 7. Read a message from |mp2|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- state.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- state.satisfiable_signals);
-
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(mp2, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kBaz[] = "baz";
- EXPECT_EQ(sizeof(kBaz), num_bytes);
- EXPECT_STREQ(kBaz, buffer);
-
- // 10. Close |mp0|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp0));
-
-// 12. Wait on |mp2| (which should eventually fail) and then close it.
-// TODO(vtl): crbug.com/351768
-#if 0
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- &state));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals);
-#endif
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp2));
- }
-
- EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
- EXPECT_TRUE(test::Shutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) {
- ScopedPlatformHandle client_platform_handle =
- mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
- EXPECT_TRUE(client_platform_handle.is_valid());
-
- base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
- mojo::embedder::test::InitWithSimplePlatformSupport();
-
- {
- ScopedTestChannel client_channel(test_io_thread.task_runner(),
- client_platform_handle.Pass());
- MojoHandle client_mp = client_channel.bootstrap_message_pipe();
- EXPECT_NE(client_mp, MOJO_HANDLE_INVALID);
- client_channel.WaitForChannelCreationCompletion();
- CHECK(client_channel.channel_info() != nullptr);
-
- // 1. Read the first message from |client_mp|.
- MojoHandleSignalsState state;
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- char buffer[1000] = {};
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kHello[] = "hello";
- EXPECT_EQ(sizeof(kHello), num_bytes);
- EXPECT_STREQ(kHello, buffer);
-
- // 2. Write a message to |client_mp| (attaching nothing).
- const char kWorld[] = "world!";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(client_mp, kWorld,
- static_cast<uint32_t>(sizeof(kWorld)), nullptr,
- 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // 4. Read a message from |client_mp|, which should have |mp1| attached.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- // The other end of the handle may or may not be closed at this point, so we
- // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED.
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
- state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
- state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
- // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd
- // die (again due to |Channel::HandleLocalError()|).
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- MojoHandle mp1 = MOJO_HANDLE_INVALID;
- uint32_t num_handles = 1;
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kBar[] = "Bar";
- EXPECT_EQ(sizeof(kBar), num_bytes);
- EXPECT_STREQ(kBar, buffer);
- EXPECT_EQ(1u, num_handles);
- EXPECT_NE(mp1, MOJO_HANDLE_INVALID);
- // TODO(vtl): If the scope were to end here (and the two handles closed),
- // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling
- // write errors (assuming the parent had closed the pipe).
-
- // 6. Close |client_mp|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp));
-
- // Create a new message pipe (endpoints |mp2| and |mp3|).
- MojoHandle mp2, mp3;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3));
-
- // 7. Write a message to |mp3|.
- const char kBaz[] = "baz";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)),
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // 8. Close |mp3|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp3));
-
- // 9. Write a message to |mp1|, attaching |mp2|.
- const char kQuux[] = "quux";
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)),
- &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
- mp2 = MOJO_HANDLE_INVALID;
-
- // 3. Read a message from |mp1|.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals);
- EXPECT_EQ(kSignalAll, state.satisfiable_signals);
-
- memset(buffer, 0, sizeof(buffer));
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- const char kFoo[] = "FOO";
- EXPECT_EQ(sizeof(kFoo), num_bytes);
- EXPECT_STREQ(kFoo, buffer);
-
- // 11. Wait on |mp1| (which should eventually fail) and then close it.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp1));
- }
-
- EXPECT_TRUE(test::Shutdown());
-}
-
-// TODO(vtl): Test immediate write & close.
-// TODO(vtl): Test broken-connection cases.
-
-} // namespace
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc
deleted file mode 100644
index 9338cc7..0000000
--- a/mojo/edk/embedder/entrypoints.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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/embedder_internal.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/public/c/system/buffer.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/functions.h"
-#include "mojo/public/c/system/message_pipe.h"
-
-using mojo::embedder::internal::g_core;
-using mojo::system::MakeUserPointer;
-
-// Definitions of the system functions.
-extern "C" {
-MojoTimeTicks MojoGetTimeTicksNow() {
- return g_core->GetTimeTicksNow();
-}
-
-MojoResult MojoClose(MojoHandle handle) {
- return g_core->Close(handle);
-}
-
-MojoResult MojoWait(MojoHandle handle,
- MojoHandleSignals signals,
- MojoDeadline deadline,
- MojoHandleSignalsState* signals_state) {
- return g_core->Wait(handle, signals, deadline,
- MakeUserPointer(signals_state));
-}
-
-MojoResult MojoWaitMany(const MojoHandle* handles,
- const MojoHandleSignals* signals,
- uint32_t num_handles,
- MojoDeadline deadline,
- uint32_t* result_index,
- MojoHandleSignalsState* signals_states) {
- return g_core->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals),
- num_handles, deadline, MakeUserPointer(result_index),
- MakeUserPointer(signals_states));
-}
-
-MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
- MojoHandle* message_pipe_handle0,
- MojoHandle* message_pipe_handle1) {
- return g_core->CreateMessagePipe(MakeUserPointer(options),
- MakeUserPointer(message_pipe_handle0),
- MakeUserPointer(message_pipe_handle1));
-}
-
-MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
- const void* bytes,
- uint32_t num_bytes,
- const MojoHandle* handles,
- uint32_t num_handles,
- MojoWriteMessageFlags flags) {
- return g_core->WriteMessage(message_pipe_handle, MakeUserPointer(bytes),
- num_bytes, MakeUserPointer(handles), num_handles,
- flags);
-}
-
-MojoResult MojoReadMessage(MojoHandle message_pipe_handle,
- void* bytes,
- uint32_t* num_bytes,
- MojoHandle* handles,
- uint32_t* num_handles,
- MojoReadMessageFlags flags) {
- return g_core->ReadMessage(
- message_pipe_handle, MakeUserPointer(bytes), MakeUserPointer(num_bytes),
- MakeUserPointer(handles), MakeUserPointer(num_handles), flags);
-}
-
-MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options,
- MojoHandle* data_pipe_producer_handle,
- MojoHandle* data_pipe_consumer_handle) {
- return g_core->CreateDataPipe(MakeUserPointer(options),
- MakeUserPointer(data_pipe_producer_handle),
- MakeUserPointer(data_pipe_consumer_handle));
-}
-
-MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle,
- const void* elements,
- uint32_t* num_elements,
- MojoWriteDataFlags flags) {
- return g_core->WriteData(data_pipe_producer_handle, MakeUserPointer(elements),
- MakeUserPointer(num_elements), flags);
-}
-
-MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
- void** buffer,
- uint32_t* buffer_num_elements,
- MojoWriteDataFlags flags) {
- return g_core->BeginWriteData(data_pipe_producer_handle,
- MakeUserPointer(buffer),
- MakeUserPointer(buffer_num_elements), flags);
-}
-
-MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
- uint32_t num_elements_written) {
- return g_core->EndWriteData(data_pipe_producer_handle, num_elements_written);
-}
-
-MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle,
- void* elements,
- uint32_t* num_elements,
- MojoReadDataFlags flags) {
- return g_core->ReadData(data_pipe_consumer_handle, MakeUserPointer(elements),
- MakeUserPointer(num_elements), flags);
-}
-
-MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
- const void** buffer,
- uint32_t* buffer_num_elements,
- MojoReadDataFlags flags) {
- return g_core->BeginReadData(data_pipe_consumer_handle,
- MakeUserPointer(buffer),
- MakeUserPointer(buffer_num_elements), flags);
-}
-
-MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
- uint32_t num_elements_read) {
- return g_core->EndReadData(data_pipe_consumer_handle, num_elements_read);
-}
-
-MojoResult MojoCreateSharedBuffer(
- const struct MojoCreateSharedBufferOptions* options,
- uint64_t num_bytes,
- MojoHandle* shared_buffer_handle) {
- return g_core->CreateSharedBuffer(MakeUserPointer(options), num_bytes,
- MakeUserPointer(shared_buffer_handle));
-}
-
-MojoResult MojoDuplicateBufferHandle(
- MojoHandle buffer_handle,
- const struct MojoDuplicateBufferHandleOptions* options,
- MojoHandle* new_buffer_handle) {
- return g_core->DuplicateBufferHandle(buffer_handle, MakeUserPointer(options),
- MakeUserPointer(new_buffer_handle));
-}
-
-MojoResult MojoMapBuffer(MojoHandle buffer_handle,
- uint64_t offset,
- uint64_t num_bytes,
- void** buffer,
- MojoMapBufferFlags flags) {
- return g_core->MapBuffer(buffer_handle, offset, num_bytes,
- MakeUserPointer(buffer), flags);
-}
-
-MojoResult MojoUnmapBuffer(void* buffer) {
- return g_core->UnmapBuffer(MakeUserPointer(buffer));
-}
-
-} // extern "C"
diff --git a/mojo/edk/embedder/platform_channel_pair.cc b/mojo/edk/embedder/platform_channel_pair.cc
deleted file mode 100644
index 4e88bc9..0000000
--- a/mojo/edk/embedder/platform_channel_pair.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 "base/logging.h"
-
-namespace mojo {
-namespace embedder {
-
-const char PlatformChannelPair::kMojoPlatformChannelHandleSwitch[] =
- "mojo-platform-channel-handle";
-
-PlatformChannelPair::~PlatformChannelPair() {
-}
-
-ScopedPlatformHandle PlatformChannelPair::PassServerHandle() {
- return server_handle_.Pass();
-}
-
-ScopedPlatformHandle PlatformChannelPair::PassClientHandle() {
- return client_handle_.Pass();
-}
-
-void PlatformChannelPair::ChildProcessLaunched() {
- DCHECK(client_handle_.is_valid());
- client_handle_.reset();
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_channel_pair.h b/mojo/edk/embedder/platform_channel_pair.h
deleted file mode 100644
index d77c100..0000000
--- a/mojo/edk/embedder/platform_channel_pair.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/launch.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace base {
-class CommandLine;
-}
-
-namespace mojo {
-namespace embedder {
-
-// It would be nice to refactor base/process/launch.h to have a more platform-
-// independent way of representing handles that are passed to child processes.
-#if defined(OS_WIN)
-typedef base::HandlesToInheritVector HandlePassingInformation;
-#elif defined(OS_POSIX)
-typedef base::FileHandleMappingVector HandlePassingInformation;
-#else
-#error "Unsupported."
-#endif
-
-// This is used to create a pair of |PlatformHandle|s that are connected by a
-// suitable (platform-specific) bidirectional "pipe" (e.g., socket on POSIX,
-// named pipe on Windows). The resulting handles can then be used in the same
-// process (e.g., in tests) or between processes. (The "server" handle is the
-// one that will be used in the process that created the pair, whereas the
-// "client" handle is the one that will be used in a different process.)
-//
-// This class provides facilities for passing the client handle to a child
-// process. The parent should call |PrepareToPassClientHandlelToChildProcess()|
-// to get the data needed to do this, spawn the child using that data, and then
-// call |ChildProcessLaunched()|. Note that on Windows this facility (will) only
-// work on Vista and later (TODO(vtl)).
-//
-// Note: |PlatformChannelPair()|, |PassClientHandleFromParentProcess()| and
-// |PrepareToPassClientHandleToChildProcess()| have platform-specific
-// implementations.
-//
-// Note: On POSIX platforms, to write to the "pipe", use
-// |PlatformChannel{Write,Writev}()| (from platform_channel_utils_posix.h)
-// instead of |write()|, |writev()|, etc. Otherwise, you have to worry about
-// platform differences in suppressing |SIGPIPE|.
-class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair {
- public:
- PlatformChannelPair();
- ~PlatformChannelPair();
-
- ScopedPlatformHandle PassServerHandle();
-
- // For in-process use (e.g., in tests or to pass over another channel).
- ScopedPlatformHandle PassClientHandle();
-
- // To be called in the child process, after the parent process called
- // |PrepareToPassClientHandleToChildProcess()| and launched the child (using
- // the provided data), to create a client handle connected to the server
- // handle (in the parent process).
- static ScopedPlatformHandle PassClientHandleFromParentProcess(
- const base::CommandLine& command_line);
-
- // Prepares to pass the client channel to a new child process, to be launched
- // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and
- // |*handle_passing_info| as needed.
- // Note: For Windows, this method only works on Vista and later.
- void PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- HandlePassingInformation* handle_passing_info) const;
-
- // To be called once the child process has been successfully launched, to do
- // any cleanup necessary.
- void ChildProcessLaunched();
-
- private:
- static const char kMojoPlatformChannelHandleSwitch[];
-
- ScopedPlatformHandle server_handle_;
- ScopedPlatformHandle client_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformChannelPair);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
diff --git a/mojo/edk/embedder/platform_channel_pair_posix.cc b/mojo/edk/embedder/platform_channel_pair_posix.cc
deleted file mode 100644
index 2242cce..0000000
--- a/mojo/edk/embedder/platform_channel_pair_posix.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/posix/global_descriptors.h"
-#include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-namespace mojo {
-namespace embedder {
-
-namespace {
-
-bool IsTargetDescriptorUsed(
- const base::FileHandleMappingVector& file_handle_mapping,
- int target_fd) {
- for (size_t i = 0; i < file_handle_mapping.size(); i++) {
- if (file_handle_mapping[i].second == target_fd)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-PlatformChannelPair::PlatformChannelPair() {
- // Create the Unix domain socket and set the ends to nonblocking.
- int fds[2];
- // TODO(vtl): Maybe fail gracefully if |socketpair()| fails.
- PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
- PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
- PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
-
-#if defined(OS_MACOSX)
- // This turns off |SIGPIPE| when writing to a closed socket (causing it to
- // fail with |EPIPE| instead). On Linux, we have to use |send...()| with
- // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
- int no_sigpipe = 1;
- PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
- sizeof(no_sigpipe)) == 0);
- PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
- sizeof(no_sigpipe)) == 0);
-#endif // defined(OS_MACOSX)
-
- server_handle_.reset(PlatformHandle(fds[0]));
- DCHECK(server_handle_.is_valid());
- client_handle_.reset(PlatformHandle(fds[1]));
- DCHECK(client_handle_.is_valid());
-}
-
-// static
-ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- std::string client_fd_string =
- command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- int client_fd = -1;
- if (client_fd_string.empty() ||
- !base::StringToInt(client_fd_string, &client_fd) ||
- client_fd < base::GlobalDescriptors::kBaseDescriptor) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedPlatformHandle();
- }
-
- return ScopedPlatformHandle(PlatformHandle(client_fd));
-}
-
-void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- base::FileHandleMappingVector* handle_passing_info) const {
- DCHECK(command_line);
- DCHECK(handle_passing_info);
- // This is an arbitrary sanity check. (Note that this guarantees that the loop
- // below will terminate sanely.)
- CHECK_LT(handle_passing_info->size(), 1000u);
-
- DCHECK(client_handle_.is_valid());
-
- // Find a suitable FD to map our client handle to in the child process.
- // This has quadratic time complexity in the size of |*handle_passing_info|,
- // but |*handle_passing_info| should be very small (usually/often empty).
- int target_fd = base::GlobalDescriptors::kBaseDescriptor;
- while (IsTargetDescriptorUsed(*handle_passing_info, target_fd))
- target_fd++;
-
- handle_passing_info->push_back(
- std::pair<int, int>(client_handle_.get().fd, target_fd));
- // 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,
- base::IntToString(target_fd));
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
deleted file mode 100644
index 56540d7..0000000
--- a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-// 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 <errno.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include <deque>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace embedder {
-namespace {
-
-void WaitReadable(PlatformHandle h) {
- struct pollfd pfds = {};
- pfds.fd = h.fd;
- pfds.events = POLLIN;
- CHECK_EQ(poll(&pfds, 1, -1), 1);
-}
-
-class PlatformChannelPairPosixTest : public testing::Test {
- public:
- PlatformChannelPairPosixTest() {}
- ~PlatformChannelPairPosixTest() override {}
-
- void SetUp() override {
- // Make sure |SIGPIPE| isn't being ignored.
- struct sigaction action = {};
- action.sa_handler = SIG_DFL;
- ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_));
- }
-
- void TearDown() override {
- // Restore the |SIGPIPE| handler.
- ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, nullptr));
- }
-
- private:
- struct sigaction old_action_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest);
-};
-
-TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
- PlatformChannelPair channel_pair;
- ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
- ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
-
- // Write to the client.
- static const char kHello[] = "hello";
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- write(client_handle.get().fd, kHello, sizeof(kHello)));
-
- // Close the client.
- client_handle.reset();
-
- // Read from the server; this should be okay.
- char buffer[100] = {};
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- read(server_handle.get().fd, buffer, sizeof(buffer)));
- EXPECT_STREQ(kHello, buffer);
-
- // Try reading again.
- ssize_t result = read(server_handle.get().fd, buffer, sizeof(buffer));
- // We should probably get zero (for "end of file"), but -1 would also be okay.
- EXPECT_TRUE(result == 0 || result == -1);
- if (result == -1)
- PLOG(WARNING) << "read (expected 0 for EOF)";
-
- // Test our replacement for |write()|/|send()|.
- result = PlatformChannelWrite(server_handle.get(), kHello, sizeof(kHello));
- EXPECT_EQ(-1, result);
- if (errno != EPIPE)
- PLOG(WARNING) << "write (expected EPIPE)";
-
- // Test our replacement for |writev()|/|sendv()|.
- struct iovec iov[2] = {{const_cast<char*>(kHello), sizeof(kHello)},
- {const_cast<char*>(kHello), sizeof(kHello)}};
- result = PlatformChannelWritev(server_handle.get(), iov, 2);
- EXPECT_EQ(-1, result);
- if (errno != EPIPE)
- PLOG(WARNING) << "write (expected EPIPE)";
-}
-
-TEST_F(PlatformChannelPairPosixTest, SendReceiveData) {
- PlatformChannelPair channel_pair;
- ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
- ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
-
- for (size_t i = 0; i < 10; i++) {
- std::string send_string(1 << i, 'A' + i);
-
- EXPECT_EQ(static_cast<ssize_t>(send_string.size()),
- PlatformChannelWrite(server_handle.get(), send_string.data(),
- send_string.size()));
-
- WaitReadable(client_handle.get());
-
- char buf[10000] = {};
- std::deque<PlatformHandle> received_handles;
- ssize_t result = PlatformChannelRecvmsg(client_handle.get(), buf,
- sizeof(buf), &received_handles);
- EXPECT_EQ(static_cast<ssize_t>(send_string.size()), result);
- EXPECT_EQ(send_string, std::string(buf, static_cast<size_t>(result)));
- EXPECT_TRUE(received_handles.empty());
- }
-}
-
-TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHello[] = "hello";
-
- PlatformChannelPair channel_pair;
- ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
- ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
-
- for (size_t i = 1; i < kPlatformChannelMaxNumHandles; i++) {
- // Make |i| files, with the j-th file consisting of j copies of the digit
- // |c|.
- const char c = '0' + (i % 10);
- ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
- for (size_t j = 1; j <= i; j++) {
- base::FilePath unused;
- base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- ASSERT_TRUE(fp);
- ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get()));
- platform_handles->push_back(
- test::PlatformHandleFromFILE(fp.Pass()).release());
- ASSERT_TRUE(platform_handles->back().is_valid());
- }
-
- // Send the FDs (+ "hello").
- struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
- // We assume that the |sendmsg()| actually sends all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1,
- &platform_handles->at(0),
- platform_handles->size()));
-
- WaitReadable(client_handle.get());
-
- char buf[10000] = {};
- std::deque<PlatformHandle> received_handles;
- // We assume that the |recvmsg()| actually reads all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf),
- &received_handles));
- EXPECT_STREQ(kHello, buf);
- EXPECT_EQ(i, received_handles.size());
-
- for (size_t j = 0; !received_handles.empty(); j++) {
- base::ScopedFILE fp(test::FILEFromPlatformHandle(
- ScopedPlatformHandle(received_handles.front()), "rb"));
- received_handles.pop_front();
- ASSERT_TRUE(fp);
- rewind(fp.get());
- char read_buf[kPlatformChannelMaxNumHandles];
- size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get());
- EXPECT_EQ(j + 1, bytes_read);
- EXPECT_EQ(std::string(j + 1, c), std::string(read_buf, bytes_read));
- }
- }
-}
-
-TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHello[] = "hello";
-
- PlatformChannelPair channel_pair;
- ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
- ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
-
- const std::string file_contents("hello world");
-
- {
- base::FilePath unused;
- base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- ASSERT_TRUE(fp);
- ASSERT_EQ(file_contents.size(),
- fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
- ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
- platform_handles->push_back(
- test::PlatformHandleFromFILE(fp.Pass()).release());
- ASSERT_TRUE(platform_handles->back().is_valid());
-
- // Send the FD (+ "hello").
- struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
- // We assume that the |sendmsg()| actually sends all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1,
- &platform_handles->at(0),
- platform_handles->size()));
- }
-
- WaitReadable(client_handle.get());
-
- // Start with an invalid handle in the deque.
- std::deque<PlatformHandle> received_handles;
- received_handles.push_back(PlatformHandle());
-
- char buf[100] = {};
- // We assume that the |recvmsg()| actually reads all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf),
- &received_handles));
- EXPECT_STREQ(kHello, buf);
- ASSERT_EQ(2u, received_handles.size());
- EXPECT_FALSE(received_handles[0].is_valid());
- EXPECT_TRUE(received_handles[1].is_valid());
-
- {
- base::ScopedFILE fp(test::FILEFromPlatformHandle(
- ScopedPlatformHandle(received_handles[1]), "rb"));
- received_handles[1] = PlatformHandle();
- ASSERT_TRUE(fp);
- rewind(fp.get());
- char read_buf[100];
- size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get());
- EXPECT_EQ(file_contents.size(), bytes_read);
- EXPECT_EQ(file_contents, std::string(read_buf, bytes_read));
- }
-}
-
-} // namespace
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_channel_pair_win.cc b/mojo/edk/embedder/platform_channel_pair_win.cc
deleted file mode 100644
index 25306a6..0000000
--- a/mojo/edk/embedder/platform_channel_pair_win.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 <windows.h>
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/win/windows_version.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-namespace mojo {
-namespace embedder {
-
-namespace {
-
-std::wstring GeneratePipeName() {
- return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u",
- GetCurrentProcessId(), GetCurrentThreadId(),
- base::RandUint64());
-}
-
-} // namespace
-
-PlatformChannelPair::PlatformChannelPair() {
- std::wstring pipe_name = GeneratePipeName();
-
- const DWORD kOpenMode =
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
- const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;
- server_handle_.reset(PlatformHandle(
- CreateNamedPipeW(pipe_name.c_str(), kOpenMode, kPipeMode,
- 1, // Max instances.
- 4096, // Out buffer size.
- 4096, // In buffer size.
- 5000, // Timeout in milliseconds.
- nullptr))); // Default security descriptor.
- PCHECK(server_handle_.is_valid());
-
- const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
- // the client.
- const DWORD kFlags =
- SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
- // Allow the handle to be inherited by child processes.
- SECURITY_ATTRIBUTES security_attributes = {
- sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
- client_handle_.reset(
- PlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess,
- 0, // No sharing.
- &security_attributes, OPEN_EXISTING, kFlags,
- nullptr))); // No template file.
- PCHECK(client_handle_.is_valid());
-
- // Since a client has connected, ConnectNamedPipe() should return zero and
- // GetLastError() should return ERROR_PIPE_CONNECTED.
- CHECK(!ConnectNamedPipe(server_handle_.get().handle, nullptr));
- PCHECK(GetLastError() == ERROR_PIPE_CONNECTED);
-}
-
-// static
-ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- std::string client_handle_string =
- command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
-
- int client_handle_value = 0;
- if (client_handle_string.empty() ||
- !base::StringToInt(client_handle_string, &client_handle_value)) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedPlatformHandle();
- }
-
- return ScopedPlatformHandle(
- PlatformHandle(LongToHandle(client_handle_value)));
-}
-
-void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- base::HandlesToInheritVector* handle_passing_info) const {
- DCHECK(command_line);
- DCHECK(handle_passing_info);
- DCHECK(client_handle_.is_valid());
-
- CHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA);
-
- handle_passing_info->push_back(client_handle_.get().handle);
-
- // 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,
- base::IntToString(HandleToLong(client_handle_.get().handle)));
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_channel_utils_posix.cc b/mojo/edk/embedder/platform_channel_utils_posix.cc
deleted file mode 100644
index 61b573b..0000000
--- a/mojo/edk/embedder/platform_channel_utils_posix.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// 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_utils_posix.h"
-
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "build/build_config.h"
-
-namespace mojo {
-namespace embedder {
-
-// On Linux, |SIGPIPE| is suppressed by passing |MSG_NOSIGNAL| to
-// |send()|/|sendmsg()|. (There is no way of suppressing |SIGPIPE| on
-// |write()|/|writev().) On Mac, |SIGPIPE| is suppressed by setting the
-// |SO_NOSIGPIPE| option on the socket.
-//
-// Performance notes:
-// - On Linux, we have to use |send()|/|sendmsg()| rather than
-// |write()|/|writev()| in order to suppress |SIGPIPE|. This is okay, since
-// |send()| is (slightly) faster than |write()| (!), while |sendmsg()| is
-// quite comparable to |writev()|.
-// - On Mac, we may use |write()|/|writev()|. Here, |write()| is considerably
-// faster than |send()|, whereas |sendmsg()| is quite comparable to
-// |writev()|.
-// - On both platforms, an appropriate |sendmsg()|/|writev()| is considerably
-// faster than two |send()|s/|write()|s.
-// - Relative numbers (minimum real times from 10 runs) for one |write()| of
-// 1032 bytes, one |send()| of 1032 bytes, one |writev()| of 32+1000 bytes,
-// one |sendmsg()| of 32+1000 bytes, two |write()|s of 32 and 1000 bytes, two
-// |send()|s of 32 and 1000 bytes:
-// - Linux: 0.81 s, 0.77 s, 0.87 s, 0.89 s, 1.31 s, 1.22 s
-// - Mac: 2.21 s, 2.91 s, 2.98 s, 3.08 s, 3.59 s, 4.74 s
-
-// Flags to use with calling |send()| or |sendmsg()| (see above).
-#if defined(OS_MACOSX)
-const int kSendFlags = 0;
-#else
-const int kSendFlags = MSG_NOSIGNAL;
-#endif
-
-ssize_t PlatformChannelWrite(PlatformHandle h,
- const void* bytes,
- size_t num_bytes) {
- DCHECK(h.is_valid());
- DCHECK(bytes);
- DCHECK_GT(num_bytes, 0u);
-
-#if defined(OS_MACOSX)
- return HANDLE_EINTR(write(h.fd, bytes, num_bytes));
-#else
- return send(h.fd, bytes, num_bytes, kSendFlags);
-#endif
-}
-
-ssize_t PlatformChannelWritev(PlatformHandle h,
- struct iovec* iov,
- size_t num_iov) {
- DCHECK(h.is_valid());
- DCHECK(iov);
- DCHECK_GT(num_iov, 0u);
-
-#if defined(OS_MACOSX)
- return HANDLE_EINTR(writev(h.fd, iov, static_cast<int>(num_iov)));
-#else
- struct msghdr msg = {};
- msg.msg_iov = iov;
- msg.msg_iovlen = num_iov;
- return HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags));
-#endif
-}
-
-ssize_t PlatformChannelSendmsgWithHandles(PlatformHandle h,
- struct iovec* iov,
- size_t num_iov,
- PlatformHandle* platform_handles,
- size_t num_platform_handles) {
- DCHECK(iov);
- DCHECK_GT(num_iov, 0u);
- DCHECK(platform_handles);
- DCHECK_GT(num_platform_handles, 0u);
- DCHECK_LE(num_platform_handles, kPlatformChannelMaxNumHandles);
-
- char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
- struct msghdr msg = {};
- msg.msg_iov = iov;
- msg.msg_iovlen = num_iov;
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = CMSG_LEN(num_platform_handles * sizeof(int));
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(num_platform_handles * sizeof(int));
- for (size_t i = 0; i < num_platform_handles; i++) {
- DCHECK(platform_handles[i].is_valid());
- reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = platform_handles[i].fd;
- }
-
- return HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags));
-}
-
-bool PlatformChannelSendHandles(PlatformHandle h,
- PlatformHandle* handles,
- size_t num_handles) {
- DCHECK(handles);
- DCHECK_GT(num_handles, 0u);
- DCHECK_LE(num_handles, kPlatformChannelMaxNumHandles);
-
- // Note: |sendmsg()| fails on Mac if we don't write at least one character.
- struct iovec iov = {const_cast<char*>(""), 1};
- char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
- struct msghdr msg = {};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = CMSG_LEN(num_handles * sizeof(int));
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(num_handles * sizeof(int));
- for (size_t i = 0; i < num_handles; i++) {
- DCHECK(handles[i].is_valid());
- reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = handles[i].fd;
- }
-
- ssize_t result = HANDLE_EINTR(sendmsg(h.fd, &msg, kSendFlags));
- if (result < 1) {
- DCHECK_EQ(result, -1);
- return false;
- }
-
- for (size_t i = 0; i < num_handles; i++)
- handles[i].CloseIfNecessary();
- return true;
-}
-
-ssize_t PlatformChannelRecvmsg(PlatformHandle h,
- void* buf,
- size_t num_bytes,
- std::deque<PlatformHandle>* platform_handles) {
- DCHECK(buf);
- DCHECK_GT(num_bytes, 0u);
- DCHECK(platform_handles);
-
- struct iovec iov = {buf, num_bytes};
- char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
- struct msghdr msg = {};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = sizeof(cmsg_buf);
-
- ssize_t result = HANDLE_EINTR(recvmsg(h.fd, &msg, MSG_DONTWAIT));
- if (result < 0)
- return result;
-
- // Success; no control messages.
- if (msg.msg_controllen == 0)
- return result;
-
- DCHECK(!(msg.msg_flags & MSG_CTRUNC));
-
- for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- size_t payload_length = cmsg->cmsg_len - CMSG_LEN(0);
- DCHECK_EQ(payload_length % sizeof(int), 0u);
- size_t num_fds = payload_length / sizeof(int);
- const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
- for (size_t i = 0; i < num_fds; i++) {
- platform_handles->push_back(PlatformHandle(fds[i]));
- DCHECK(platform_handles->back().is_valid());
- }
- }
- }
-
- return result;
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_channel_utils_posix.h b/mojo/edk/embedder/platform_channel_utils_posix.h
deleted file mode 100644
index 34efcad..0000000
--- a/mojo/edk/embedder/platform_channel_utils_posix.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
-
-#include <stddef.h>
-#include <sys/types.h> // For |ssize_t|.
-
-#include <deque>
-
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-struct iovec; // Declared in <sys/uio.h>.
-
-namespace mojo {
-namespace embedder {
-
-// The maximum number of handles that can be sent "at once" using
-// |PlatformChannelSendmsgWithHandles()|.
-// TODO(vtl): This number is taken from ipc/file_descriptor_set_posix.h:
-// |FileDescriptorSet::kMaxDescriptorsPerMessage|. Where does it come from?
-const size_t kPlatformChannelMaxNumHandles = 7;
-
-// Use these to write to a socket created using |PlatformChannelPair| (or
-// equivalent). These are like |write()| and |writev()|, but handle |EINTR| and
-// never raise |SIGPIPE|. (Note: On Mac, the suppression of |SIGPIPE| is set up
-// by |PlatformChannelPair|.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelWrite(PlatformHandle h, const void* bytes, size_t num_bytes);
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov);
-
-// Writes data, and the given set of |PlatformHandle|s (i.e., file descriptors)
-// over the Unix domain socket given by |h| (e.g., created using
-// |PlatformChannelPair()|). All the handles must be valid, and there must be at
-// least one and at most |kPlatformChannelMaxNumHandles| handles. The return
-// value is as for |sendmsg()|, namely -1 on failure and otherwise the number of
-// bytes of data sent on success (note that this may not be all the data
-// specified by |iov|). (The handles are not closed, regardless of success or
-// failure.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelSendmsgWithHandles(PlatformHandle h,
- struct iovec* iov,
- size_t num_iov,
- PlatformHandle* platform_handles,
- size_t num_platform_handles);
-
-// TODO(vtl): Remove this once I've switched things over to
-// |PlatformChannelSendmsgWithHandles()|.
-// Sends |PlatformHandle|s (i.e., file descriptors) over the Unix domain socket
-// (e.g., created using PlatformChannelPair|). (These will be sent in a single
-// message having one null byte of data and one control message header with all
-// the file descriptors.) All of the handles must be valid, and there must be at
-// most |kPlatformChannelMaxNumHandles| (and at least one handle). Returns true
-// on success, in which case it closes all the handles.
-MOJO_SYSTEM_IMPL_EXPORT bool PlatformChannelSendHandles(PlatformHandle h,
- PlatformHandle* handles,
- size_t num_handles);
-
-// Wrapper around |recvmsg()|, which will extract any attached file descriptors
-// (in the control message) to |PlatformHandle|s (and append them to
-// |platform_handles|). (This also handles |EINTR|.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelRecvmsg(PlatformHandle h,
- void* buf,
- size_t num_bytes,
- std::deque<PlatformHandle>* platform_handles);
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
diff --git a/mojo/edk/embedder/platform_handle.cc b/mojo/edk/embedder/platform_handle.cc
deleted file mode 100644
index 4675714..0000000
--- a/mojo/edk/embedder/platform_handle.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 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_handle.h"
-
-#include "build/build_config.h"
-#if defined(OS_POSIX)
-#include <unistd.h>
-#elif defined(OS_WIN)
-#include <windows.h>
-#else
-#error "Platform not yet supported."
-#endif
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-
-namespace mojo {
-namespace embedder {
-
-void PlatformHandle::CloseIfNecessary() {
- if (!is_valid())
- return;
-
-#if defined(OS_POSIX)
- bool success = (close(fd) == 0);
- DPCHECK(success);
- fd = -1;
-#elif defined(OS_WIN)
- bool success = !!CloseHandle(handle);
- DPCHECK(success);
- handle = INVALID_HANDLE_VALUE;
-#else
-#error "Platform not yet supported."
-#endif
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_handle.h b/mojo/edk/embedder/platform_handle.h
deleted file mode 100644
index 346301a..0000000
--- a/mojo/edk/embedder/platform_handle.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 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_EDK_EMBEDDER_PLATFORM_HANDLE_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_
-
-#include "build/build_config.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace mojo {
-namespace embedder {
-
-#if defined(OS_POSIX)
-struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle {
- PlatformHandle() : fd(-1) {}
- explicit PlatformHandle(int fd) : fd(fd) {}
-
- void CloseIfNecessary();
-
- bool is_valid() const { return fd != -1; }
-
- int fd;
-};
-#elif defined(OS_WIN)
-struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle {
- PlatformHandle() : handle(INVALID_HANDLE_VALUE) {}
- explicit PlatformHandle(HANDLE handle) : handle(handle) {}
-
- void CloseIfNecessary();
-
- bool is_valid() const { return handle != INVALID_HANDLE_VALUE; }
-
- HANDLE handle;
-};
-#else
-#error "Platform not yet supported."
-#endif
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_
diff --git a/mojo/edk/embedder/platform_handle_utils.h b/mojo/edk/embedder/platform_handle_utils.h
deleted file mode 100644
index b3d7a79..0000000
--- a/mojo/edk/embedder/platform_handle_utils.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
-
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-// Closes all the |PlatformHandle|s in the given container.
-template <typename PlatformHandleContainer>
-MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllPlatformHandles(
- PlatformHandleContainer* platform_handles) {
- for (typename PlatformHandleContainer::iterator it =
- platform_handles->begin();
- it != platform_handles->end(); ++it)
- it->CloseIfNecessary();
-}
-
-// Duplicates the given |PlatformHandle| (which must be valid). (Returns an
-// invalid |ScopedPlatformHandle| on failure.)
-MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle
-DuplicatePlatformHandle(PlatformHandle platform_handle);
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
diff --git a/mojo/edk/embedder/platform_handle_utils_posix.cc b/mojo/edk/embedder/platform_handle_utils_posix.cc
deleted file mode 100644
index b3be93f..0000000
--- a/mojo/edk/embedder/platform_handle_utils_posix.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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_handle_utils.h"
-
-#include <unistd.h>
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace embedder {
-
-ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) {
- DCHECK(platform_handle.is_valid());
- // Note that |dup()| returns -1 on error (which is exactly the value we use
- // for invalid |PlatformHandle| FDs).
- return ScopedPlatformHandle(PlatformHandle(dup(platform_handle.fd)));
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_handle_utils_win.cc b/mojo/edk/embedder/platform_handle_utils_win.cc
deleted file mode 100644
index 43d1331..0000000
--- a/mojo/edk/embedder/platform_handle_utils_win.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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_handle_utils.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace embedder {
-
-ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) {
- DCHECK(platform_handle.is_valid());
-
- HANDLE new_handle;
- if (!DuplicateHandle(GetCurrentProcess(), platform_handle.handle,
- GetCurrentProcess(), &new_handle, 0, TRUE,
- DUPLICATE_SAME_ACCESS))
- return ScopedPlatformHandle();
- DCHECK_NE(new_handle, INVALID_HANDLE_VALUE);
- return ScopedPlatformHandle(PlatformHandle(new_handle));
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/platform_handle_vector.h b/mojo/edk/embedder/platform_handle_vector.h
deleted file mode 100644
index 96356b7..0000000
--- a/mojo/edk/embedder/platform_handle_vector.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
-
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-typedef std::vector<PlatformHandle> PlatformHandleVector;
-
-// A deleter (for use with |scoped_ptr|) which closes all handles and then
-// |delete|s the |PlatformHandleVector|.
-struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter {
- void operator()(PlatformHandleVector* platform_handles) const {
- CloseAllPlatformHandles(platform_handles);
- delete platform_handles;
- }
-};
-
-typedef scoped_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>
- ScopedPlatformHandleVectorPtr;
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
diff --git a/mojo/edk/embedder/platform_shared_buffer.h b/mojo/edk/embedder/platform_shared_buffer.h
deleted file mode 100644
index 07f8b90..0000000
--- a/mojo/edk/embedder/platform_shared_buffer.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-class PlatformSharedBufferMapping;
-
-// |PlatformSharedBuffer| is an interface for a thread-safe, ref-counted wrapper
-// around OS-specific shared memory. It has the following features:
-// - A |PlatformSharedBuffer| simply represents a piece of shared memory that
-// *may* be mapped and *may* be shared to another process.
-// - A single |PlatformSharedBuffer| may be mapped multiple times. The
-// lifetime of the mapping (owned by |PlatformSharedBufferMapping|) is
-// separate from the lifetime of the |PlatformSharedBuffer|.
-// - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not
-// restricted by page size. However, more memory may actually be mapped than
-// requested.
-//
-// It currently does NOT support the following:
-// - Sharing read-only. (This will probably eventually be supported.)
-//
-// TODO(vtl): Rectify this with |base::SharedMemory|.
-class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer
- : public base::RefCountedThreadSafe<PlatformSharedBuffer> {
- public:
- // Gets the size of shared buffer (in number of bytes).
- virtual size_t GetNumBytes() const = 0;
-
- // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|]
- // must be contained in [0, |num_bytes|], and |length| must be at least 1.
- // Returns null on failure.
- virtual scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset,
- size_t length) = 0;
-
- // Checks if |offset| and |length| are valid arguments.
- virtual bool IsValidMap(size_t offset, size_t length) = 0;
-
- // Like |Map()|, but doesn't check its arguments (which should have been
- // preflighted using |IsValidMap()|).
- virtual scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
- size_t length) = 0;
-
- // Duplicates the underlying platform handle and passes it to the caller.
- // TODO(vtl): On POSIX, we'll need two FDs to support sharing read-only.
- virtual ScopedPlatformHandle DuplicatePlatformHandle() = 0;
-
- // Passes the underlying platform handle to the caller. This should only be
- // called if there's a unique reference to this object (owned by the caller).
- // After calling this, this object should no longer be used, but should only
- // be disposed of.
- virtual ScopedPlatformHandle PassPlatformHandle() = 0;
-
- protected:
- friend class base::RefCountedThreadSafe<PlatformSharedBuffer>;
-
- PlatformSharedBuffer() {}
- virtual ~PlatformSharedBuffer() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer);
-};
-
-// An interface for a mapping of a |PlatformSharedBuffer| (compararable to a
-// "file view" in Windows); see above. Created by (implementations of)
-// |PlatformSharedBuffer::Map()|. Automatically unmaps memory on destruction.
-//
-// Mappings are NOT thread-safe.
-//
-// Note: This is an entirely separate class (instead of
-// |PlatformSharedBuffer::Mapping|) so that it can be forward-declared.
-class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping {
- public:
- // IMPORTANT: Implementations must implement a destructor that unmaps memory.
- virtual ~PlatformSharedBufferMapping() {}
-
- virtual void* GetBase() const = 0;
- virtual size_t GetLength() const = 0;
-
- protected:
- PlatformSharedBufferMapping() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PlatformSharedBufferMapping);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
diff --git a/mojo/edk/embedder/platform_support.h b/mojo/edk/embedder/platform_support.h
deleted file mode 100644
index 4556ee3..0000000
--- a/mojo/edk/embedder/platform_support.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-class PlatformSharedBuffer;
-
-// This class is provided by the embedder to implement (typically
-// platform-dependent) things needed by the Mojo system implementation.
-class MOJO_SYSTEM_IMPL_EXPORT PlatformSupport {
- public:
- virtual ~PlatformSupport() {}
-
- virtual PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) = 0;
- virtual PlatformSharedBuffer* CreateSharedBufferFromHandle(
- size_t num_bytes,
- ScopedPlatformHandle platform_handle) = 0;
-
- protected:
- PlatformSupport() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PlatformSupport);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_SUPPORT_H_
diff --git a/mojo/edk/embedder/scoped_platform_handle.h b/mojo/edk/embedder/scoped_platform_handle.h
deleted file mode 100644
index 2919b04..0000000
--- a/mojo/edk/embedder/scoped_platform_handle.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
-#define MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
-
-#include "base/compiler_specific.h"
-#include "base/move.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-class MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle {
- MOVE_ONLY_TYPE_FOR_CPP_03(ScopedPlatformHandle, RValue)
-
- public:
- ScopedPlatformHandle() {}
- explicit ScopedPlatformHandle(PlatformHandle handle) : handle_(handle) {}
- ~ScopedPlatformHandle() { handle_.CloseIfNecessary(); }
-
- // Move-only constructor and operator=.
- ScopedPlatformHandle(RValue other) : handle_(other.object->release()) {}
- ScopedPlatformHandle& operator=(RValue other) {
- handle_ = other.object->release();
- return *this;
- }
-
- const PlatformHandle& get() const { return handle_; }
-
- void swap(ScopedPlatformHandle& other) {
- PlatformHandle temp = handle_;
- handle_ = other.handle_;
- other.handle_ = temp;
- }
-
- PlatformHandle release() WARN_UNUSED_RESULT {
- PlatformHandle rv = handle_;
- handle_ = PlatformHandle();
- return rv;
- }
-
- void reset(PlatformHandle handle = PlatformHandle()) {
- handle_.CloseIfNecessary();
- handle_ = handle;
- }
-
- bool is_valid() const { return handle_.is_valid(); }
-
- private:
- PlatformHandle handle_;
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.cc b/mojo/edk/embedder/simple_platform_shared_buffer.cc
deleted file mode 100644
index 866250c..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// 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/simple_platform_shared_buffer.h"
-
-#include "base/logging.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-
-namespace mojo {
-namespace embedder {
-
-// static
-SimplePlatformSharedBuffer* SimplePlatformSharedBuffer::Create(
- size_t num_bytes) {
- DCHECK_GT(num_bytes, 0u);
-
- SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes);
- if (!rv->Init()) {
- // We can't just delete it directly, due to the "in destructor" (debug)
- // check.
- scoped_refptr<SimplePlatformSharedBuffer> deleter(rv);
- return nullptr;
- }
-
- return rv;
-}
-
-// static
-SimplePlatformSharedBuffer*
-SimplePlatformSharedBuffer::CreateFromPlatformHandle(
- size_t num_bytes,
- ScopedPlatformHandle platform_handle) {
- DCHECK_GT(num_bytes, 0u);
-
- SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes);
- if (!rv->InitFromPlatformHandle(platform_handle.Pass())) {
- // We can't just delete it directly, due to the "in destructor" (debug)
- // check.
- scoped_refptr<SimplePlatformSharedBuffer> deleter(rv);
- return nullptr;
- }
-
- return rv;
-}
-
-size_t SimplePlatformSharedBuffer::GetNumBytes() const {
- return num_bytes_;
-}
-
-scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::Map(
- size_t offset,
- size_t length) {
- if (!IsValidMap(offset, length))
- return nullptr;
-
- return MapNoCheck(offset, length);
-}
-
-bool SimplePlatformSharedBuffer::IsValidMap(size_t offset, size_t length) {
- if (offset > num_bytes_ || length == 0)
- return false;
-
- // Note: This is an overflow-safe check of |offset + length > num_bytes_|
- // (that |num_bytes >= offset| is verified above).
- if (length > num_bytes_ - offset)
- return false;
-
- return true;
-}
-
-scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapNoCheck(
- size_t offset,
- size_t length) {
- DCHECK(IsValidMap(offset, length));
- return MapImpl(offset, length);
-}
-
-ScopedPlatformHandle SimplePlatformSharedBuffer::DuplicatePlatformHandle() {
- return mojo::embedder::DuplicatePlatformHandle(handle_.get());
-}
-
-ScopedPlatformHandle SimplePlatformSharedBuffer::PassPlatformHandle() {
- DCHECK(HasOneRef());
- return handle_.Pass();
-}
-
-SimplePlatformSharedBuffer::SimplePlatformSharedBuffer(size_t num_bytes)
- : num_bytes_(num_bytes) {
-}
-
-SimplePlatformSharedBuffer::~SimplePlatformSharedBuffer() {
-}
-
-SimplePlatformSharedBufferMapping::~SimplePlatformSharedBufferMapping() {
- Unmap();
-}
-
-void* SimplePlatformSharedBufferMapping::GetBase() const {
- return base_;
-}
-
-size_t SimplePlatformSharedBufferMapping::GetLength() const {
- return length_;
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.h b/mojo/edk/embedder/simple_platform_shared_buffer.h
deleted file mode 100644
index b4958b9..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_
-#define MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-// A simple implementation of |PlatformSharedBuffer|.
-class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer
- : public PlatformSharedBuffer {
- public:
- // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled).
- // |num_bytes| must be nonzero. Returns null on failure.
- static SimplePlatformSharedBuffer* Create(size_t num_bytes);
-
- static SimplePlatformSharedBuffer* CreateFromPlatformHandle(
- size_t num_bytes,
- ScopedPlatformHandle platform_handle);
-
- // |PlatformSharedBuffer| implementation:
- size_t GetNumBytes() const override;
- scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset,
- size_t length) override;
- bool IsValidMap(size_t offset, size_t length) override;
- scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
- size_t length) override;
- ScopedPlatformHandle DuplicatePlatformHandle() override;
- ScopedPlatformHandle PassPlatformHandle() override;
-
- private:
- explicit SimplePlatformSharedBuffer(size_t num_bytes);
- ~SimplePlatformSharedBuffer() override;
-
- // Implemented in simple_platform_shared_buffer_{posix,win}.cc:
-
- // This is called by |Create()| before this object is given to anyone.
- bool Init();
-
- // This is like |Init()|, but for |CreateFromPlatformHandle()|. (Note: It
- // should verify that |platform_handle| is an appropriate handle for the
- // claimed |num_bytes_|.)
- bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle);
-
- // The platform-dependent part of |Map()|; doesn't check arguments.
- scoped_ptr<PlatformSharedBufferMapping> MapImpl(size_t offset, size_t length);
-
- const size_t num_bytes_;
-
- // This is set in |Init()|/|InitFromPlatformHandle()| and never modified
- // (except by |PassPlatformHandle()|; see the comments above its declaration),
- // hence does not need to be protected by a lock.
- ScopedPlatformHandle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(SimplePlatformSharedBuffer);
-};
-
-// An implementation of |PlatformSharedBufferMapping|, produced by
-// |SimplePlatformSharedBuffer|.
-class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBufferMapping
- : public PlatformSharedBufferMapping {
- public:
- ~SimplePlatformSharedBufferMapping() override;
-
- void* GetBase() const override;
- size_t GetLength() const override;
-
- private:
- friend class SimplePlatformSharedBuffer;
-
- SimplePlatformSharedBufferMapping(void* base,
- size_t length,
- void* real_base,
- size_t real_length)
- : base_(base),
- length_(length),
- real_base_(real_base),
- real_length_(real_length) {}
- void Unmap();
-
- void* const base_;
- const size_t length_;
-
- void* const real_base_;
- const size_t real_length_;
-
- DISALLOW_COPY_AND_ASSIGN(SimplePlatformSharedBufferMapping);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SHARED_BUFFER_H_
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_android.cc b/mojo/edk/embedder/simple_platform_shared_buffer_android.cc
deleted file mode 100644
index 3517db3..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer_android.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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/simple_platform_shared_buffer.h"
-
-#include <stdint.h>
-#include <sys/mman.h> // For |mmap()|/|munmap()|.
-#include <sys/types.h> // For |off_t|.
-#include <unistd.h>
-
-#include <limits>
-
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "third_party/ashmem/ashmem.h"
-
-namespace mojo {
-namespace embedder {
-
-// SimplePlatformSharedBuffer --------------------------------------------------
-
-bool SimplePlatformSharedBuffer::Init() {
- DCHECK(!handle_.is_valid());
-
- if (static_cast<uint64_t>(num_bytes_) >
- static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
- return false;
- }
-
- base::ScopedFD fd(ashmem_create_region(nullptr, num_bytes_));
- if (!fd.is_valid()) {
- DPLOG(ERROR) << "ashmem_create_region()";
- return false;
- }
-
- if (ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE) < 0) {
- DPLOG(ERROR) << "ashmem_set_prot_region()";
- return false;
- }
-
- handle_.reset(PlatformHandle(fd.release()));
- return true;
-}
-
-bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
- ScopedPlatformHandle platform_handle) {
- DCHECK(!handle_.is_valid());
-
- if (static_cast<uint64_t>(num_bytes_) >
- static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
- return false;
- }
-
- int size = ashmem_get_size_region(platform_handle.get().fd);
-
- if (size < 0) {
- DPLOG(ERROR) << "ashmem_get_size_region()";
- return false;
- }
-
- if (static_cast<size_t>(size) != num_bytes_) {
- LOG(ERROR) << "Shared memory region has the wrong size";
- return false;
- }
-
- handle_ = platform_handle.Pass();
- return true;
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc b/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc
deleted file mode 100644
index a3d10ef..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// 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/simple_platform_shared_buffer.h"
-
-#include <stdint.h>
-#include <stdio.h> // For |fileno()|.
-#include <sys/mman.h> // For |mmap()|/|munmap()|.
-#include <sys/stat.h>
-#include <sys/types.h> // For |off_t|.
-#include <unistd.h>
-
-#include <limits>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/sys_info.h"
-#include "base/threading/thread_restrictions.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-// We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
-// |uint64_t|.
-static_assert(sizeof(size_t) <= sizeof(uint64_t), "size_t too big");
-static_assert(sizeof(off_t) <= sizeof(uint64_t), "off_t too big");
-
-namespace mojo {
-namespace embedder {
-
-// SimplePlatformSharedBuffer --------------------------------------------------
-
-// The implementation for android uses ashmem to generate the file descriptor
-// for the shared memory. See simple_platform_shared_buffer_android.cc
-#if !defined(OS_ANDROID)
-
-bool SimplePlatformSharedBuffer::Init() {
- DCHECK(!handle_.is_valid());
-
- base::ThreadRestrictions::ScopedAllowIO allow_io;
-
- if (static_cast<uint64_t>(num_bytes_) >
- static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
- return false;
- }
-
- // TODO(vtl): This is stupid. The implementation of
- // |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
- // |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
- // can own. (base/memory/shared_memory_posix.cc does this too, with more
- // |fstat()|s thrown in for good measure.)
- base::FilePath shared_buffer_dir;
- if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
- LOG(ERROR) << "Failed to get temporary directory for shared memory";
- return false;
- }
- base::FilePath shared_buffer_file;
- base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
- shared_buffer_dir, &shared_buffer_file));
- if (!fp) {
- LOG(ERROR) << "Failed to create/open temporary file for shared memory";
- return false;
- }
- // Note: |unlink()| is not interruptible.
- if (unlink(shared_buffer_file.value().c_str()) != 0) {
- PLOG(WARNING) << "unlink";
- // This isn't "fatal" (e.g., someone else may have unlinked the file first),
- // so we may as well continue.
- }
-
- // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
- base::ScopedFD fd(dup(fileno(fp.get())));
- if (!fd.is_valid()) {
- PLOG(ERROR) << "dup";
- return false;
- }
-
- if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(num_bytes_))) != 0) {
- PLOG(ERROR) << "ftruncate";
- return false;
- }
-
- handle_.reset(PlatformHandle(fd.release()));
- return true;
-}
-
-bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
- ScopedPlatformHandle platform_handle) {
- DCHECK(!handle_.is_valid());
-
- if (static_cast<uint64_t>(num_bytes_) >
- static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
- return false;
- }
-
- struct stat sb = {};
- // Note: |fstat()| isn't interruptible.
- if (fstat(platform_handle.get().fd, &sb) != 0) {
- PLOG(ERROR) << "fstat";
- return false;
- }
-
- if (!S_ISREG(sb.st_mode)) {
- LOG(ERROR) << "Platform handle not to a regular file";
- return false;
- }
-
- if (sb.st_size != static_cast<off_t>(num_bytes_)) {
- LOG(ERROR) << "Shared memory file has the wrong size";
- return false;
- }
-
- // TODO(vtl): More checks?
-
- handle_ = platform_handle.Pass();
- return true;
-}
-
-#endif // !defined(OS_ANDROID)
-
-scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl(
- size_t offset,
- size_t length) {
- size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
- size_t real_offset = offset - offset_rounding;
- size_t real_length = length + offset_rounding;
-
- // This should hold (since we checked |num_bytes| versus the maximum value of
- // |off_t| on creation, but it never hurts to be paranoid.
- DCHECK_LE(static_cast<uint64_t>(real_offset),
- static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
-
- void* real_base =
- mmap(nullptr, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
- handle_.get().fd, static_cast<off_t>(real_offset));
- // |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
- // return null either.
- if (real_base == MAP_FAILED || !real_base) {
- PLOG(ERROR) << "mmap";
- return nullptr;
- }
-
- void* base = static_cast<char*>(real_base) + offset_rounding;
- return make_scoped_ptr(new SimplePlatformSharedBufferMapping(
- base, length, real_base, real_length));
-}
-
-// SimplePlatformSharedBufferMapping -------------------------------------------
-
-void SimplePlatformSharedBufferMapping::Unmap() {
- int result = munmap(real_base_, real_length_);
- PLOG_IF(ERROR, result != 0) << "munmap";
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc
deleted file mode 100644
index 4644b7b..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// 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/simple_platform_shared_buffer.h"
-
-#include <limits>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace embedder {
-namespace {
-
-TEST(SimplePlatformSharedBufferTest, Basic) {
- const size_t kNumInts = 100;
- const size_t kNumBytes = kNumInts * sizeof(int);
- // A fudge so that we're not just writing zero bytes 75% of the time.
- const int kFudge = 1234567890;
-
- // Make some memory.
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(kNumBytes));
- ASSERT_TRUE(buffer);
-
- // Map it all, scribble some stuff, and then unmap it.
- {
- EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes));
- scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kNumBytes));
- ASSERT_TRUE(mapping);
- ASSERT_TRUE(mapping->GetBase());
- int* stuff = static_cast<int*>(mapping->GetBase());
- for (size_t i = 0; i < kNumInts; i++)
- stuff[i] = static_cast<int>(i) + kFudge;
- }
-
- // Map it all again, check that our scribbling is still there, then do a
- // partial mapping and scribble on that, check that everything is coherent,
- // unmap the first mapping, scribble on some of the second mapping, and then
- // unmap it.
- {
- ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes));
- // Use |MapNoCheck()| this time.
- scoped_ptr<PlatformSharedBufferMapping> mapping1(
- buffer->MapNoCheck(0, kNumBytes));
- ASSERT_TRUE(mapping1);
- ASSERT_TRUE(mapping1->GetBase());
- int* stuff1 = static_cast<int*>(mapping1->GetBase());
- for (size_t i = 0; i < kNumInts; i++)
- EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i;
-
- scoped_ptr<PlatformSharedBufferMapping> mapping2(
- buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int)));
- ASSERT_TRUE(mapping2);
- ASSERT_TRUE(mapping2->GetBase());
- int* stuff2 = static_cast<int*>(mapping2->GetBase());
- EXPECT_EQ(static_cast<int>(kNumInts / 2) + kFudge, stuff2[0]);
- EXPECT_EQ(static_cast<int>(kNumInts / 2) + 1 + kFudge, stuff2[1]);
-
- stuff2[0] = 123;
- stuff2[1] = 456;
- EXPECT_EQ(123, stuff1[kNumInts / 2]);
- EXPECT_EQ(456, stuff1[kNumInts / 2 + 1]);
-
- mapping1.reset();
-
- EXPECT_EQ(123, stuff2[0]);
- EXPECT_EQ(456, stuff2[1]);
- stuff2[1] = 789;
- }
-
- // Do another partial mapping and check that everything is the way we expect
- // it to be.
- {
- EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int)));
- scoped_ptr<PlatformSharedBufferMapping> mapping(
- buffer->Map(sizeof(int), kNumBytes - sizeof(int)));
- ASSERT_TRUE(mapping);
- ASSERT_TRUE(mapping->GetBase());
- int* stuff = static_cast<int*>(mapping->GetBase());
-
- for (size_t j = 0; j < kNumInts - 1; j++) {
- int i = static_cast<int>(j) + 1;
- if (i == kNumInts / 2) {
- EXPECT_EQ(123, stuff[j]);
- } else if (i == kNumInts / 2 + 1) {
- EXPECT_EQ(789, stuff[j]);
- } else {
- EXPECT_EQ(i + kFudge, stuff[j]) << i;
- }
- }
- }
-}
-
-// TODO(vtl): Bigger buffers.
-
-TEST(SimplePlatformSharedBufferTest, InvalidMappings) {
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(100));
- ASSERT_TRUE(buffer);
-
- // Zero length not allowed.
- EXPECT_FALSE(buffer->Map(0, 0));
- EXPECT_FALSE(buffer->IsValidMap(0, 0));
-
- // Okay:
- EXPECT_TRUE(buffer->Map(0, 100));
- EXPECT_TRUE(buffer->IsValidMap(0, 100));
- // Offset + length too big.
- EXPECT_FALSE(buffer->Map(0, 101));
- EXPECT_FALSE(buffer->IsValidMap(0, 101));
- EXPECT_FALSE(buffer->Map(1, 100));
- EXPECT_FALSE(buffer->IsValidMap(1, 100));
-
- // Okay:
- EXPECT_TRUE(buffer->Map(50, 50));
- EXPECT_TRUE(buffer->IsValidMap(50, 50));
- // Offset + length too big.
- EXPECT_FALSE(buffer->Map(50, 51));
- EXPECT_FALSE(buffer->IsValidMap(50, 51));
- EXPECT_FALSE(buffer->Map(51, 50));
- EXPECT_FALSE(buffer->IsValidMap(51, 50));
-}
-
-TEST(SimplePlatformSharedBufferTest, TooBig) {
- // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds
- // (since it only involves creating a 4 GB file).
- const size_t kMaxSizeT = std::numeric_limits<size_t>::max();
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(kMaxSizeT));
- // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should
- // always fail.
- if (buffer)
- EXPECT_FALSE(buffer->Map(0, kMaxSizeT));
-}
-
-// Tests that separate mappings get distinct addresses.
-// Note: It's not inconceivable that the OS could ref-count identical mappings
-// and reuse the same address, in which case we'd have to be more careful about
-// using the address as the key for unmapping.
-TEST(SimplePlatformSharedBufferTest, MappingsDistinct) {
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(100));
- scoped_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100));
- scoped_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100));
- EXPECT_NE(mapping1->GetBase(), mapping2->GetBase());
-}
-
-TEST(SimplePlatformSharedBufferTest, BufferZeroInitialized) {
- static const size_t kSizes[] = {10, 100, 1000, 10000, 100000};
- for (size_t i = 0; i < arraysize(kSizes); i++) {
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(kSizes[i]));
- scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kSizes[i]));
- for (size_t j = 0; j < kSizes[i]; j++) {
- // "Assert" instead of "expect" so we don't spam the output with thousands
- // of failures if we fail.
- ASSERT_EQ('\0', static_cast<char*>(mapping->GetBase())[j])
- << "size " << kSizes[i] << ", offset " << j;
- }
- }
-}
-
-TEST(SimplePlatformSharedBufferTest, MappingsOutliveBuffer) {
- scoped_ptr<PlatformSharedBufferMapping> mapping1;
- scoped_ptr<PlatformSharedBufferMapping> mapping2;
-
- {
- scoped_refptr<SimplePlatformSharedBuffer> buffer(
- SimplePlatformSharedBuffer::Create(100));
- mapping1 = buffer->Map(0, 100).Pass();
- mapping2 = buffer->Map(50, 50).Pass();
- static_cast<char*>(mapping1->GetBase())[50] = 'x';
- }
-
- EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
-
- static_cast<char*>(mapping2->GetBase())[1] = 'y';
- EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
-}
-
-} // namespace
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_win.cc b/mojo/edk/embedder/simple_platform_shared_buffer_win.cc
deleted file mode 100644
index 0737465..0000000
--- a/mojo/edk/embedder/simple_platform_shared_buffer_win.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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/simple_platform_shared_buffer.h"
-
-#include <windows.h>
-
-#include <limits>
-
-#include "base/logging.h"
-#include "base/sys_info.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-
-namespace mojo {
-namespace embedder {
-
-// SimplePlatformSharedBuffer --------------------------------------------------
-
-bool SimplePlatformSharedBuffer::Init() {
- DCHECK(!handle_.is_valid());
-
- // TODO(vtl): Currently, we only support mapping up to 2^32-1 bytes.
- if (static_cast<uint64_t>(num_bytes_) >
- static_cast<uint64_t>(std::numeric_limits<DWORD>::max())) {
- return false;
- }
-
- // IMPORTANT NOTE: Unnamed objects are NOT SECURABLE. Thus if we ever want to
- // share read-only to other processes, we'll have to name our file mapping
- // object.
- // TODO(vtl): Unlike |base::SharedMemory|, we don't round up the size (to a
- // multiple of 64 KB). This may cause problems with NaCl. Cross this bridge
- // when we get there. crbug.com/210609
- handle_.reset(PlatformHandle(
- CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0,
- static_cast<DWORD>(num_bytes_), nullptr)));
- if (!handle_.is_valid()) {
- PLOG(ERROR) << "CreateFileMapping";
- return false;
- }
-
- return true;
-}
-
-bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
- ScopedPlatformHandle platform_handle) {
- DCHECK(!handle_.is_valid());
-
- // TODO(vtl): Implement.
- NOTIMPLEMENTED();
- return false;
-}
-
-scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl(
- size_t offset,
- size_t length) {
- size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
- size_t real_offset = offset - offset_rounding;
- size_t real_length = length + offset_rounding;
-
- // This should hold (since we checked |num_bytes| versus the maximum value of
- // |off_t| on creation, but it never hurts to be paranoid.
- DCHECK_LE(static_cast<uint64_t>(real_offset),
- static_cast<uint64_t>(std::numeric_limits<DWORD>::max()));
-
- void* real_base =
- MapViewOfFile(handle_.get().handle, FILE_MAP_READ | FILE_MAP_WRITE, 0,
- static_cast<DWORD>(real_offset), real_length);
- if (!real_base) {
- PLOG(ERROR) << "MapViewOfFile";
- return nullptr;
- }
-
- void* base = static_cast<char*>(real_base) + offset_rounding;
- return make_scoped_ptr(new SimplePlatformSharedBufferMapping(
- base, length, real_base, real_length));
-}
-
-// SimplePlatformSharedBufferMapping -------------------------------------------
-
-void SimplePlatformSharedBufferMapping::Unmap() {
- BOOL result = UnmapViewOfFile(real_base_);
- PLOG_IF(ERROR, !result) << "UnmapViewOfFile";
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_support.cc b/mojo/edk/embedder/simple_platform_support.cc
deleted file mode 100644
index c59cfb3..0000000
--- a/mojo/edk/embedder/simple_platform_support.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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/simple_platform_support.h"
-
-#include "mojo/edk/embedder/simple_platform_shared_buffer.h"
-
-namespace mojo {
-namespace embedder {
-
-PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBuffer(
- size_t num_bytes) {
- return SimplePlatformSharedBuffer::Create(num_bytes);
-}
-
-PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBufferFromHandle(
- size_t num_bytes,
- ScopedPlatformHandle platform_handle) {
- return SimplePlatformSharedBuffer::CreateFromPlatformHandle(
- num_bytes, platform_handle.Pass());
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/mojo/edk/embedder/simple_platform_support.h b/mojo/edk/embedder/simple_platform_support.h
deleted file mode 100644
index 2013f8d..0000000
--- a/mojo/edk/embedder/simple_platform_support.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_
-#define MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_support.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-
-// A simple implementation of |PlatformSupport|, when sandboxing and
-// multiprocess support are not issues (e.g., in most tests). Note: This class
-// has no state, and different instances of |SimplePlatformSupport| are mutually
-// compatible (i.e., you don't need to use a single instance of it everywhere --
-// you may simply create one whenever/wherever you need it).
-class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSupport : public PlatformSupport {
- public:
- SimplePlatformSupport() {}
- ~SimplePlatformSupport() override {}
-
- PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) override;
- PlatformSharedBuffer* CreateSharedBufferFromHandle(
- size_t num_bytes,
- ScopedPlatformHandle platform_handle) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SimplePlatformSupport);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_
diff --git a/mojo/edk/embedder/test_embedder.cc b/mojo/edk/embedder/test_embedder.cc
deleted file mode 100644
index defab41..0000000
--- a/mojo/edk/embedder/test_embedder.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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/test_embedder.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/channel_manager.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/handle_table.h"
-
-namespace mojo {
-
-namespace system {
-namespace internal {
-
-bool ShutdownCheckNoLeaks(Core* core) {
- // No point in taking the lock.
- const HandleTable::HandleToEntryMap& handle_to_entry_map =
- core->handle_table_.handle_to_entry_map_;
-
- if (handle_to_entry_map.empty())
- return true;
-
- for (HandleTable::HandleToEntryMap::const_iterator it =
- handle_to_entry_map.begin();
- it != handle_to_entry_map.end(); ++it) {
- LOG(ERROR) << "Mojo embedder shutdown: Leaking handle " << (*it).first;
- }
- return false;
-}
-
-} // namespace internal
-} // namespace system
-
-namespace embedder {
-namespace test {
-
-void InitWithSimplePlatformSupport() {
- Init(make_scoped_ptr(new SimplePlatformSupport()));
-}
-
-bool Shutdown() {
- CHECK(internal::g_channel_manager);
- delete internal::g_channel_manager;
- internal::g_channel_manager = nullptr;
-
- CHECK(internal::g_core);
- bool rv = system::internal::ShutdownCheckNoLeaks(internal::g_core);
- delete internal::g_core;
- internal::g_core = nullptr;
- return rv;
-}
-
-} // namespace test
-} // namespace embedder
-
-} // namespace mojo
diff --git a/mojo/edk/embedder/test_embedder.h b/mojo/edk/embedder/test_embedder.h
deleted file mode 100644
index 76917ee..0000000
--- a/mojo/edk/embedder/test_embedder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
-#define MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
-
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace embedder {
-namespace test {
-
-// Calls |Init()| with a |SimplePlatformSupport| (use this in tests if, e.g.,
-// you don't care about sandboxing, etc.).
-MOJO_SYSTEM_IMPL_EXPORT void InitWithSimplePlatformSupport();
-
-// This shuts down the global, singleton instance. (Note: "Real" embedders are
-// not expected to ever shut down this instance. This |Shutdown()| function will
-// do more work to ensure that tests don't leak, etc.) Returns true if there
-// were no problems, false if there were leaks -- i.e., handles still open -- or
-// any other problems.
-//
-// Note: It is up to the caller to ensure that there are not outstanding
-// callbacks from |CreateChannel()| before calling this.
-MOJO_SYSTEM_IMPL_EXPORT bool Shutdown();
-
-} // namespace test
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
diff --git a/mojo/edk/js/BUILD.gn b/mojo/edk/js/BUILD.gn
deleted file mode 100644
index 9a066d3..0000000
--- a/mojo/edk/js/BUILD.gn
+++ /dev/null
@@ -1,56 +0,0 @@
-# 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.
-
-import("../mojo_edk.gni")
-
-mojo_edk_source_set("js") {
- sources = [
- "core.cc",
- "core.h",
- "drain_data.cc",
- "drain_data.h",
- "handle.cc",
- "handle.h",
- "handle_close_observer.h",
- "mojo_runner_delegate.cc",
- "mojo_runner_delegate.h",
- "support.cc",
- "support.h",
- "threading.cc",
- "threading.h",
- "waiting_callback.cc",
- "waiting_callback.h",
- ]
-
- public_deps = [
- "//base",
- "//gin",
- "//v8",
- ]
-
- mojo_sdk_deps = [
- "mojo/public/cpp/environment",
- "mojo/public/cpp/system",
- ]
-}
-
-mojo_edk_source_set("js_unittests") {
- testonly = true
- sources = [
- "handle_unittest.cc",
- ]
-
- deps = [
- "//testing/gtest",
- ]
-
- mojo_edk_deps = [
- "mojo/edk/js",
- "mojo/edk/test:test_support",
- ]
-
- mojo_sdk_deps = [
- "mojo/public/cpp/system",
- ]
-}
diff --git a/mojo/edk/js/DEPS b/mojo/edk/js/DEPS
deleted file mode 100644
index c350edf..0000000
--- a/mojo/edk/js/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
- "+base",
- "+gin",
- "+v8",
-]
diff --git a/mojo/edk/js/core.cc b/mojo/edk/js/core.cc
deleted file mode 100644
index c06977d..0000000
--- a/mojo/edk/js/core.cc
+++ /dev/null
@@ -1,381 +0,0 @@
-// 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/js/core.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "gin/arguments.h"
-#include "gin/array_buffer.h"
-#include "gin/converter.h"
-#include "gin/dictionary.h"
-#include "gin/function_template.h"
-#include "gin/handle.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-#include "gin/wrappable.h"
-#include "mojo/edk/js/drain_data.h"
-#include "mojo/edk/js/handle.h"
-
-namespace mojo {
-namespace js {
-
-namespace {
-
-MojoResult CloseHandle(gin::Handle<HandleWrapper> handle) {
- if (!handle->get().is_valid())
- return MOJO_RESULT_INVALID_ARGUMENT;
- handle->Close();
- return MOJO_RESULT_OK;
-}
-
-gin::Dictionary WaitHandle(const gin::Arguments& args,
- mojo::Handle handle,
- MojoHandleSignals signals,
- MojoDeadline deadline) {
- v8::Isolate* isolate = args.isolate();
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate);
-
- MojoHandleSignalsState signals_state;
- MojoResult result = mojo::Wait(handle, signals, deadline, &signals_state);
- dictionary.Set("result", result);
-
- mojo::WaitManyResult wmv(result, 0);
- if (!wmv.AreSignalsStatesValid()) {
- dictionary.Set("signalsState", v8::Null(isolate).As<v8::Value>());
- } else {
- gin::Dictionary signalsStateDict = gin::Dictionary::CreateEmpty(isolate);
- signalsStateDict.Set("satisfiedSignals", signals_state.satisfied_signals);
- signalsStateDict.Set("satisfiableSignals",
- signals_state.satisfiable_signals);
- dictionary.Set("signalsState", signalsStateDict);
- }
-
- return dictionary;
-}
-
-gin::Dictionary WaitMany(const gin::Arguments& args,
- const std::vector<mojo::Handle>& handles,
- const std::vector<MojoHandleSignals>& signals,
- MojoDeadline deadline) {
- v8::Isolate* isolate = args.isolate();
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate);
-
- std::vector<MojoHandleSignalsState> signals_states(signals.size());
- mojo::WaitManyResult wmv =
- mojo::WaitMany(handles, signals, deadline, &signals_states);
- dictionary.Set("result", wmv.result);
- if (wmv.IsIndexValid()) {
- dictionary.Set("index", wmv.index);
- } else {
- dictionary.Set("index", v8::Null(isolate).As<v8::Value>());
- }
- if (wmv.AreSignalsStatesValid()) {
- std::vector<gin::Dictionary> vec;
- for (size_t i = 0; i < handles.size(); ++i) {
- gin::Dictionary signalsStateDict = gin::Dictionary::CreateEmpty(isolate);
- signalsStateDict.Set("satisfiedSignals",
- signals_states[i].satisfied_signals);
- signalsStateDict.Set("satisfiableSignals",
- signals_states[i].satisfiable_signals);
- vec.push_back(signalsStateDict);
- }
- dictionary.Set("signalsState", vec);
- } else {
- dictionary.Set("signalsState", v8::Null(isolate).As<v8::Value>());
- }
-
- return dictionary;
-}
-
-gin::Dictionary CreateMessagePipe(const gin::Arguments& args) {
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT);
-
- MojoHandle handle0 = MOJO_HANDLE_INVALID;
- MojoHandle handle1 = MOJO_HANDLE_INVALID;
- MojoResult result = MOJO_RESULT_OK;
-
- v8::Handle<v8::Value> options_value = args.PeekNext();
- if (options_value.IsEmpty() || options_value->IsNull() ||
- options_value->IsUndefined()) {
- result = MojoCreateMessagePipe(NULL, &handle0, &handle1);
- } else if (options_value->IsObject()) {
- gin::Dictionary options_dict(args.isolate(), options_value->ToObject());
- MojoCreateMessagePipeOptions options;
- // For future struct_size, we can probably infer that from the presence of
- // properties in options_dict. For now, it's always 8.
- options.struct_size = 8;
- // Ideally these would be optional. But the interface makes it hard to
- // typecheck them then.
- if (!options_dict.Get("flags", &options.flags)) {
- return dictionary;
- }
-
- result = MojoCreateMessagePipe(&options, &handle0, &handle1);
- } else {
- return dictionary;
- }
-
- CHECK_EQ(MOJO_RESULT_OK, result);
-
- dictionary.Set("result", result);
- dictionary.Set("handle0", mojo::Handle(handle0));
- dictionary.Set("handle1", mojo::Handle(handle1));
- return dictionary;
-}
-
-MojoResult WriteMessage(
- mojo::Handle handle,
- const gin::ArrayBufferView& buffer,
- const std::vector<gin::Handle<HandleWrapper> >& handles,
- MojoWriteMessageFlags flags) {
- std::vector<MojoHandle> raw_handles(handles.size());
- for (size_t i = 0; i < handles.size(); ++i)
- raw_handles[i] = handles[i]->get().value();
- MojoResult rv = MojoWriteMessage(handle.value(),
- buffer.bytes(),
- static_cast<uint32_t>(buffer.num_bytes()),
- raw_handles.empty() ? NULL : &raw_handles[0],
- static_cast<uint32_t>(raw_handles.size()),
- flags);
- // MojoWriteMessage takes ownership of the handles upon success, so
- // release them here.
- if (rv == MOJO_RESULT_OK) {
- for (size_t i = 0; i < handles.size(); ++i)
- ignore_result(handles[i]->release());
- }
- return rv;
-}
-
-gin::Dictionary ReadMessage(const gin::Arguments& args,
- mojo::Handle handle,
- MojoReadMessageFlags flags) {
- uint32_t num_bytes = 0;
- uint32_t num_handles = 0;
- MojoResult result = MojoReadMessage(
- handle.value(), NULL, &num_bytes, NULL, &num_handles, flags);
- if (result != MOJO_RESULT_RESOURCE_EXHAUSTED) {
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", result);
- return dictionary;
- }
-
- v8::Handle<v8::ArrayBuffer> array_buffer =
- v8::ArrayBuffer::New(args.isolate(), num_bytes);
- std::vector<mojo::Handle> handles(num_handles);
-
- gin::ArrayBuffer buffer;
- ConvertFromV8(args.isolate(), array_buffer, &buffer);
- CHECK(buffer.num_bytes() == num_bytes);
-
- result = MojoReadMessage(handle.value(),
- buffer.bytes(),
- &num_bytes,
- handles.empty() ? NULL :
- reinterpret_cast<MojoHandle*>(&handles[0]),
- &num_handles,
- flags);
-
- CHECK(buffer.num_bytes() == num_bytes);
- CHECK(handles.size() == num_handles);
-
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", result);
- dictionary.Set("buffer", array_buffer);
- dictionary.Set("handles", handles);
- return dictionary;
-}
-
-gin::Dictionary CreateDataPipe(const gin::Arguments& args) {
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT);
-
- MojoHandle producer_handle = MOJO_HANDLE_INVALID;
- MojoHandle consumer_handle = MOJO_HANDLE_INVALID;
- MojoResult result = MOJO_RESULT_OK;
-
- v8::Handle<v8::Value> options_value = args.PeekNext();
- if (options_value.IsEmpty() || options_value->IsNull() ||
- options_value->IsUndefined()) {
- result = MojoCreateDataPipe(NULL, &producer_handle, &consumer_handle);
- } else if (options_value->IsObject()) {
- gin::Dictionary options_dict(args.isolate(), options_value->ToObject());
- MojoCreateDataPipeOptions options;
- // For future struct_size, we can probably infer that from the presence of
- // properties in options_dict. For now, it's always 16.
- options.struct_size = 16;
- // Ideally these would be optional. But the interface makes it hard to
- // typecheck them then.
- if (!options_dict.Get("flags", &options.flags) ||
- !options_dict.Get("elementNumBytes", &options.element_num_bytes) ||
- !options_dict.Get("capacityNumBytes", &options.capacity_num_bytes)) {
- return dictionary;
- }
-
- result = MojoCreateDataPipe(&options, &producer_handle, &consumer_handle);
- } else {
- return dictionary;
- }
-
- CHECK_EQ(MOJO_RESULT_OK, result);
-
- dictionary.Set("result", result);
- dictionary.Set("producerHandle", mojo::Handle(producer_handle));
- dictionary.Set("consumerHandle", mojo::Handle(consumer_handle));
- return dictionary;
-}
-
-gin::Dictionary WriteData(const gin::Arguments& args,
- mojo::Handle handle,
- const gin::ArrayBufferView& buffer,
- MojoWriteDataFlags flags) {
- uint32_t num_bytes = static_cast<uint32_t>(buffer.num_bytes());
- MojoResult result =
- MojoWriteData(handle.value(), buffer.bytes(), &num_bytes, flags);
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", result);
- dictionary.Set("numBytes", num_bytes);
- return dictionary;
-}
-
-gin::Dictionary ReadData(const gin::Arguments& args,
- mojo::Handle handle,
- MojoReadDataFlags flags) {
- uint32_t num_bytes = 0;
- MojoResult result = MojoReadData(
- handle.value(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY);
- if (result != MOJO_RESULT_OK) {
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", result);
- return dictionary;
- }
-
- v8::Handle<v8::ArrayBuffer> array_buffer =
- v8::ArrayBuffer::New(args.isolate(), num_bytes);
- gin::ArrayBuffer buffer;
- ConvertFromV8(args.isolate(), array_buffer, &buffer);
- CHECK_EQ(num_bytes, buffer.num_bytes());
-
- result = MojoReadData(handle.value(), buffer.bytes(), &num_bytes, flags);
- CHECK_EQ(num_bytes, buffer.num_bytes());
-
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
- dictionary.Set("result", result);
- dictionary.Set("buffer", array_buffer);
- return dictionary;
-}
-
-// Asynchronously read all of the data available for the specified data pipe
-// consumer handle until the remote handle is closed or an error occurs. A
-// Promise is returned whose settled value is an object like this:
-// {result: core.RESULT_OK, buffer: dataArrayBuffer}. If the read failed,
-// then the Promise is rejected, the result will be the actual error code,
-// and the buffer will contain whatever was read before the error occurred.
-// The drainData data pipe handle argument is closed automatically.
-
-v8::Handle<v8::Value> DoDrainData(gin::Arguments* args,
- gin::Handle<HandleWrapper> handle) {
- return (new DrainData(args->isolate(), handle->release()))->GetPromise();
-}
-
-bool IsHandle(gin::Arguments* args, v8::Handle<v8::Value> val) {
- gin::Handle<mojo::js::HandleWrapper> ignore_handle;
- return gin::Converter<gin::Handle<mojo::js::HandleWrapper>>::FromV8(
- args->isolate(), val, &ignore_handle);
-}
-
-
-gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
-
-} // namespace
-
-const char Core::kModuleName[] = "mojo/public/js/core";
-
-v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) {
- gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
- v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(
- &g_wrapper_info);
-
- if (templ.IsEmpty()) {
- templ =
- gin::ObjectTemplateBuilder(isolate)
- // TODO(mpcomplete): Should these just be methods on the JS Handle
- // object?
- .SetMethod("close", CloseHandle)
- .SetMethod("wait", WaitHandle)
- .SetMethod("waitMany", WaitMany)
- .SetMethod("createMessagePipe", CreateMessagePipe)
- .SetMethod("writeMessage", WriteMessage)
- .SetMethod("readMessage", ReadMessage)
- .SetMethod("createDataPipe", CreateDataPipe)
- .SetMethod("writeData", WriteData)
- .SetMethod("readData", ReadData)
- .SetMethod("drainData", DoDrainData)
- .SetMethod("isHandle", IsHandle)
-
- .SetValue("RESULT_OK", MOJO_RESULT_OK)
- .SetValue("RESULT_CANCELLED", MOJO_RESULT_CANCELLED)
- .SetValue("RESULT_UNKNOWN", MOJO_RESULT_UNKNOWN)
- .SetValue("RESULT_INVALID_ARGUMENT", MOJO_RESULT_INVALID_ARGUMENT)
- .SetValue("RESULT_DEADLINE_EXCEEDED", MOJO_RESULT_DEADLINE_EXCEEDED)
- .SetValue("RESULT_NOT_FOUND", MOJO_RESULT_NOT_FOUND)
- .SetValue("RESULT_ALREADY_EXISTS", MOJO_RESULT_ALREADY_EXISTS)
- .SetValue("RESULT_PERMISSION_DENIED", MOJO_RESULT_PERMISSION_DENIED)
- .SetValue("RESULT_RESOURCE_EXHAUSTED",
- MOJO_RESULT_RESOURCE_EXHAUSTED)
- .SetValue("RESULT_FAILED_PRECONDITION",
- MOJO_RESULT_FAILED_PRECONDITION)
- .SetValue("RESULT_ABORTED", MOJO_RESULT_ABORTED)
- .SetValue("RESULT_OUT_OF_RANGE", MOJO_RESULT_OUT_OF_RANGE)
- .SetValue("RESULT_UNIMPLEMENTED", MOJO_RESULT_UNIMPLEMENTED)
- .SetValue("RESULT_INTERNAL", MOJO_RESULT_INTERNAL)
- .SetValue("RESULT_UNAVAILABLE", MOJO_RESULT_UNAVAILABLE)
- .SetValue("RESULT_DATA_LOSS", MOJO_RESULT_DATA_LOSS)
- .SetValue("RESULT_BUSY", MOJO_RESULT_BUSY)
- .SetValue("RESULT_SHOULD_WAIT", MOJO_RESULT_SHOULD_WAIT)
-
- .SetValue("DEADLINE_INDEFINITE", MOJO_DEADLINE_INDEFINITE)
-
- .SetValue("HANDLE_SIGNAL_NONE", MOJO_HANDLE_SIGNAL_NONE)
- .SetValue("HANDLE_SIGNAL_READABLE", MOJO_HANDLE_SIGNAL_READABLE)
- .SetValue("HANDLE_SIGNAL_WRITABLE", MOJO_HANDLE_SIGNAL_WRITABLE)
- .SetValue("HANDLE_SIGNAL_PEER_CLOSED",
- MOJO_HANDLE_SIGNAL_PEER_CLOSED)
-
- .SetValue("CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE",
- MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE)
-
- .SetValue("WRITE_MESSAGE_FLAG_NONE", MOJO_WRITE_MESSAGE_FLAG_NONE)
-
- .SetValue("READ_MESSAGE_FLAG_NONE", MOJO_READ_MESSAGE_FLAG_NONE)
- .SetValue("READ_MESSAGE_FLAG_MAY_DISCARD",
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)
-
- .SetValue("CREATE_DATA_PIPE_OPTIONS_FLAG_NONE",
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE)
- .SetValue("CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD",
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)
-
- .SetValue("WRITE_DATA_FLAG_NONE", MOJO_WRITE_DATA_FLAG_NONE)
- .SetValue("WRITE_DATA_FLAG_ALL_OR_NONE",
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)
-
- .SetValue("READ_DATA_FLAG_NONE", MOJO_READ_DATA_FLAG_NONE)
- .SetValue("READ_DATA_FLAG_ALL_OR_NONE",
- MOJO_READ_DATA_FLAG_ALL_OR_NONE)
- .SetValue("READ_DATA_FLAG_DISCARD", MOJO_READ_DATA_FLAG_DISCARD)
- .SetValue("READ_DATA_FLAG_QUERY", MOJO_READ_DATA_FLAG_QUERY)
- .SetValue("READ_DATA_FLAG_PEEK", MOJO_READ_DATA_FLAG_PEEK)
- .Build();
-
- data->SetObjectTemplate(&g_wrapper_info, templ);
- }
-
- return templ->NewInstance();
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/core.h b/mojo/edk/js/core.h
deleted file mode 100644
index 445fb00..0000000
--- a/mojo/edk/js/core.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_CORE_H_
-#define MOJO_EDK_JS_CORE_H_
-
-#include "v8/include/v8.h"
-
-namespace mojo {
-namespace js {
-
-class Core {
- public:
- static const char kModuleName[];
- static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_CORE_H_
diff --git a/mojo/edk/js/drain_data.cc b/mojo/edk/js/drain_data.cc
deleted file mode 100644
index 0667c64..0000000
--- a/mojo/edk/js/drain_data.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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/js/drain_data.h"
-
-#include "gin/array_buffer.h"
-#include "gin/converter.h"
-#include "gin/dictionary.h"
-#include "gin/per_context_data.h"
-#include "gin/per_isolate_data.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace js {
-
-DrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle)
- : isolate_(isolate),
- handle_(DataPipeConsumerHandle(handle.value())),
- wait_id_(0) {
-
- v8::Handle<v8::Context> context(isolate_->GetCurrentContext());
- runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
-
- WaitForData();
-}
-
-v8::Handle<v8::Value> DrainData::GetPromise() {
- CHECK(resolver_.IsEmpty());
- v8::Handle<v8::Promise::Resolver> resolver(
- v8::Promise::Resolver::New(isolate_));
- resolver_.Reset(isolate_, resolver);
- return resolver->GetPromise();
-}
-
-DrainData::~DrainData() {
- if (wait_id_)
- Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
- resolver_.Reset();
-}
-
-void DrainData::WaitForData() {
- wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait(
- handle_.get().value(),
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- &DrainData::WaitCompleted,
- this);
-}
-
-void DrainData::DataReady(MojoResult result) {
- wait_id_ = 0;
- if (result != MOJO_RESULT_OK) {
- DeliverData(result);
- return;
- }
- while (result == MOJO_RESULT_OK) {
- result = ReadData();
- if (result == MOJO_RESULT_SHOULD_WAIT)
- WaitForData();
- else if (result != MOJO_RESULT_OK)
- DeliverData(result);
- }
-}
-
-MojoResult DrainData::ReadData() {
- const void* buffer;
- uint32_t num_bytes = 0;
- MojoResult result = BeginReadDataRaw(
- handle_.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
- if (result != MOJO_RESULT_OK)
- return result;
- const char* p = static_cast<const char*>(buffer);
- DataBuffer* data_buffer = new DataBuffer(p, p + num_bytes);
- data_buffers_.push_back(data_buffer);
- return EndReadDataRaw(handle_.get(), num_bytes);
-}
-
-void DrainData::DeliverData(MojoResult result) {
- if (!runner_) {
- delete this;
- return;
- }
-
- size_t total_bytes = 0;
- for (unsigned i = 0; i < data_buffers_.size(); i++)
- total_bytes += data_buffers_[i]->size();
-
- // Create a total_bytes length ArrayBuffer return value.
- gin::Runner::Scope scope(runner_.get());
- v8::Handle<v8::ArrayBuffer> array_buffer =
- v8::ArrayBuffer::New(isolate_, total_bytes);
- gin::ArrayBuffer buffer;
- ConvertFromV8(isolate_, array_buffer, &buffer);
- CHECK_EQ(total_bytes, buffer.num_bytes());
-
- // Copy the data_buffers into the ArrayBuffer.
- char* array_buffer_ptr = static_cast<char*>(buffer.bytes());
- size_t offset = 0;
- for (size_t i = 0; i < data_buffers_.size(); i++) {
- size_t num_bytes = data_buffers_[i]->size();
- if (num_bytes == 0)
- continue;
- const char* data_buffer_ptr = &((*data_buffers_[i])[0]);
- memcpy(array_buffer_ptr + offset, data_buffer_ptr, num_bytes);
- offset += num_bytes;
- }
-
- // The "settled" value of the promise always includes all of the data
- // that was read before either an error occurred or the remote pipe handle
- // was closed. The latter is indicated by MOJO_RESULT_FAILED_PRECONDITION.
-
- v8::Handle<v8::Promise::Resolver> resolver(
- v8::Local<v8::Promise::Resolver>::New(isolate_, resolver_));
-
- gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate_);
- dictionary.Set("result", result);
- dictionary.Set("buffer", array_buffer);
- v8::Handle<v8::Value> settled_value(ConvertToV8(isolate_, dictionary));
-
- if (result == MOJO_RESULT_FAILED_PRECONDITION)
- resolver->Resolve(settled_value);
- else
- resolver->Reject(settled_value);
-
- delete this;
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/drain_data.h b/mojo/edk/js/drain_data.h
deleted file mode 100644
index 48f1de2..0000000
--- a/mojo/edk/js/drain_data.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_DRAIN_DATA_H_
-#define MOJO_EDK_JS_DRAIN_DATA_H_
-
-#include "base/memory/scoped_vector.h"
-#include "gin/runner.h"
-#include "mojo/public/c/environment/async_waiter.h"
-#include "mojo/public/cpp/system/core.h"
-#include "v8/include/v8.h"
-
-namespace mojo {
-namespace js {
-
-// This class is the implementation of the Mojo JavaScript core module's
-// drainData() method. It is not intended to be used directly. The caller
-// allocates a DrainData on the heap and returns GetPromise() to JS. The
-// implementation deletes itself after reading as much data as possible
-// and rejecting or resolving the Promise.
-
-class DrainData {
- public:
- // Starts waiting for data on the specified data pipe consumer handle.
- // See WaitForData(). The constructor does not block.
- DrainData(v8::Isolate* isolate, mojo::Handle handle);
-
- // Returns a Promise that will be settled when no more data can be read.
- // Should be called just once on a newly allocated DrainData object.
- v8::Handle<v8::Value> GetPromise();
-
- private:
- ~DrainData();
-
- // Registers an "async waiter" that calls DataReady() via WaitCompleted().
- void WaitForData();
- static void WaitCompleted(void* self, MojoResult result) {
- static_cast<DrainData*>(self)->DataReady(result);
- }
-
- // Use ReadData() to read whatever is availble now on handle_ and save
- // it in data_buffers_.
- void DataReady(MojoResult result);
- MojoResult ReadData();
-
- // When the remote data pipe handle is closed, or an error occurs, deliver
- // all of the buffered data to the JS Promise and then delete this.
- void DeliverData(MojoResult result);
-
- typedef std::vector<char> DataBuffer;
-
- v8::Isolate* isolate_;
- ScopedDataPipeConsumerHandle handle_;
- MojoAsyncWaitID wait_id_;
- base::WeakPtr<gin::Runner> runner_;
- v8::UniquePersistent<v8::Promise::Resolver> resolver_;
- ScopedVector<DataBuffer> data_buffers_;
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_DRAIN_DATA_H_
diff --git a/mojo/edk/js/handle.cc b/mojo/edk/js/handle.cc
deleted file mode 100644
index de8f338..0000000
--- a/mojo/edk/js/handle.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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/js/handle.h"
-
-#include "mojo/edk/js/handle_close_observer.h"
-
-namespace mojo {
-namespace js {
-
-gin::WrapperInfo HandleWrapper::kWrapperInfo = { gin::kEmbedderNativeGin };
-
-HandleWrapper::HandleWrapper(MojoHandle handle)
- : handle_(mojo::Handle(handle)) {
-}
-
-HandleWrapper::~HandleWrapper() {
- NotifyCloseObservers();
-}
-
-void HandleWrapper::Close() {
- NotifyCloseObservers();
- handle_.reset();
-}
-
-void HandleWrapper::AddCloseObserver(HandleCloseObserver* observer) {
- close_observers_.AddObserver(observer);
-}
-
-void HandleWrapper::RemoveCloseObserver(HandleCloseObserver* observer) {
- close_observers_.RemoveObserver(observer);
-}
-
-void HandleWrapper::NotifyCloseObservers() {
- if (!handle_.is_valid())
- return;
-
- FOR_EACH_OBSERVER(HandleCloseObserver, close_observers_, OnWillCloseHandle());
-}
-
-} // namespace js
-} // namespace mojo
-
-namespace gin {
-
-v8::Handle<v8::Value> Converter<mojo::Handle>::ToV8(v8::Isolate* isolate,
- const mojo::Handle& val) {
- if (!val.is_valid())
- return v8::Null(isolate);
- return mojo::js::HandleWrapper::Create(isolate, val.value()).ToV8();
-}
-
-bool Converter<mojo::Handle>::FromV8(v8::Isolate* isolate,
- v8::Handle<v8::Value> val,
- mojo::Handle* out) {
- if (val->IsNull()) {
- *out = mojo::Handle();
- return true;
- }
-
- gin::Handle<mojo::js::HandleWrapper> handle;
- if (!Converter<gin::Handle<mojo::js::HandleWrapper> >::FromV8(
- isolate, val, &handle))
- return false;
-
- *out = handle->get();
- return true;
-}
-
-v8::Handle<v8::Value> Converter<mojo::MessagePipeHandle>::ToV8(
- v8::Isolate* isolate, mojo::MessagePipeHandle val) {
- return Converter<mojo::Handle>::ToV8(isolate, val);
-}
-
-bool Converter<mojo::MessagePipeHandle>::FromV8(v8::Isolate* isolate,
- v8::Handle<v8::Value> val,
- mojo::MessagePipeHandle* out) {
- return Converter<mojo::Handle>::FromV8(isolate, val, out);
-}
-
-
-} // namespace gin
diff --git a/mojo/edk/js/handle.h b/mojo/edk/js/handle.h
deleted file mode 100644
index 200b322..0000000
--- a/mojo/edk/js/handle.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_HANDLE_H_
-#define MOJO_EDK_JS_HANDLE_H_
-
-#include "base/observer_list.h"
-#include "gin/converter.h"
-#include "gin/handle.h"
-#include "gin/wrappable.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace js {
-class HandleCloseObserver;
-
-// Wrapper for mojo Handles exposed to JavaScript. This ensures the Handle
-// is Closed when its JS object is garbage collected.
-class HandleWrapper : public gin::Wrappable<HandleWrapper> {
- public:
- static gin::WrapperInfo kWrapperInfo;
-
- static gin::Handle<HandleWrapper> Create(v8::Isolate* isolate,
- MojoHandle handle) {
- return gin::CreateHandle(isolate, new HandleWrapper(handle));
- }
-
- mojo::Handle get() const { return handle_.get(); }
- mojo::Handle release() { return handle_.release(); }
- void Close();
-
- void AddCloseObserver(HandleCloseObserver* observer);
- void RemoveCloseObserver(HandleCloseObserver* observer);
-
- protected:
- HandleWrapper(MojoHandle handle);
- ~HandleWrapper() override;
- void NotifyCloseObservers();
-
- mojo::ScopedHandle handle_;
- ObserverList<HandleCloseObserver> close_observers_;
-};
-
-} // namespace js
-} // namespace mojo
-
-namespace gin {
-
-// Note: It's important to use this converter rather than the one for
-// MojoHandle, since that will do a simple int32 conversion. It's unfortunate
-// there's no way to prevent against accidental use.
-// TODO(mpcomplete): define converters for all Handle subtypes.
-template<>
-struct Converter<mojo::Handle> {
- static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
- const mojo::Handle& val);
- static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
- mojo::Handle* out);
-};
-
-template<>
-struct Converter<mojo::MessagePipeHandle> {
- static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
- mojo::MessagePipeHandle val);
- static bool FromV8(v8::Isolate* isolate,
- v8::Handle<v8::Value> val,
- mojo::MessagePipeHandle* out);
-};
-
-// We need to specialize the normal gin::Handle converter in order to handle
-// converting |null| to a wrapper for an empty mojo::Handle.
-template<>
-struct Converter<gin::Handle<mojo::js::HandleWrapper> > {
- static v8::Handle<v8::Value> ToV8(
- v8::Isolate* isolate, const gin::Handle<mojo::js::HandleWrapper>& val) {
- return val.ToV8();
- }
-
- static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
- gin::Handle<mojo::js::HandleWrapper>* out) {
- if (val->IsNull()) {
- *out = mojo::js::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID);
- return true;
- }
-
- mojo::js::HandleWrapper* object = NULL;
- if (!Converter<mojo::js::HandleWrapper*>::FromV8(isolate, val, &object)) {
- return false;
- }
- *out = gin::Handle<mojo::js::HandleWrapper>(val, object);
- return true;
- }
-};
-
-} // namespace gin
-
-#endif // MOJO_EDK_JS_HANDLE_H_
diff --git a/mojo/edk/js/handle_close_observer.h b/mojo/edk/js/handle_close_observer.h
deleted file mode 100644
index 3e537fd..0000000
--- a/mojo/edk/js/handle_close_observer.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_
-#define MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_
-
-namespace mojo {
-namespace js {
-
-class HandleCloseObserver {
- public:
- virtual void OnWillCloseHandle() = 0;
-
- protected:
- virtual ~HandleCloseObserver() {}
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_
diff --git a/mojo/edk/js/handle_unittest.cc b/mojo/edk/js/handle_unittest.cc
deleted file mode 100644
index 53f474e..0000000
--- a/mojo/edk/js/handle_unittest.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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 "base/macros.h"
-#include "mojo/edk/js/handle.h"
-#include "mojo/edk/js/handle_close_observer.h"
-#include "mojo/public/cpp/system/core.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace js {
-
-class HandleWrapperTest : public testing::Test,
- public HandleCloseObserver {
- public:
- HandleWrapperTest() : closes_observed_(0) {}
-
- void OnWillCloseHandle() override { closes_observed_++; }
-
- protected:
- int closes_observed_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HandleWrapperTest);
-};
-
-class TestHandleWrapper : public HandleWrapper {
- public:
- explicit TestHandleWrapper(MojoHandle handle) : HandleWrapper(handle) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestHandleWrapper);
-};
-
-// Test that calling Close() on a HandleWrapper for an invalid handle does not
-// notify observers.
-TEST_F(HandleWrapperTest, CloseWithInvalidHandle) {
- {
- TestHandleWrapper wrapper(MOJO_HANDLE_INVALID);
- wrapper.AddCloseObserver(this);
- ASSERT_EQ(0, closes_observed_);
- wrapper.Close();
- EXPECT_EQ(0, closes_observed_);
- }
- EXPECT_EQ(0, closes_observed_);
-}
-
-// Test that destroying a HandleWrapper for an invalid handle does not notify
-// observers.
-TEST_F(HandleWrapperTest, DestroyWithInvalidHandle) {
- {
- TestHandleWrapper wrapper(MOJO_HANDLE_INVALID);
- wrapper.AddCloseObserver(this);
- ASSERT_EQ(0, closes_observed_);
- }
- EXPECT_EQ(0, closes_observed_);
-}
-
-// Test that calling Close on a HandleWrapper for a valid handle notifies
-// observers once.
-TEST_F(HandleWrapperTest, CloseWithValidHandle) {
- {
- mojo::MessagePipe pipe;
- TestHandleWrapper wrapper(pipe.handle0.release().value());
- wrapper.AddCloseObserver(this);
- ASSERT_EQ(0, closes_observed_);
- wrapper.Close();
- EXPECT_EQ(1, closes_observed_);
- // Check that calling close again doesn't notify observers.
- wrapper.Close();
- EXPECT_EQ(1, closes_observed_);
- }
- // Check that destroying a closed HandleWrapper doesn't notify observers.
- EXPECT_EQ(1, closes_observed_);
-}
-
-// Test that destroying a HandleWrapper for a valid handle notifies observers.
-TEST_F(HandleWrapperTest, DestroyWithValidHandle) {
- {
- mojo::MessagePipe pipe;
- TestHandleWrapper wrapper(pipe.handle0.release().value());
- wrapper.AddCloseObserver(this);
- ASSERT_EQ(0, closes_observed_);
- }
- EXPECT_EQ(1, closes_observed_);
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/mojo_runner_delegate.cc b/mojo/edk/js/mojo_runner_delegate.cc
deleted file mode 100644
index 152b12c..0000000
--- a/mojo/edk/js/mojo_runner_delegate.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 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/js/mojo_runner_delegate.h"
-
-#include "base/bind.h"
-#include "base/path_service.h"
-#include "gin/converter.h"
-#include "gin/modules/console.h"
-#include "gin/modules/module_registry.h"
-#include "gin/modules/timer.h"
-#include "gin/try_catch.h"
-#include "mojo/edk/js/core.h"
-#include "mojo/edk/js/handle.h"
-#include "mojo/edk/js/support.h"
-#include "mojo/edk/js/threading.h"
-
-namespace mojo {
-namespace js {
-
-namespace {
-
-// TODO(abarth): Rather than loading these modules from the file system, we
-// should load them from the network via Mojo IPC.
-std::vector<base::FilePath> GetModuleSearchPaths() {
- std::vector<base::FilePath> search_paths(2);
- PathService::Get(base::DIR_SOURCE_ROOT, &search_paths[0]);
- PathService::Get(base::DIR_EXE, &search_paths[1]);
- search_paths[1] = search_paths[1].AppendASCII("gen");
- return search_paths;
-}
-
-void StartCallback(base::WeakPtr<gin::Runner> runner,
- MojoHandle pipe,
- v8::Handle<v8::Value> module) {
- v8::Isolate* isolate = runner->GetContextHolder()->isolate();
- v8::Handle<v8::Function> start;
- CHECK(gin::ConvertFromV8(isolate, module, &start));
-
- v8::Handle<v8::Value> args[] = {
- gin::ConvertToV8(isolate, Handle(pipe)) };
- runner->Call(start, runner->global(), 1, args);
-}
-
-} // namespace
-
-MojoRunnerDelegate::MojoRunnerDelegate()
- : ModuleRunnerDelegate(GetModuleSearchPaths()) {
- AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule);
- AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule);
- AddBuiltinModule(js::Core::kModuleName, js::Core::GetModule);
- AddBuiltinModule(js::Support::kModuleName, js::Support::GetModule);
- AddBuiltinModule(js::Threading::kModuleName, js::Threading::GetModule);
-}
-
-MojoRunnerDelegate::~MojoRunnerDelegate() {
-}
-
-void MojoRunnerDelegate::Start(gin::Runner* runner,
- MojoHandle pipe,
- const std::string& module) {
- gin::Runner::Scope scope(runner);
- gin::ModuleRegistry* registry =
- gin::ModuleRegistry::From(runner->GetContextHolder()->context());
- registry->LoadModule(runner->GetContextHolder()->isolate(), module,
- base::Bind(StartCallback, runner->GetWeakPtr(), pipe));
- AttemptToLoadMoreModules(runner);
-}
-
-void MojoRunnerDelegate::UnhandledException(gin::ShellRunner* runner,
- gin::TryCatch& try_catch) {
- gin::ModuleRunnerDelegate::UnhandledException(runner, try_catch);
- LOG(ERROR) << try_catch.GetStackTrace();
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/mojo_runner_delegate.h b/mojo/edk/js/mojo_runner_delegate.h
deleted file mode 100644
index 423eefb..0000000
--- a/mojo/edk/js/mojo_runner_delegate.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 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_EDK_JS_MOJO_RUNNER_DELEGATE_H_
-#define MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_
-
-#include "base/macros.h"
-#include "gin/modules/module_runner_delegate.h"
-#include "mojo/public/c/system/core.h"
-
-namespace mojo {
-namespace js {
-
-class MojoRunnerDelegate : public gin::ModuleRunnerDelegate {
- public:
- MojoRunnerDelegate();
- ~MojoRunnerDelegate() override;
-
- void Start(gin::Runner* runner, MojoHandle pipe, const std::string& module);
-
- private:
- // From ModuleRunnerDelegate:
- void UnhandledException(gin::ShellRunner* runner,
- gin::TryCatch& try_catch) override;
-
- DISALLOW_COPY_AND_ASSIGN(MojoRunnerDelegate);
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_
diff --git a/mojo/edk/js/support.cc b/mojo/edk/js/support.cc
deleted file mode 100644
index 7d44024..0000000
--- a/mojo/edk/js/support.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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/js/support.h"
-
-#include "base/bind.h"
-#include "gin/arguments.h"
-#include "gin/converter.h"
-#include "gin/function_template.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-#include "gin/wrappable.h"
-#include "mojo/edk/js/handle.h"
-#include "mojo/edk/js/waiting_callback.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace js {
-
-namespace {
-
-WaitingCallback* AsyncWait(const gin::Arguments& args,
- gin::Handle<HandleWrapper> handle,
- MojoHandleSignals signals,
- v8::Handle<v8::Function> callback) {
- return WaitingCallback::Create(args.isolate(), callback, handle, signals)
- .get();
-}
-
-void CancelWait(WaitingCallback* waiting_callback) {
- waiting_callback->Cancel();
-}
-
-gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
-
-} // namespace
-
-const char Support::kModuleName[] = "mojo/public/js/support";
-
-v8::Local<v8::Value> Support::GetModule(v8::Isolate* isolate) {
- gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
- v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(
- &g_wrapper_info);
-
- if (templ.IsEmpty()) {
- templ = gin::ObjectTemplateBuilder(isolate)
- .SetMethod("asyncWait", AsyncWait)
- .SetMethod("cancelWait", CancelWait)
- .Build();
-
- data->SetObjectTemplate(&g_wrapper_info, templ);
- }
-
- return templ->NewInstance();
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/support.h b/mojo/edk/js/support.h
deleted file mode 100644
index b49dd23..0000000
--- a/mojo/edk/js/support.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_SUPPORT_H_
-#define MOJO_EDK_JS_SUPPORT_H_
-
-#include "v8/include/v8.h"
-
-namespace mojo {
-namespace js {
-
-class Support {
- public:
- static const char kModuleName[];
- static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_SUPPORT_H_
diff --git a/mojo/edk/js/test/BUILD.gn b/mojo/edk/js/test/BUILD.gn
deleted file mode 100644
index badc3ad..0000000
--- a/mojo/edk/js/test/BUILD.gn
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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.
-
-test("js_unittests") {
- deps = [
- "../../js",
- "../../js:js_unittests",
- "../../test:run_all_unittests",
- "../../test:test_support",
- "../../../public/cpp/environment",
- "../../../public/cpp/system",
- "../../../public/cpp/utility",
- "../../../public/interfaces/bindings/tests:test_interfaces",
- "//base",
- "//gin:gin_test",
- "//mojo/environment:chromium",
- ]
-
- sources = [
- "run_js_tests.cc",
- ]
-}
-
-test("js_integration_tests") {
- deps = [
- "../../js",
- "../../js/tests:js_to_cpp_tests",
- "../../test:run_all_unittests",
- "../../test:test_support",
- "../../../public/cpp/bindings",
- "../../../public/interfaces/bindings/tests:test_interfaces",
- "//base",
- "//gin:gin_test",
- "//mojo/environment:chromium",
- ]
-
- sources = [
- "run_js_integration_tests.cc",
- ]
-}
diff --git a/mojo/edk/js/test/hexdump.js b/mojo/edk/js/test/hexdump.js
deleted file mode 100644
index b36c47f..0000000
--- a/mojo/edk/js/test/hexdump.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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.
-
-define(function() {
- function hexify(value, length) {
- var hex = value.toString(16);
- while (hex.length < length)
- hex = "0" + hex;
- return hex;
- }
-
- function dumpArray(bytes) {
- var dumped = "";
- for (var i = 0; i < bytes.length; ++i) {
- dumped += hexify(bytes[i], 2);
-
- if (i % 16 == 15) {
- dumped += "\n";
- continue;
- }
-
- if (i % 2 == 1)
- dumped += " ";
- if (i % 8 == 7)
- dumped += " ";
- }
- return dumped;
- }
-
- var exports = {};
- exports.dumpArray = dumpArray;
- return exports;
-});
diff --git a/mojo/edk/js/test/run_js_integration_tests.cc b/mojo/edk/js/test/run_js_integration_tests.cc
deleted file mode 100644
index 1a6f1d6..0000000
--- a/mojo/edk/js/test/run_js_integration_tests.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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 "base/files/file_path.h"
-#include "base/path_service.h"
-#include "gin/modules/console.h"
-#include "gin/modules/module_registry.h"
-#include "gin/modules/timer.h"
-#include "gin/test/file_runner.h"
-#include "gin/test/gtest.h"
-#include "mojo/edk/js/core.h"
-#include "mojo/edk/js/support.h"
-#include "mojo/edk/js/threading.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace js {
-namespace {
-
-class TestRunnerDelegate : public gin::FileRunnerDelegate {
- public:
- TestRunnerDelegate() {
- AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule);
- AddBuiltinModule(Core::kModuleName, Core::GetModule);
- AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule);
- AddBuiltinModule(Threading::kModuleName, Threading::GetModule);
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(TestRunnerDelegate);
-};
-
-void RunTest(std::string test, bool addSupportModule) {
- base::FilePath path;
- PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.AppendASCII("mojo")
- .AppendASCII("edk")
- .AppendASCII("js")
- .AppendASCII("tests")
- .AppendASCII(test);
- TestRunnerDelegate delegate;
- if (addSupportModule)
- delegate.AddBuiltinModule(Support::kModuleName, Support::GetModule);
- gin::RunTestFromFile(path, &delegate, true);
-}
-
-TEST(JSTest, connection) {
- RunTest("connection_tests.js", false);
-}
-
-TEST(JSTest, sample_service) {
- RunTest("sample_service_tests.js", true);
-}
-
-} // namespace
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/test/run_js_tests.cc b/mojo/edk/js/test/run_js_tests.cc
deleted file mode 100644
index b574902..0000000
--- a/mojo/edk/js/test/run_js_tests.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 "base/files/file_path.h"
-#include "base/path_service.h"
-#include "gin/modules/console.h"
-#include "gin/modules/module_registry.h"
-#include "gin/test/file_runner.h"
-#include "gin/test/gtest.h"
-#include "mojo/edk/js/core.h"
-#include "mojo/edk/js/support.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace js {
-namespace {
-
-class TestRunnerDelegate : public gin::FileRunnerDelegate {
- public:
- TestRunnerDelegate() {
- AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule);
- AddBuiltinModule(Core::kModuleName, Core::GetModule);
- AddBuiltinModule(Support::kModuleName, Support::GetModule);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestRunnerDelegate);
-};
-
-void RunTest(std::string test, bool run_until_idle) {
- base::FilePath path;
- PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.AppendASCII("mojo")
- .AppendASCII("public")
- .AppendASCII("js")
- .AppendASCII(test);
- TestRunnerDelegate delegate;
- gin::RunTestFromFile(path, &delegate, run_until_idle);
-}
-
-// TODO(abarth): Should we autogenerate these stubs from GYP?
-TEST(JSTest, core) {
- RunTest("core_unittests.js", true);
-}
-
-TEST(JSTest, codec) {
- RunTest("codec_unittests.js", true);
-}
-
-TEST(JSTest, struct) {
- RunTest("struct_unittests.js", true);
-}
-
-TEST(JSTest, validation) {
- RunTest("validation_unittests.js", true);
-}
-
-} // namespace
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn
deleted file mode 100644
index c9711c7..0000000
--- a/mojo/edk/js/tests/BUILD.gn
+++ /dev/null
@@ -1,36 +0,0 @@
-# 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.
-
-import("../../mojo_edk.gni")
-import("../../../public/tools/bindings/mojom.gni")
-
-mojo_edk_source_set("js_to_cpp_tests") {
- testonly = true
-
- deps = [
- ":js_to_cpp_bindings",
- "//gin:gin_test",
- ]
-
- mojo_edk_deps = [
- "mojo/edk/js",
- "mojo/edk/test:test_support",
- ]
-
- mojo_sdk_deps = [
- "mojo/public/cpp/bindings",
- "mojo/public/cpp/system",
- "mojo/public/interfaces/bindings/tests:test_interfaces",
- ]
-
- sources = [
- "js_to_cpp_tests.cc",
- ]
-}
-
-mojom("js_to_cpp_bindings") {
- sources = [
- "js_to_cpp.mojom",
- ]
-}
diff --git a/mojo/edk/js/tests/connection_tests.js b/mojo/edk/js/tests/connection_tests.js
deleted file mode 100644
index 17009d9..0000000
--- a/mojo/edk/js/tests/connection_tests.js
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2013 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.
-
-// Mock out the support module to avoid depending on the message loop.
-define("mojo/public/js/support", ["timer"], function(timer) {
- var waitingCallbacks = [];
-
- function WaitCookie(id) {
- this.id = id;
- }
-
- function asyncWait(handle, flags, callback) {
- var id = waitingCallbacks.length;
- waitingCallbacks.push(callback);
- return new WaitCookie(id);
- }
-
- function cancelWait(cookie) {
- waitingCallbacks[cookie.id] = null;
- }
-
- function numberOfWaitingCallbacks() {
- var count = 0;
- for (var i = 0; i < waitingCallbacks.length; ++i) {
- if (waitingCallbacks[i])
- ++count;
- }
- return count;
- }
-
- function pumpOnce(result) {
- var callbacks = waitingCallbacks;
- waitingCallbacks = [];
- for (var i = 0; i < callbacks.length; ++i) {
- if (callbacks[i])
- callbacks[i](result);
- }
- }
-
- // Queue up a pumpOnce call to execute after the stack unwinds. Use
- // this to trigger a pump after all Promises are executed.
- function queuePump(result) {
- timer.createOneShot(0, pumpOnce.bind(undefined, result));
- }
-
- var exports = {};
- exports.asyncWait = asyncWait;
- exports.cancelWait = cancelWait;
- exports.numberOfWaitingCallbacks = numberOfWaitingCallbacks;
- exports.pumpOnce = pumpOnce;
- exports.queuePump = queuePump;
- return exports;
-});
-
-define([
- "gin/test/expect",
- "mojo/public/js/support",
- "mojo/public/js/core",
- "mojo/public/js/connection",
- "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom",
- "mojo/public/interfaces/bindings/tests/sample_service.mojom",
- "mojo/public/js/threading",
- "gc",
-], function(expect,
- mockSupport,
- core,
- connection,
- sample_interfaces,
- sample_service,
- threading,
- gc) {
- testClientServer();
- testWriteToClosedPipe();
- testRequestResponse().then(function() {
- this.result = "PASS";
- gc.collectGarbage(); // should not crash
- threading.quit();
- }.bind(this)).catch(function(e) {
- this.result = "FAIL: " + (e.stack || e);
- threading.quit();
- }.bind(this));
-
- function createPeerConnection(handle, stubClass, proxyClass) {
- var c = new connection.Connection(handle, stubClass, proxyClass);
- c.local.peer = c.remote;
- c.remote.peer = c.local;
- return c;
- }
-
- function testClientServer() {
- var receivedFrobinate = false;
- var receivedDidFrobinate = false;
-
- // ServiceImpl ------------------------------------------------------------
-
- function ServiceImpl() {
- }
-
- ServiceImpl.prototype = Object.create(
- sample_service.Service.stubClass.prototype);
-
- ServiceImpl.prototype.frobinate = function(foo, baz, port) {
- receivedFrobinate = true;
-
- expect(foo.name).toBe("Example name");
- expect(baz).toBeTruthy();
- expect(core.close(port)).toBe(core.RESULT_OK);
-
- this.peer.didFrobinate(42);
- };
-
- // ServiceClientImpl ------------------------------------------------------
-
- function ServiceClientImpl() {
- }
-
- ServiceClientImpl.prototype =
- Object.create(sample_service.ServiceClient.stubClass.prototype);
-
- ServiceClientImpl.prototype.didFrobinate = function(result) {
- receivedDidFrobinate = true;
-
- expect(result).toBe(42);
- };
-
- var pipe = core.createMessagePipe();
- var anotherPipe = core.createMessagePipe();
- var sourcePipe = core.createMessagePipe();
-
- var connection0 = createPeerConnection(
- pipe.handle0, ServiceImpl, sample_service.ServiceClient.proxyClass);
-
- var connection1 = createPeerConnection(
- pipe.handle1, ServiceClientImpl, sample_service.Service.proxyClass);
-
- var foo = new sample_service.Foo();
- foo.bar = new sample_service.Bar();
- foo.name = "Example name";
- foo.source = sourcePipe.handle0;
- connection1.remote.frobinate(foo, true, anotherPipe.handle0);
-
- mockSupport.pumpOnce(core.RESULT_OK);
-
- expect(receivedFrobinate).toBeTruthy();
- expect(receivedDidFrobinate).toBeTruthy();
-
- connection0.close();
- connection1.close();
-
- expect(mockSupport.numberOfWaitingCallbacks()).toBe(0);
-
- // sourcePipe.handle0 was closed automatically when sent over IPC.
- expect(core.close(sourcePipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
- // sourcePipe.handle1 hasn't been closed yet.
- expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK);
-
- // anotherPipe.handle0 was closed automatically when sent over IPC.
- expect(core.close(anotherPipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
- // anotherPipe.handle1 hasn't been closed yet.
- expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK);
-
- // The Connection object is responsible for closing these handles.
- expect(core.close(pipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
- expect(core.close(pipe.handle1)).toBe(core.RESULT_INVALID_ARGUMENT);
- }
-
- function testWriteToClosedPipe() {
- var pipe = core.createMessagePipe();
-
- var connection1 = createPeerConnection(
- pipe.handle1, function() {}, sample_service.Service.proxyClass);
-
- // Close the other end of the pipe.
- core.close(pipe.handle0);
-
- // Not observed yet because we haven't pumped events yet.
- expect(connection1.encounteredError()).toBeFalsy();
-
- var foo = new sample_service.Foo();
- foo.bar = new sample_service.Bar();
- // TODO(darin): crbug.com/357043: pass null in place of |foo| here.
- connection1.remote.frobinate(foo, true, null);
-
- // Write failures are not reported.
- expect(connection1.encounteredError()).toBeFalsy();
-
- // Pump events, and then we should start observing the closed pipe.
- mockSupport.pumpOnce(core.RESULT_OK);
-
- expect(connection1.encounteredError()).toBeTruthy();
-
- connection1.close();
- }
-
- function testRequestResponse() {
-
- // ProviderImpl ------------------------------------------------------------
-
- function ProviderImpl() {
- }
-
- ProviderImpl.prototype =
- Object.create(sample_interfaces.Provider.stubClass.prototype);
-
- ProviderImpl.prototype.echoString = function(a) {
- mockSupport.queuePump(core.RESULT_OK);
- return Promise.resolve({a: a});
- };
-
- ProviderImpl.prototype.echoStrings = function(a, b) {
- mockSupport.queuePump(core.RESULT_OK);
- return Promise.resolve({a: a, b: b});
- };
-
- // ProviderClientImpl ------------------------------------------------------
-
- function ProviderClientImpl() {
- }
-
- ProviderClientImpl.prototype =
- Object.create(sample_interfaces.ProviderClient.stubClass.prototype);
-
- var pipe = core.createMessagePipe();
-
- var connection0 = createPeerConnection(
- pipe.handle0,
- ProviderImpl,
- sample_interfaces.ProviderClient.proxyClass);
-
- var connection1 = createPeerConnection(
- pipe.handle1,
- ProviderClientImpl,
- sample_interfaces.Provider.proxyClass);
-
- var origReadMessage = core.readMessage;
- // echoString
- mockSupport.queuePump(core.RESULT_OK);
- return connection1.remote.echoString("hello").then(function(response) {
- expect(response.a).toBe("hello");
- }).then(function() {
- // echoStrings
- mockSupport.queuePump(core.RESULT_OK);
- return connection1.remote.echoStrings("hello", "world");
- }).then(function(response) {
- expect(response.a).toBe("hello");
- expect(response.b).toBe("world");
- }).then(function() {
- // Mock a read failure, expect it to fail.
- core.readMessage = function() {
- return { result: core.RESULT_UNKNOWN };
- };
- mockSupport.queuePump(core.RESULT_OK);
- return connection1.remote.echoString("goodbye");
- }).then(function() {
- throw Error("Expected echoString to fail.");
- }, function(error) {
- expect(error.message).toBe("Connection error: " + core.RESULT_UNKNOWN);
-
- // Clean up.
- core.readMessage = origReadMessage;
- });
- }
-});
diff --git a/mojo/edk/js/tests/js_to_cpp.mojom b/mojo/edk/js/tests/js_to_cpp.mojom
deleted file mode 100644
index 69f67b6..0000000
--- a/mojo/edk/js/tests/js_to_cpp.mojom
+++ /dev/null
@@ -1,53 +0,0 @@
-module js_to_cpp;
-
-// This struct encompasses all of the basic types, so that they
-// may be sent from C++ to JS and back for validation.
-struct EchoArgs {
- int64 si64;
- int32 si32;
- int16 si16;
- int8 si8;
- uint64 ui64;
- uint32 ui32;
- uint16 ui16;
- uint8 ui8;
- float float_val;
- float float_inf;
- float float_nan;
- double double_val;
- double double_inf;
- double double_nan;
- string? name;
- array<string>? string_array;
- handle<message_pipe>? message_handle;
- handle<data_pipe_consumer>? data_handle;
-};
-
-struct EchoArgsList {
- EchoArgsList? next;
- EchoArgs? item;
-};
-
-// Note: For messages which control test flow, pick numbers that are unlikely
-// to be hit as a result of our deliberate corruption of response messages.
-interface CppSide {
- // Sent for all tests to notify that the JS side is now ready.
- StartTest@88888888();
-
- // Indicates end for echo, bit-flip, and back-pointer tests.
- TestFinished@99999999();
-
- // Responses from specific tests.
- PingResponse();
- EchoResponse(EchoArgsList list);
- BitFlipResponse(EchoArgsList arg);
- BackPointerResponse(EchoArgsList arg);
-};
-
-[Client=CppSide]
-interface JsSide {
- Ping();
- Echo(int32 numIterations, EchoArgs arg);
- BitFlip(EchoArgs arg);
- BackPointer(EchoArgs arg);
-};
diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc
deleted file mode 100644
index 1da70c2..0000000
--- a/mojo/edk/js/tests/js_to_cpp_tests.cc
+++ /dev/null
@@ -1,418 +0,0 @@
-// 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 "base/at_exit.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "gin/array_buffer.h"
-#include "gin/public/isolate_holder.h"
-#include "mojo/edk/js/mojo_runner_delegate.h"
-#include "mojo/edk/js/tests/js_to_cpp.mojom.h"
-#include "mojo/edk/test/test_utils.h"
-#include "mojo/public/cpp/system/core.h"
-#include "mojo/public/cpp/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace js {
-
-// Global value updated by some checks to prevent compilers from optimizing
-// reads out of existence.
-uint32 g_waste_accumulator = 0;
-
-namespace {
-
-// Negative numbers with different values in each byte, the last of
-// which can survive promotion to double and back.
-const int8 kExpectedInt8Value = -65;
-const int16 kExpectedInt16Value = -16961;
-const int32 kExpectedInt32Value = -1145258561;
-const int64 kExpectedInt64Value = -77263311946305LL;
-
-// Positive numbers with different values in each byte, the last of
-// which can survive promotion to double and back.
-const uint8 kExpectedUInt8Value = 65;
-const uint16 kExpectedUInt16Value = 16961;
-const uint32 kExpectedUInt32Value = 1145258561;
-const uint64 kExpectedUInt64Value = 77263311946305LL;
-
-// Double/float values, including special case constants.
-const double kExpectedDoubleVal = 3.14159265358979323846;
-const double kExpectedDoubleInf = std::numeric_limits<double>::infinity();
-const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN();
-const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal);
-const float kExpectedFloatInf = std::numeric_limits<float>::infinity();
-const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN();
-
-// NaN has the property that it is not equal to itself.
-#define EXPECT_NAN(x) EXPECT_NE(x, x)
-
-void CheckDataPipe(MojoHandle data_pipe_handle) {
- unsigned char buffer[100];
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- MojoResult result = MojoReadData(
- data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(64u, buffer_size);
- for (int i = 0; i < 64; ++i) {
- EXPECT_EQ(i, buffer[i]);
- }
-}
-
-void CheckMessagePipe(MojoHandle message_pipe_handle) {
- unsigned char buffer[100];
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- MojoResult result = MojoReadMessage(
- message_pipe_handle, buffer, &buffer_size, 0, 0, 0);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(64u, buffer_size);
- for (int i = 0; i < 64; ++i) {
- EXPECT_EQ(255 - i, buffer[i]);
- }
-}
-
-js_to_cpp::EchoArgsPtr BuildSampleEchoArgs() {
- js_to_cpp::EchoArgsPtr args(js_to_cpp::EchoArgs::New());
- args->si64 = kExpectedInt64Value;
- args->si32 = kExpectedInt32Value;
- args->si16 = kExpectedInt16Value;
- args->si8 = kExpectedInt8Value;
- args->ui64 = kExpectedUInt64Value;
- args->ui32 = kExpectedUInt32Value;
- args->ui16 = kExpectedUInt16Value;
- args->ui8 = kExpectedUInt8Value;
- args->float_val = kExpectedFloatVal;
- args->float_inf = kExpectedFloatInf;
- args->float_nan = kExpectedFloatNan;
- args->double_val = kExpectedDoubleVal;
- args->double_inf = kExpectedDoubleInf;
- args->double_nan = kExpectedDoubleNan;
- args->name = "coming";
- Array<String> string_array(3);
- string_array[0] = "one";
- string_array[1] = "two";
- string_array[2] = "three";
- args->string_array = string_array.Pass();
- return args.Pass();
-}
-
-void CheckSampleEchoArgs(const js_to_cpp::EchoArgs& arg) {
- EXPECT_EQ(kExpectedInt64Value, arg.si64);
- EXPECT_EQ(kExpectedInt32Value, arg.si32);
- EXPECT_EQ(kExpectedInt16Value, arg.si16);
- EXPECT_EQ(kExpectedInt8Value, arg.si8);
- EXPECT_EQ(kExpectedUInt64Value, arg.ui64);
- EXPECT_EQ(kExpectedUInt32Value, arg.ui32);
- EXPECT_EQ(kExpectedUInt16Value, arg.ui16);
- EXPECT_EQ(kExpectedUInt8Value, arg.ui8);
- EXPECT_EQ(kExpectedFloatVal, arg.float_val);
- EXPECT_EQ(kExpectedFloatInf, arg.float_inf);
- EXPECT_NAN(arg.float_nan);
- EXPECT_EQ(kExpectedDoubleVal, arg.double_val);
- EXPECT_EQ(kExpectedDoubleInf, arg.double_inf);
- EXPECT_NAN(arg.double_nan);
- EXPECT_EQ(std::string("coming"), arg.name.get());
- EXPECT_EQ(std::string("one"), arg.string_array[0].get());
- EXPECT_EQ(std::string("two"), arg.string_array[1].get());
- EXPECT_EQ(std::string("three"), arg.string_array[2].get());
- CheckDataPipe(arg.data_handle.get().value());
- CheckMessagePipe(arg.message_handle.get().value());
-}
-
-void CheckSampleEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) {
- if (list.is_null())
- return;
- CheckSampleEchoArgs(*list->item);
- CheckSampleEchoArgsList(list->next);
-}
-
-// More forgiving checks are needed in the face of potentially corrupt
-// messages. The values don't matter so long as all accesses are within
-// bounds.
-void CheckCorruptedString(const String& arg) {
- if (arg.is_null())
- return;
- for (size_t i = 0; i < arg.size(); ++i)
- g_waste_accumulator += arg[i];
-}
-
-void CheckCorruptedStringArray(const Array<String>& string_array) {
- if (string_array.is_null())
- return;
- for (size_t i = 0; i < string_array.size(); ++i)
- CheckCorruptedString(string_array[i]);
-}
-
-void CheckCorruptedDataPipe(MojoHandle data_pipe_handle) {
- unsigned char buffer[100];
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- MojoResult result = MojoReadData(
- data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE);
- if (result != MOJO_RESULT_OK)
- return;
- for (uint32_t i = 0; i < buffer_size; ++i)
- g_waste_accumulator += buffer[i];
-}
-
-void CheckCorruptedMessagePipe(MojoHandle message_pipe_handle) {
- unsigned char buffer[100];
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- MojoResult result = MojoReadMessage(
- message_pipe_handle, buffer, &buffer_size, 0, 0, 0);
- if (result != MOJO_RESULT_OK)
- return;
- for (uint32_t i = 0; i < buffer_size; ++i)
- g_waste_accumulator += buffer[i];
-}
-
-void CheckCorruptedEchoArgs(const js_to_cpp::EchoArgsPtr& arg) {
- if (arg.is_null())
- return;
- CheckCorruptedString(arg->name);
- CheckCorruptedStringArray(arg->string_array);
- if (arg->data_handle.is_valid())
- CheckCorruptedDataPipe(arg->data_handle.get().value());
- if (arg->message_handle.is_valid())
- CheckCorruptedMessagePipe(arg->message_handle.get().value());
-}
-
-void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) {
- if (list.is_null())
- return;
- CheckCorruptedEchoArgs(list->item);
- CheckCorruptedEchoArgsList(list->next);
-}
-
-// Base Provider implementation class. It's expected that tests subclass and
-// override the appropriate Provider functions. When test is done quit the
-// run_loop().
-class CppSideConnection : public js_to_cpp::CppSide {
- public:
- CppSideConnection() :
- run_loop_(NULL),
- js_side_(NULL),
- mishandled_messages_(0) {
- }
- ~CppSideConnection() override {}
-
- void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
- base::RunLoop* run_loop() { return run_loop_; }
-
- void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; }
- js_to_cpp::JsSide* js_side() { return js_side_; }
-
- // js_to_cpp::CppSide:
- void StartTest() override { NOTREACHED(); }
-
- void TestFinished() override { NOTREACHED(); }
-
- void PingResponse() override { mishandled_messages_ += 1; }
-
- void EchoResponse(js_to_cpp::EchoArgsListPtr list) override {
- mishandled_messages_ += 1;
- }
-
- void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override {
- mishandled_messages_ += 1;
- }
-
- void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override {
- mishandled_messages_ += 1;
- }
-
- protected:
- base::RunLoop* run_loop_;
- js_to_cpp::JsSide* js_side_;
- int mishandled_messages_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CppSideConnection);
-};
-
-// Trivial test to verify a message sent from JS is received.
-class PingCppSideConnection : public CppSideConnection {
- public:
- PingCppSideConnection() : got_message_(false) {}
- ~PingCppSideConnection() override {}
-
- // js_to_cpp::CppSide:
- void StartTest() override { js_side_->Ping(); }
-
- void PingResponse() override {
- got_message_ = true;
- run_loop()->Quit();
- }
-
- bool DidSucceed() {
- return got_message_ && !mishandled_messages_;
- }
-
- private:
- bool got_message_;
- DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection);
-};
-
-// Test that parameters are passed with correct values.
-class EchoCppSideConnection : public CppSideConnection {
- public:
- EchoCppSideConnection() :
- message_count_(0),
- termination_seen_(false) {
- }
- ~EchoCppSideConnection() override {}
-
- // js_to_cpp::CppSide:
- void StartTest() override {
- js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs());
- }
-
- void EchoResponse(js_to_cpp::EchoArgsListPtr list) override {
- const js_to_cpp::EchoArgsPtr& special_arg = list->item;
- message_count_ += 1;
- EXPECT_EQ(-1, special_arg->si64);
- EXPECT_EQ(-1, special_arg->si32);
- EXPECT_EQ(-1, special_arg->si16);
- EXPECT_EQ(-1, special_arg->si8);
- EXPECT_EQ(std::string("going"), special_arg->name.To<std::string>());
- CheckSampleEchoArgsList(list->next);
- }
-
- void TestFinished() override {
- termination_seen_ = true;
- run_loop()->Quit();
- }
-
- bool DidSucceed() {
- return termination_seen_ &&
- !mishandled_messages_ &&
- message_count_ == kExpectedMessageCount;
- }
-
- private:
- static const int kExpectedMessageCount = 10;
- int message_count_;
- bool termination_seen_;
- DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection);
-};
-
-// Test that corrupted messages don't wreak havoc.
-class BitFlipCppSideConnection : public CppSideConnection {
- public:
- BitFlipCppSideConnection() : termination_seen_(false) {}
- ~BitFlipCppSideConnection() override {}
-
- // js_to_cpp::CppSide:
- void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); }
-
- void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override {
- CheckCorruptedEchoArgsList(list);
- }
-
- void TestFinished() override {
- termination_seen_ = true;
- run_loop()->Quit();
- }
-
- bool DidSucceed() {
- return termination_seen_;
- }
-
- private:
- bool termination_seen_;
- DISALLOW_COPY_AND_ASSIGN(BitFlipCppSideConnection);
-};
-
-// Test that severely random messages don't wreak havoc.
-class BackPointerCppSideConnection : public CppSideConnection {
- public:
- BackPointerCppSideConnection() : termination_seen_(false) {}
- ~BackPointerCppSideConnection() override {}
-
- // js_to_cpp::CppSide:
- void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); }
-
- void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override {
- CheckCorruptedEchoArgsList(list);
- }
-
- void TestFinished() override {
- termination_seen_ = true;
- run_loop()->Quit();
- }
-
- bool DidSucceed() {
- return termination_seen_;
- }
-
- private:
- bool termination_seen_;
- DISALLOW_COPY_AND_ASSIGN(BackPointerCppSideConnection);
-};
-
-} // namespace
-
-class JsToCppTest : public testing::Test {
- public:
- JsToCppTest() {}
-
- void RunTest(const std::string& test, CppSideConnection* cpp_side) {
- cpp_side->set_run_loop(&run_loop_);
-
- MessagePipe pipe;
- js_to_cpp::JsSidePtr js_side =
- MakeProxy<js_to_cpp::JsSide>(pipe.handle0.Pass());
- js_side.set_client(cpp_side);
-
- js_side.internal_state()->router_for_testing()->EnableTestingMode();
-
- cpp_side->set_js_side(js_side.get());
-
- gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
- gin::ArrayBufferAllocator::SharedInstance());
- gin::IsolateHolder instance;
- MojoRunnerDelegate delegate;
- gin::ShellRunner runner(&delegate, instance.isolate());
- delegate.Start(&runner, pipe.handle1.release().value(), test);
-
- run_loop_.Run();
- }
-
- private:
- base::ShadowingAtExitManager at_exit_;
- base::MessageLoop loop;
- base::RunLoop run_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(JsToCppTest);
-};
-
-TEST_F(JsToCppTest, Ping) {
- PingCppSideConnection cpp_side_connection;
- RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection);
- EXPECT_TRUE(cpp_side_connection.DidSucceed());
-}
-
-TEST_F(JsToCppTest, Echo) {
- EchoCppSideConnection cpp_side_connection;
- RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection);
- EXPECT_TRUE(cpp_side_connection.DidSucceed());
-}
-
-TEST_F(JsToCppTest, BitFlip) {
- BitFlipCppSideConnection cpp_side_connection;
- RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection);
- EXPECT_TRUE(cpp_side_connection.DidSucceed());
-}
-
-TEST_F(JsToCppTest, BackPointer) {
- BackPointerCppSideConnection cpp_side_connection;
- RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection);
- EXPECT_TRUE(cpp_side_connection.DidSucceed());
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/tests/js_to_cpp_tests.js b/mojo/edk/js/tests/js_to_cpp_tests.js
deleted file mode 100644
index 140ad4c..0000000
--- a/mojo/edk/js/tests/js_to_cpp_tests.js
+++ /dev/null
@@ -1,226 +0,0 @@
-// 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.
-
-define('mojo/edk/js/tests/js_to_cpp_tests', [
- 'console',
- 'mojo/edk/js/tests/js_to_cpp.mojom',
- 'mojo/public/js/connection',
- 'mojo/public/js/connector',
- 'mojo/public/js/core',
-], function (console, jsToCpp, connection, connector, core) {
- var retainedConnection;
- var sampleData;
- var sampleMessage;
- var BAD_VALUE = 13;
- var DATA_PIPE_PARAMS = {
- flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
- elementNumBytes: 1,
- capacityNumBytes: 64
- };
-
- function JsSideConnection() {
- }
-
- JsSideConnection.prototype =
- Object.create(jsToCpp.JsSide.stubClass.prototype);
-
- JsSideConnection.prototype.ping = function (arg) {
- this.cppSide_.pingResponse();
- };
-
- JsSideConnection.prototype.echo = function (numIterations, arg) {
- var dataPipe1;
- var dataPipe2;
- var i;
- var messagePipe1;
- var messagePipe2;
- var specialArg;
-
- // Ensure expected negative values are negative.
- if (arg.si64 > 0)
- arg.si64 = BAD_VALUE;
-
- if (arg.si32 > 0)
- arg.si32 = BAD_VALUE;
-
- if (arg.si16 > 0)
- arg.si16 = BAD_VALUE;
-
- if (arg.si8 > 0)
- arg.si8 = BAD_VALUE;
-
- for (i = 0; i < numIterations; ++i) {
- dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS);
- dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS);
- messagePipe1 = core.createMessagePipe();
- messagePipe2 = core.createMessagePipe();
-
- arg.data_handle = dataPipe1.consumerHandle;
- arg.message_handle = messagePipe1.handle1;
-
- specialArg = new jsToCpp.EchoArgs();
- specialArg.si64 = -1;
- specialArg.si32 = -1;
- specialArg.si16 = -1;
- specialArg.si8 = -1;
- specialArg.name = 'going';
- specialArg.data_handle = dataPipe2.consumerHandle;
- specialArg.message_handle = messagePipe2.handle1;
-
- writeDataPipe(dataPipe1, sampleData);
- writeDataPipe(dataPipe2, sampleData);
- writeMessagePipe(messagePipe1, sampleMessage);
- writeMessagePipe(messagePipe2, sampleMessage);
-
- this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg));
-
- core.close(dataPipe1.producerHandle);
- core.close(dataPipe2.producerHandle);
- core.close(messagePipe1.handle0);
- core.close(messagePipe2.handle0);
- }
- this.cppSide_.testFinished();
- };
-
- JsSideConnection.prototype.bitFlip = function (arg) {
- var iteration = 0;
- var dataPipe;
- var messagePipe;
- var proto = connector.Connector.prototype;
- var stopSignalled = false;
-
- proto.realAccept = proto.accept;
- proto.accept = function (message) {
- var offset = iteration / 8;
- var mask;
- var value;
- if (offset < message.buffer.arrayBuffer.byteLength) {
- mask = 1 << (iteration % 8);
- value = message.buffer.getUint8(offset) ^ mask;
- message.buffer.setUint8(offset, value);
- return this.realAccept(message);
- }
- stopSignalled = true;
- return false;
- };
-
- while (!stopSignalled) {
- dataPipe = core.createDataPipe(DATA_PIPE_PARAMS);
- messagePipe = core.createMessagePipe();
- writeDataPipe(dataPipe, sampleData);
- writeMessagePipe(messagePipe, sampleMessage);
- arg.data_handle = dataPipe.consumerHandle;
- arg.message_handle = messagePipe.handle1;
-
- this.cppSide_.bitFlipResponse(createEchoArgsList(arg));
-
- core.close(dataPipe.producerHandle);
- core.close(messagePipe.handle0);
- iteration += 1;
- }
-
- proto.accept = proto.realAccept;
- proto.realAccept = null;
- this.cppSide_.testFinished();
- };
-
- JsSideConnection.prototype.backPointer = function (arg) {
- var iteration = 0;
- var dataPipe;
- var messagePipe;
- var proto = connector.Connector.prototype;
- var stopSignalled = false;
-
- proto.realAccept = proto.accept;
- proto.accept = function (message) {
- var delta = 8 * (1 + iteration % 32);
- var offset = 8 * ((iteration / 32) | 0);
- if (offset < message.buffer.arrayBuffer.byteLength - 4) {
- message.buffer.dataView.setUint32(offset, 0x100000000 - delta, true);
- message.buffer.dataView.setUint32(offset + 4, 0xffffffff, true);
- return this.realAccept(message);
- }
- stopSignalled = true;
- return false;
- };
-
- while (!stopSignalled) {
- dataPipe = core.createDataPipe(DATA_PIPE_PARAMS);
- messagePipe = core.createMessagePipe();
- writeDataPipe(dataPipe, sampleData);
- writeMessagePipe(messagePipe, sampleMessage);
- arg.data_handle = dataPipe.consumerHandle;
- arg.message_handle = messagePipe.handle1;
-
- this.cppSide_.backPointerResponse(createEchoArgsList(arg));
-
- core.close(dataPipe.producerHandle);
- core.close(messagePipe.handle0);
- iteration += 1;
- }
-
- proto.accept = proto.realAccept;
- proto.realAccept = null;
- this.cppSide_.testFinished();
- };
-
- function writeDataPipe(pipe, data) {
- var writeResult = core.writeData(
- pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE);
-
- if (writeResult.result != core.RESULT_OK) {
- console.log('ERROR: Data pipe write result was ' + writeResult.result);
- return false;
- }
- if (writeResult.numBytes != data.length) {
- console.log('ERROR: Data pipe write length was ' + writeResult.numBytes);
- return false;
- }
- return true;
- }
-
- function writeMessagePipe(pipe, arrayBuffer) {
- var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0);
- if (result != core.RESULT_OK) {
- console.log('ERROR: Message pipe write result was ' + result);
- return false;
- }
- return true;
- }
-
- function createEchoArgsListElement(item, next) {
- var list = new jsToCpp.EchoArgsList();
- list.item = item;
- list.next = next;
- return list;
- }
-
- function createEchoArgsList() {
- var genuineArray = Array.prototype.slice.call(arguments);
- return genuineArray.reduceRight(function (previous, current) {
- return createEchoArgsListElement(current, previous);
- }, null);
- }
-
- function createCppSideConnection(handle, stubClass, proxyClass) {
- var c = new connection.Connection(handle, stubClass, proxyClass);
- c.local.cppSide_ = c.remote;
- return c;
- }
-
- return function(handle) {
- var i;
- sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes);
- for (i = 0; i < sampleData.length; ++i) {
- sampleData[i] = i;
- }
- sampleMessage = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes);
- for (i = 0; i < sampleMessage.length; ++i) {
- sampleMessage[i] = 255 - i;
- }
- retainedConnection = createCppSideConnection(
- handle, JsSideConnection,jsToCpp.CppSide.proxyClass);
- retainedConnection.remote.startTest();
- };
-});
diff --git a/mojo/edk/js/tests/sample_service_tests.js b/mojo/edk/js/tests/sample_service_tests.js
deleted file mode 100644
index 2afdf3e..0000000
--- a/mojo/edk/js/tests/sample_service_tests.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2013 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.
-
-define([
- "console",
- "mojo/edk/js/test/hexdump",
- "gin/test/expect",
- "mojo/public/interfaces/bindings/tests/sample_service.mojom",
- "mojo/public/interfaces/bindings/tests/sample_import.mojom",
- "mojo/public/interfaces/bindings/tests/sample_import2.mojom",
- "mojo/public/js/core",
- ], function(console, hexdump, expect, sample, imported, imported2, core) {
-
- var global = this;
-
- // Set this variable to true to print the binary message in hex.
- var dumpMessageAsHex = false;
-
- function makeFoo() {
- var bar = new sample.Bar();
- bar.alpha = 20;
- bar.beta = 40;
- bar.gamma = 60;
- bar.type = sample.Bar.Type.VERTICAL;
-
- var extra_bars = new Array(3);
- for (var i = 0; i < extra_bars.length; ++i) {
- var base = i * 100;
- var type = i % 2 ?
- sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
- extra_bars[i] = new sample.Bar();
- extra_bars[i].alpha = base;
- extra_bars[i].beta = base + 20;
- extra_bars[i].gamma = base + 40;
- extra_bars[i].type = type;
- }
-
- var data = new Array(10);
- for (var i = 0; i < data.length; ++i) {
- data[i] = data.length - i;
- }
-
- var source = 0xFFFF; // Invent a dummy handle.
-
- var foo = new sample.Foo();
- foo.name = "foopy";
- foo.x = 1;
- foo.y = 2;
- foo.a = false;
- foo.b = true;
- foo.c = false;
- foo.bar = bar;
- foo.extra_bars = extra_bars;
- foo.data = data;
- foo.source = source;
- return foo;
- }
-
- // Check that the given |Foo| is identical to the one made by |MakeFoo()|.
- function checkFoo(foo) {
- expect(foo.name).toBe("foopy");
- expect(foo.x).toBe(1);
- expect(foo.y).toBe(2);
- expect(foo.a).toBeFalsy();
- expect(foo.b).toBeTruthy();
- expect(foo.c).toBeFalsy();
- expect(foo.bar.alpha).toBe(20);
- expect(foo.bar.beta).toBe(40);
- expect(foo.bar.gamma).toBe(60);
- expect(foo.bar.type).toBe(sample.Bar.Type.VERTICAL);
-
- expect(foo.extra_bars.length).toBe(3);
- for (var i = 0; i < foo.extra_bars.length; ++i) {
- var base = i * 100;
- var type = i % 2 ?
- sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
- expect(foo.extra_bars[i].alpha).toBe(base);
- expect(foo.extra_bars[i].beta).toBe(base + 20);
- expect(foo.extra_bars[i].gamma).toBe(base + 40);
- expect(foo.extra_bars[i].type).toBe(type);
- }
-
- expect(foo.data.length).toBe(10);
- for (var i = 0; i < foo.data.length; ++i)
- expect(foo.data[i]).toBe(foo.data.length - i);
-
- expect(foo.source).toBe(0xFFFF);
- }
-
- // Check that values are set to the defaults if we don't override them.
- function checkDefaultValues() {
- var bar = new sample.Bar();
- expect(bar.alpha).toBe(255);
- expect(bar.type).toBe(sample.Bar.Type.VERTICAL);
-
- var foo = new sample.Foo();
- expect(foo.name).toBe("Fooby");
- expect(foo.a).toBeTruthy();
- expect(foo.data).toBeNull();
-
- var defaults = new sample.DefaultsTest();
- expect(defaults.a0).toBe(-12);
- expect(defaults.a1).toBe(sample.kTwelve);
- expect(defaults.a2).toBe(1234);
- expect(defaults.a3).toBe(34567);
- expect(defaults.a4).toBe(123456);
- expect(defaults.a5).toBe(3456789012);
- expect(defaults.a6).toBe(-111111111111);
- // JS doesn't have a 64 bit integer type so this is just checking that the
- // expected and actual values have the same closest double value.
- expect(defaults.a7).toBe(9999999999999999999);
- expect(defaults.a8).toBe(0x12345);
- expect(defaults.a9).toBe(-0x12345);
- expect(defaults.a10).toBe(1234);
- expect(defaults.a11).toBe(true);
- expect(defaults.a12).toBe(false);
- expect(defaults.a13).toBe(123.25);
- expect(defaults.a14).toBe(1234567890.123);
- expect(defaults.a15).toBe(1E10);
- expect(defaults.a16).toBe(-1.2E+20);
- expect(defaults.a17).toBe(1.23E-20);
- expect(defaults.a20).toBe(sample.Bar.Type.BOTH);
- expect(defaults.a21).toBeNull();
- expect(defaults.a22).toBeTruthy();
- expect(defaults.a22.shape).toBe(imported.Shape.RECTANGLE);
- expect(defaults.a22.color).toBe(imported2.Color.BLACK);
- expect(defaults.a21).toBeNull();
- expect(defaults.a23).toBe(0xFFFFFFFFFFFFFFFF);
- expect(defaults.a24).toBe(0x123456789);
- expect(defaults.a25).toBe(-0x123456789);
- }
-
- function ServiceImpl() {
- }
-
- ServiceImpl.prototype = Object.create(sample.Service.stubClass.prototype);
-
- ServiceImpl.prototype.frobinate = function(foo, baz, port) {
- checkFoo(foo);
- expect(baz).toBe(sample.Service.BazOptions.EXTRA);
- expect(core.isHandle(port)).toBeTruthy();
- global.result = "PASS";
- };
-
- function SimpleMessageReceiver() {
- }
-
- SimpleMessageReceiver.prototype.accept = function(message) {
- if (dumpMessageAsHex) {
- var uint8Array = new Uint8Array(message.buffer.arrayBuffer);
- console.log(hexdump.dumpArray(uint8Array));
- }
- // Imagine some IPC happened here.
- var serviceImpl = new ServiceImpl();
- serviceImpl.accept(message);
- };
-
- var serviceProxy = new sample.Service.proxyClass;
- serviceProxy.receiver_ = new SimpleMessageReceiver;
-
- checkDefaultValues();
-
- var foo = makeFoo();
- checkFoo(foo);
-
- var pipe = core.createMessagePipe();
- serviceProxy.frobinate(foo, sample.Service.BazOptions.EXTRA, pipe.handle0);
- expect(core.close(pipe.handle0)).toBe(core.RESULT_OK);
- expect(core.close(pipe.handle1)).toBe(core.RESULT_OK);
-});
diff --git a/mojo/edk/js/threading.cc b/mojo/edk/js/threading.cc
deleted file mode 100644
index b571e3e..0000000
--- a/mojo/edk/js/threading.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 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/js/threading.h"
-
-#include "base/message_loop/message_loop.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "mojo/edk/js/handle.h"
-
-namespace mojo {
-namespace js {
-
-namespace {
-
-void Quit() {
- base::MessageLoop::current()->QuitNow();
-}
-
-gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
-
-} // namespace
-
-const char Threading::kModuleName[] = "mojo/public/js/threading";
-
-v8::Local<v8::Value> Threading::GetModule(v8::Isolate* isolate) {
- gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
- v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(
- &g_wrapper_info);
-
- if (templ.IsEmpty()) {
- templ = gin::ObjectTemplateBuilder(isolate)
- .SetMethod("quit", Quit)
- .Build();
-
- data->SetObjectTemplate(&g_wrapper_info, templ);
- }
-
- return templ->NewInstance();
-}
-
-Threading::Threading() {
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/threading.h b/mojo/edk/js/threading.h
deleted file mode 100644
index 7cf0d53..0000000
--- a/mojo/edk/js/threading.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2013 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_EDK_JS_THREADING_H_
-#define MOJO_EDK_JS_THREADING_H_
-
-#include "gin/public/wrapper_info.h"
-#include "v8/include/v8.h"
-
-namespace mojo {
-namespace js {
-
-class Threading {
- public:
- static const char kModuleName[];
- static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
- private:
- Threading();
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_THREADING_H_
diff --git a/mojo/edk/js/waiting_callback.cc b/mojo/edk/js/waiting_callback.cc
deleted file mode 100644
index d5c48c5..0000000
--- a/mojo/edk/js/waiting_callback.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// 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/js/waiting_callback.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "gin/per_context_data.h"
-#include "mojo/public/cpp/environment/environment.h"
-
-namespace mojo {
-namespace js {
-
-namespace {
-
-v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
- return gin::StringToSymbol(isolate, "::mojo::js::WaitingCallback");
-}
-
-} // namespace
-
-gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin };
-
-// static
-gin::Handle<WaitingCallback> WaitingCallback::Create(
- v8::Isolate* isolate,
- v8::Handle<v8::Function> callback,
- gin::Handle<HandleWrapper> handle_wrapper,
- MojoHandleSignals signals) {
- gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle(
- isolate, new WaitingCallback(isolate, callback, handle_wrapper));
- waiting_callback->wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait(
- handle_wrapper->get().value(),
- signals,
- MOJO_DEADLINE_INDEFINITE,
- &WaitingCallback::CallOnHandleReady,
- waiting_callback.get());
- return waiting_callback;
-}
-
-void WaitingCallback::Cancel() {
- if (!wait_id_)
- return;
-
- handle_wrapper_->RemoveCloseObserver(this);
- handle_wrapper_ = NULL;
- Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
- wait_id_ = 0;
-}
-
-WaitingCallback::WaitingCallback(v8::Isolate* isolate,
- v8::Handle<v8::Function> callback,
- gin::Handle<HandleWrapper> handle_wrapper)
- : wait_id_(0), handle_wrapper_(handle_wrapper.get()), weak_factory_(this) {
- handle_wrapper_->AddCloseObserver(this);
- v8::Handle<v8::Context> context = isolate->GetCurrentContext();
- runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
- GetWrapper(isolate)->SetHiddenValue(GetHiddenPropertyName(isolate), callback);
-}
-
-WaitingCallback::~WaitingCallback() {
- Cancel();
-}
-
-// static
-void WaitingCallback::CallOnHandleReady(void* closure, MojoResult result) {
- static_cast<WaitingCallback*>(closure)->OnHandleReady(result);
-}
-
-void WaitingCallback::ClearWaitId() {
- wait_id_ = 0;
- handle_wrapper_->RemoveCloseObserver(this);
- handle_wrapper_ = nullptr;
-}
-
-void WaitingCallback::OnHandleReady(MojoResult result) {
- ClearWaitId();
- CallCallback(result);
-}
-
-void WaitingCallback::CallCallback(MojoResult result) {
- // ClearWaitId must already have been called.
- DCHECK(!wait_id_);
- DCHECK(!handle_wrapper_);
-
- if (!runner_)
- return;
-
- gin::Runner::Scope scope(runner_.get());
- v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
-
- v8::Handle<v8::Value> hidden_value =
- GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate));
- v8::Handle<v8::Function> callback;
- CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback));
-
- v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) };
- runner_->Call(callback, runner_->global(), 1, args);
-}
-
-void WaitingCallback::OnWillCloseHandle() {
- Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
-
- // This may be called from GC, so we can't execute Javascript now, call
- // ClearWaitId explicitly, and CallCallback asynchronously.
- ClearWaitId();
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&WaitingCallback::CallCallback, weak_factory_.GetWeakPtr(),
- MOJO_RESULT_INVALID_ARGUMENT));
-}
-
-} // namespace js
-} // namespace mojo
diff --git a/mojo/edk/js/waiting_callback.h b/mojo/edk/js/waiting_callback.h
deleted file mode 100644
index 5a9dfaf..0000000
--- a/mojo/edk/js/waiting_callback.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_JS_WAITING_CALLBACK_H_
-#define MOJO_EDK_JS_WAITING_CALLBACK_H_
-
-#include "base/memory/weak_ptr.h"
-#include "gin/handle.h"
-#include "gin/runner.h"
-#include "gin/wrappable.h"
-#include "mojo/edk/js/handle.h"
-#include "mojo/edk/js/handle_close_observer.h"
-#include "mojo/public/c/environment/async_waiter.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace js {
-
-class WaitingCallback : public gin::Wrappable<WaitingCallback>,
- public HandleCloseObserver {
- public:
- static gin::WrapperInfo kWrapperInfo;
-
- // Creates a new WaitingCallback.
- static gin::Handle<WaitingCallback> Create(
- v8::Isolate* isolate,
- v8::Handle<v8::Function> callback,
- gin::Handle<HandleWrapper> handle_wrapper,
- MojoHandleSignals signals);
-
- // Cancels the callback. Does nothing if a callback is not pending. This is
- // implicitly invoked from the destructor but can be explicitly invoked as
- // necessary.
- void Cancel();
-
- private:
- WaitingCallback(v8::Isolate* isolate,
- v8::Handle<v8::Function> callback,
- gin::Handle<HandleWrapper> handle_wrapper);
- ~WaitingCallback() override;
-
- // Callback from MojoAsyncWaiter. |closure| is the WaitingCallback.
- static void CallOnHandleReady(void* closure, MojoResult result);
-
- // Invoked from CallOnHandleReady() (CallOnHandleReady() must be static).
- void OnHandleReady(MojoResult result);
-
- // Invoked by the HandleWrapper if the handle is closed while this wait is
- // still in progress.
- void OnWillCloseHandle() override;
-
- void ClearWaitId();
- void CallCallback(MojoResult result);
-
- base::WeakPtr<gin::Runner> runner_;
- MojoAsyncWaitID wait_id_;
-
- HandleWrapper* handle_wrapper_;
- base::WeakPtrFactory<WaitingCallback> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(WaitingCallback);
-};
-
-} // namespace js
-} // namespace mojo
-
-#endif // MOJO_EDK_JS_WAITING_CALLBACK_H_
diff --git a/mojo/edk/mojo_edk.gni b/mojo/edk/mojo_edk.gni
deleted file mode 100644
index 1d1d992..0000000
--- a/mojo/edk/mojo_edk.gni
+++ /dev/null
@@ -1,95 +0,0 @@
-# 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.
-
-import("../public/mojo_sdk.gni")
-
-# A mojo_edk_source_set is a mojo_sdk_source_set that does not restrict
-# external dependencies and understands the following additional variables, all
-# of which admit a list of the relevant elements specified relative to the
-# location of the Mojo EDK:
-# mojo_edk_configs
-# allow_circular_mojo_edk_includes_from
-# mojo_edk_public_deps
-# mojo_edk_deps
-
-# Note that it is assumed that the Mojo EDK is a sibling of the Mojo SDK in a
-# client repo; the distinctions made above are for the sake of clarity in
-# writing targets.
-template("mojo_edk_source_set") {
- mojo_sdk_source_set(target_name) {
- restrict_external_deps = false
-
- if (defined(invoker.visibility)) {
- visibility = invoker.visibility
- }
- if (defined(invoker.mojo_edk_visibility)) {
- mojo_sdk_visibility = invoker.mojo_edk_visibility
- }
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- if (defined(invoker.sources)) {
- sources = invoker.sources
- }
- if (defined(invoker.defines)) {
- defines = invoker.defines
- }
- if (defined(invoker.public_configs)) {
- public_configs = invoker.public_configs
- }
-
- configs = []
- if (defined(invoker.configs)) {
- configs = invoker.configs
- }
- if (defined(invoker.mojo_edk_configs)) {
- foreach(edk_config, invoker.mojo_edk_configs) {
- # Check that the EDK config was not mistakenly given as an absolute
- # path.
- assert(get_path_info(edk_config, "abspath") != edk_config)
- configs += [ rebase_path(edk_config, ".", mojo_root) ]
- }
- }
-
- allow_circular_includes_from = []
- if (defined(invoker.allow_circular_includes_from)) {
- allow_circular_includes_from += invoker.allow_circular_includes_from
- }
- if (defined(invoker.allow_circular_mojo_edk_includes_from)) {
- foreach(edk_target, invoker.allow_circular_mojo_edk_includes_from) {
- # Check that the EDK target was not mistakenly given as an absolute
- # path.
- assert(get_path_info(edk_target, "abspath") != edk_target)
- allow_circular_includes_from +=
- [ rebase_path(edk_target, ".", mojo_root) ]
- }
- }
-
- if (defined(invoker.public_deps)) {
- public_deps = invoker.public_deps
- }
- mojo_sdk_public_deps = []
- if (defined(invoker.mojo_edk_public_deps)) {
- # The EDK is required to be a sibling of the SDK, so the relative
- # dependencies are rewritten in the same way.
- mojo_sdk_public_deps = invoker.mojo_edk_public_deps
- }
- if (defined(invoker.mojo_sdk_public_deps)) {
- mojo_sdk_public_deps += invoker.mojo_sdk_public_deps
- }
-
- if (defined(invoker.deps)) {
- deps = invoker.deps
- }
- mojo_sdk_deps = []
- if (defined(invoker.mojo_edk_deps)) {
- # The EDK is required to be a sibling of the SDK, so the relative
- # dependencies are rewritten in the same way.
- mojo_sdk_deps = invoker.mojo_edk_deps
- }
- if (defined(invoker.mojo_sdk_deps)) {
- mojo_sdk_deps += invoker.mojo_sdk_deps
- }
- }
-}
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
deleted file mode 100644
index 2f8abdd..0000000
--- a/mojo/edk/system/BUILD.gn
+++ /dev/null
@@ -1,209 +0,0 @@
-# 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.
-
-import("../mojo_edk.gni")
-
-if (is_android) {
- import("//build/config/android/config.gni")
- import("//build/config/android/rules.gni")
-}
-
-config("system_config") {
- defines = [
- # Ensures that dependent projects import the core functions on Windows.
- "MOJO_USE_SYSTEM_IMPL",
- ]
-}
-
-component("system") {
- output_name = "mojo_system_impl"
-
- sources = [
- "async_waiter.cc",
- "async_waiter.h",
- "awakable.h",
- "awakable_list.cc",
- "awakable_list.h",
- "channel.cc",
- "channel.h",
- "channel_endpoint.cc",
- "channel_endpoint.h",
- "channel_endpoint_client.h",
- "channel_endpoint_id.cc",
- "channel_endpoint_id.h",
- "channel_info.cc",
- "channel_info.h",
- "channel_manager.cc",
- "channel_manager.h",
- "configuration.cc",
- "configuration.h",
- "core.cc",
- "core.h",
- "data_pipe.cc",
- "data_pipe.h",
- "data_pipe_consumer_dispatcher.cc",
- "data_pipe_consumer_dispatcher.h",
- "data_pipe_producer_dispatcher.cc",
- "data_pipe_producer_dispatcher.h",
- "dispatcher.cc",
- "dispatcher.h",
- "endpoint_relayer.cc",
- "endpoint_relayer.h",
- "handle_signals_state.h",
- "handle_table.cc",
- "handle_table.h",
- "incoming_endpoint.cc",
- "incoming_endpoint.h",
- "local_data_pipe.cc",
- "local_data_pipe.h",
- "local_message_pipe_endpoint.cc",
- "local_message_pipe_endpoint.h",
- "mapping_table.cc",
- "mapping_table.h",
- "memory.cc",
- "memory.h",
- "message_in_transit.cc",
- "message_in_transit.h",
- "message_in_transit_queue.cc",
- "message_in_transit_queue.h",
- "message_pipe.cc",
- "message_pipe.h",
- "message_pipe_dispatcher.cc",
- "message_pipe_dispatcher.h",
- "message_pipe_endpoint.cc",
- "message_pipe_endpoint.h",
- "options_validation.h",
- "platform_handle_dispatcher.cc",
- "platform_handle_dispatcher.h",
- "proxy_message_pipe_endpoint.cc",
- "proxy_message_pipe_endpoint.h",
- "raw_channel.cc",
- "raw_channel.h",
- "raw_channel_posix.cc",
- "raw_channel_win.cc",
- "shared_buffer_dispatcher.cc",
- "shared_buffer_dispatcher.h",
- "simple_dispatcher.cc",
- "simple_dispatcher.h",
- "transport_data.cc",
- "transport_data.h",
- "unique_identifier.cc",
- "unique_identifier.h",
- "waiter.cc",
- "waiter.h",
- ]
-
- defines = [
- "MOJO_SYSTEM_IMPL_IMPLEMENTATION",
- "MOJO_SYSTEM_IMPLEMENTATION",
- ]
-
- all_dependent_configs = [ ":system_config" ]
-
- public_deps = [
- "../embedder",
- "../embedder:platform",
- "../../public/c/system",
- ]
-
- deps = [
- "//base",
- "//base/third_party/dynamic_annotations",
- "//crypto",
- ]
-
- allow_circular_includes_from = [ "../embedder" ]
-}
-
-mojo_edk_source_set("test_utils") {
- testonly = true
-
- sources = [
- "test_utils.cc",
- "test_utils.h",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- ]
-}
-
-# GYP version: mojo/edk/mojo_edk.gyp:mojo_system_unittests
-test("mojo_system_unittests") {
- sources = [
- "../test/multiprocess_test_helper_unittest.cc",
- "awakable_list_unittest.cc",
- "channel_endpoint_id_unittest.cc",
- "channel_manager_unittest.cc",
- "channel_unittest.cc",
- "core_test_base.cc",
- "core_test_base.h",
- "core_unittest.cc",
- "data_pipe_unittest.cc",
- "dispatcher_unittest.cc",
- "local_data_pipe_unittest.cc",
- "memory_unittest.cc",
- "message_pipe_dispatcher_unittest.cc",
- "message_pipe_test_utils.cc",
- "message_pipe_test_utils.h",
- "message_pipe_unittest.cc",
- "multiprocess_message_pipe_unittest.cc",
- "options_validation_unittest.cc",
- "platform_handle_dispatcher_unittest.cc",
- "raw_channel_unittest.cc",
- "remote_message_pipe_unittest.cc",
- "run_all_unittests.cc",
- "shared_buffer_dispatcher_unittest.cc",
- "simple_dispatcher_unittest.cc",
- "unique_identifier_unittest.cc",
- "waiter_test_utils.cc",
- "waiter_test_utils.h",
- "waiter_unittest.cc",
- ]
-
- deps = [
- ":system",
- ":test_utils",
- "../embedder:embedder_unittests",
- "../test:test_support",
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-
- if (is_android) {
- deps += [ "//testing/android:native_test_native_code" ]
- }
-
- allow_circular_includes_from = [ "../embedder:embedder_unittests" ]
-}
-
-# GYP version: mojo/edk/mojo_edk.gyp:mojo_message_pipe_perftests
-test("mojo_message_pipe_perftests") {
- sources = [
- "message_pipe_perftest.cc",
- "message_pipe_test_utils.h",
- "message_pipe_test_utils.cc",
- ]
-
- deps = [
- ":system",
- ":test_utils",
- "../test:test_support",
- "//base",
- "//base/test:test_support",
- "//base/test:test_support_perf",
- "//testing/gtest",
- ]
-}
-
-if (is_android) {
- unittest_apk("mojo_system_unittests_apk") {
- deps = [
- ":mojo_system_unittests",
- ]
- unittests_dep = ":mojo_system_unittests"
- }
-}
diff --git a/mojo/edk/system/DEPS b/mojo/edk/system/DEPS
deleted file mode 100644
index 4ef4138..0000000
--- a/mojo/edk/system/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+crypto",
-]
diff --git a/mojo/edk/system/async_waiter.cc b/mojo/edk/system/async_waiter.cc
deleted file mode 100644
index 071eb01..0000000
--- a/mojo/edk/system/async_waiter.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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/async_waiter.h"
-
-namespace mojo {
-namespace system {
-
-AsyncWaiter::AsyncWaiter(AwakeCallback callback) : callback_(callback) {
-}
-
-AsyncWaiter::~AsyncWaiter() {
-}
-
-bool AsyncWaiter::Awake(MojoResult result, uintptr_t context) {
- callback_.Run(result);
- delete this;
- return false;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/async_waiter.h b/mojo/edk/system/async_waiter.h
deleted file mode 100644
index da412c0..0000000
--- a/mojo/edk/system/async_waiter.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_ASYNC_WAITER_H_
-#define MOJO_EDK_SYSTEM_ASYNC_WAITER_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "mojo/edk/system/awakable.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-// An |Awakable| implementation that just calls a given callback object.
-class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable {
- public:
- typedef base::Callback<void(MojoResult)> AwakeCallback;
-
- // |callback| must satisfy the same contract as |Awakable::Awake()|.
- explicit AsyncWaiter(AwakeCallback callback);
- virtual ~AsyncWaiter();
-
- private:
- // |Awakable| implementation:
- bool Awake(MojoResult result, uintptr_t context) override;
-
- AwakeCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncWaiter);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_ASYNC_WAITER_H_
diff --git a/mojo/edk/system/awakable.h b/mojo/edk/system/awakable.h
deleted file mode 100644
index 057d3eb..0000000
--- a/mojo/edk/system/awakable.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_AWAKABLE_H_
-#define MOJO_EDK_SYSTEM_AWAKABLE_H_
-
-#include <stdint.h>
-
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-// An interface that may be waited on |AwakableList|.
-class MOJO_SYSTEM_IMPL_EXPORT Awakable {
- public:
- // |Awake()| must satisfy the following contract:
- // * As this is called from any thread, this must be thread-safe.
- // * As this is called inside a lock, this must not call anything that takes
- // "non-terminal" locks, i.e., those which are always safe to take.
- // This should return false if this must not be called again for the same
- // reason (e.g., for the same call to |AwakableList::Add()|).
- virtual bool Awake(MojoResult result, uintptr_t context) = 0;
-
- protected:
- Awakable() {}
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_AWAKABLE_H_
diff --git a/mojo/edk/system/awakable_list.cc b/mojo/edk/system/awakable_list.cc
deleted file mode 100644
index e74e2c0..0000000
--- a/mojo/edk/system/awakable_list.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 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/awakable_list.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/awakable.h"
-#include "mojo/edk/system/handle_signals_state.h"
-
-namespace mojo {
-namespace system {
-
-AwakableList::AwakableList() {
-}
-
-AwakableList::~AwakableList() {
- DCHECK(awakables_.empty());
-}
-
-void AwakableList::AwakeForStateChange(const HandleSignalsState& state) {
- for (AwakeInfoList::iterator it = awakables_.begin();
- it != awakables_.end();) {
- bool keep = true;
- if (state.satisfies(it->signals))
- keep = it->awakable->Awake(MOJO_RESULT_OK, it->context);
- else if (!state.can_satisfy(it->signals))
- keep = it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context);
- AwakeInfoList::iterator maybe_delete = it;
- ++it;
-
- if (!keep)
- awakables_.erase(maybe_delete);
- }
-}
-
-void AwakableList::CancelAll() {
- for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end();
- ++it) {
- it->awakable->Awake(MOJO_RESULT_CANCELLED, it->context);
- }
- awakables_.clear();
-}
-
-void AwakableList::Add(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context) {
- awakables_.push_back(AwakeInfo(awakable, signals, context));
-}
-
-void AwakableList::Remove(Awakable* awakable) {
- // We allow a thread to wait on the same handle multiple times simultaneously,
- // so we need to scan the entire list and remove all occurrences of |waiter|.
- for (AwakeInfoList::iterator it = awakables_.begin();
- it != awakables_.end();) {
- AwakeInfoList::iterator maybe_delete = it;
- ++it;
- if (maybe_delete->awakable == awakable)
- awakables_.erase(maybe_delete);
- }
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/awakable_list.h b/mojo/edk/system/awakable_list.h
deleted file mode 100644
index 19c03c8..0000000
--- a/mojo/edk/system/awakable_list.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_AWAKABLE_LIST_H_
-#define MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_
-
-#include <stdint.h>
-
-#include <list>
-
-#include "base/macros.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-class Awakable;
-struct HandleSignalsState;
-
-// |AwakableList| tracks all the |Waiter|s that are waiting on a given
-// handle/|Dispatcher|. There should be a |AwakableList| for each handle that
-// can be waited on (in any way). In the simple case, the |AwakableList| is
-// owned by the |Dispatcher|, whereas in more complex cases it is owned by the
-// secondary object (see simple_dispatcher.* and the explanatory comment in
-// core.cc). This class is thread-unsafe (all concurrent access must be
-// protected by some lock).
-class MOJO_SYSTEM_IMPL_EXPORT AwakableList {
- public:
- AwakableList();
- ~AwakableList();
-
- void AwakeForStateChange(const HandleSignalsState& state);
- void CancelAll();
- void Add(Awakable* awakable, MojoHandleSignals signals, uint32_t context);
- void Remove(Awakable* awakable);
-
- private:
- struct AwakeInfo {
- AwakeInfo(Awakable* awakable, MojoHandleSignals signals, uint32_t context)
- : awakable(awakable), signals(signals), context(context) {}
-
- Awakable* awakable;
- MojoHandleSignals signals;
- uint32_t context;
- };
- typedef std::list<AwakeInfo> AwakeInfoList;
-
- AwakeInfoList awakables_;
-
- DISALLOW_COPY_AND_ASSIGN(AwakableList);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_
diff --git a/mojo/edk/system/awakable_list_unittest.cc b/mojo/edk/system/awakable_list_unittest.cc
deleted file mode 100644
index 0ef6a7a..0000000
--- a/mojo/edk/system/awakable_list_unittest.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2013 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.
-
-// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
-// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
-// increase tolerance and reduce observed flakiness (though doing so reduces the
-// meaningfulness of the test).
-
-#include "mojo/edk/system/awakable_list.h"
-
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/time/time.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/system/waiter_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-TEST(AwakableListTest, BasicCancel) {
- MojoResult result;
- uint32_t context;
-
- // Cancel immediately after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
- thread.Start();
- awakable_list.CancelAll();
- // Double-remove okay:
- awakable_list.Remove(thread.waiter());
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(1u, context);
-
- // Cancel before after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
- awakable_list.CancelAll();
- thread.Start();
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(2u, context);
-
- // Cancel some time after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.CancelAll();
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(3u, context);
-}
-
-TEST(AwakableListTest, BasicAwakeSatisfied) {
- MojoResult result;
- uint32_t context;
-
- // Awake immediately after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
- thread.Start();
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread.waiter());
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(1u, context);
-
- // Awake before after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread.waiter());
- // Double-remove okay:
- awakable_list.Remove(thread.waiter());
- thread.Start();
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(2u, context);
-
- // Awake some time after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread.waiter());
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(3u, context);
-}
-
-TEST(AwakableListTest, BasicAwakeUnsatisfiable) {
- MojoResult result;
- uint32_t context;
-
- // Awake (for unsatisfiability) immediately after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
- thread.Start();
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread.waiter());
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(1u, context);
-
- // Awake (for unsatisfiability) before after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE));
- awakable_list.Remove(thread.waiter());
- thread.Start();
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(2u, context);
-
- // Awake (for unsatisfiability) some time after thread start.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread(&result, &context);
- awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread.waiter());
- // Double-remove okay:
- awakable_list.Remove(thread.waiter());
- } // Join |thread|.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(3u, context);
-}
-
-TEST(AwakableListTest, MultipleAwakables) {
- MojoResult result1;
- MojoResult result2;
- MojoResult result3;
- MojoResult result4;
- uint32_t context1;
- uint32_t context2;
- uint32_t context3;
- uint32_t context4;
-
- // Cancel two awakables.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread1(&result1, &context1);
- awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
- thread1.Start();
- test::SimpleWaiterThread thread2(&result2, &context2);
- awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
- thread2.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.CancelAll();
- } // Join threads.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
- EXPECT_EQ(1u, context1);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
- EXPECT_EQ(2u, context2);
-
- // Awake one awakable, cancel other.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread1(&result1, &context1);
- awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
- thread1.Start();
- test::SimpleWaiterThread thread2(&result2, &context2);
- awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4);
- thread2.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread1.waiter());
- awakable_list.CancelAll();
- } // Join threads.
- EXPECT_EQ(MOJO_RESULT_OK, result1);
- EXPECT_EQ(3u, context1);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
- EXPECT_EQ(4u, context2);
-
- // Cancel one awakable, awake other for unsatisfiability.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread1(&result1, &context1);
- awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5);
- thread1.Start();
- test::SimpleWaiterThread thread2(&result2, &context2);
- awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6);
- thread2.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE));
- awakable_list.Remove(thread2.waiter());
- awakable_list.CancelAll();
- } // Join threads.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
- EXPECT_EQ(5u, context1);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2);
- EXPECT_EQ(6u, context2);
-
- // Cancel one awakable, awake other for unsatisfiability.
- {
- AwakableList awakable_list;
- test::SimpleWaiterThread thread1(&result1, &context1);
- awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7);
- thread1.Start();
-
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
-
- // Should do nothing.
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_NONE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
-
- test::SimpleWaiterThread thread2(&result2, &context2);
- awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8);
- thread2.Start();
-
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
-
- // Awake #1.
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
- awakable_list.Remove(thread1.waiter());
-
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
-
- test::SimpleWaiterThread thread3(&result3, &context3);
- awakable_list.Add(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9);
- thread3.Start();
-
- test::SimpleWaiterThread thread4(&result4, &context4);
- awakable_list.Add(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10);
- thread4.Start();
-
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
-
- // Awake #2 and #3 for unsatisfiability.
- awakable_list.AwakeForStateChange(HandleSignalsState(
- MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE));
- awakable_list.Remove(thread2.waiter());
- awakable_list.Remove(thread3.waiter());
-
- // Cancel #4.
- awakable_list.CancelAll();
- } // Join threads.
- EXPECT_EQ(MOJO_RESULT_OK, result1);
- EXPECT_EQ(7u, context1);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2);
- EXPECT_EQ(8u, context2);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3);
- EXPECT_EQ(9u, context3);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result4);
- EXPECT_EQ(10u, context4);
-}
-
-class KeepAwakable : public Awakable {
- public:
- KeepAwakable() : awake_count(0) {}
-
- bool Awake(MojoResult result, uintptr_t context) override {
- awake_count++;
- return true;
- }
-
- int awake_count;
-
- DISALLOW_COPY_AND_ASSIGN(KeepAwakable);
-};
-
-class RemoveAwakable : public Awakable {
- public:
- RemoveAwakable() : awake_count(0) {}
-
- bool Awake(MojoResult result, uintptr_t context) override {
- awake_count++;
- return false;
- }
-
- int awake_count;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveAwakable);
-};
-
-TEST(AwakableListTest, KeepAwakablesReturningTrue) {
- KeepAwakable keep0;
- KeepAwakable keep1;
- RemoveAwakable remove0;
- RemoveAwakable remove1;
- RemoveAwakable remove2;
-
- HandleSignalsState hss(MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_HANDLE_SIGNAL_WRITABLE);
-
- AwakableList remove_all;
- remove_all.Add(&remove0, MOJO_HANDLE_SIGNAL_WRITABLE, 0);
- remove_all.Add(&remove1, MOJO_HANDLE_SIGNAL_WRITABLE, 0);
-
- remove_all.AwakeForStateChange(hss);
- EXPECT_EQ(remove0.awake_count, 1);
- EXPECT_EQ(remove1.awake_count, 1);
-
- remove_all.AwakeForStateChange(hss);
- EXPECT_EQ(remove0.awake_count, 1);
- EXPECT_EQ(remove1.awake_count, 1);
-
- AwakableList remove_first;
- remove_first.Add(&remove2, MOJO_HANDLE_SIGNAL_WRITABLE, 0);
- remove_first.Add(&keep0, MOJO_HANDLE_SIGNAL_WRITABLE, 0);
- remove_first.Add(&keep1, MOJO_HANDLE_SIGNAL_WRITABLE, 0);
-
- remove_first.AwakeForStateChange(hss);
- EXPECT_EQ(keep0.awake_count, 1);
- EXPECT_EQ(keep1.awake_count, 1);
- EXPECT_EQ(remove2.awake_count, 1);
-
- remove_first.AwakeForStateChange(hss);
- EXPECT_EQ(keep0.awake_count, 2);
- EXPECT_EQ(keep1.awake_count, 2);
- EXPECT_EQ(remove2.awake_count, 1);
-
- remove_first.Remove(&keep0);
- remove_first.Remove(&keep1);
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
deleted file mode 100644
index 71d7208..0000000
--- a/mojo/edk/system/channel.cc
+++ /dev/null
@@ -1,604 +0,0 @@
-// Copyright 2013 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/channel.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/system/endpoint_relayer.h"
-#include "mojo/edk/system/transport_data.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-struct SerializedEndpoint {
- // This is the endpoint ID on the receiving side, and should be a "remote ID".
- // (The receiving side should already have had an endpoint attached and been
- // run via the |Channel|s. This endpoint will have both IDs assigned, so this
- // ID is only needed to associate that endpoint with a particular dispatcher.)
- ChannelEndpointId receiver_endpoint_id;
-};
-
-} // namespace
-
-Channel::Channel(embedder::PlatformSupport* platform_support)
- : platform_support_(platform_support),
- is_running_(false),
- is_shutting_down_(false),
- channel_manager_(nullptr) {
-}
-
-void Channel::Init(scoped_ptr<RawChannel> raw_channel) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
- DCHECK(raw_channel);
-
- // No need to take |lock_|, since this must be called before this object
- // becomes thread-safe.
- DCHECK(!is_running_);
- raw_channel_ = raw_channel.Pass();
- raw_channel_->Init(this);
- is_running_ = true;
-}
-
-void Channel::SetChannelManager(ChannelManager* channel_manager) {
- DCHECK(channel_manager);
-
- base::AutoLock locker(lock_);
- DCHECK(!is_shutting_down_);
- DCHECK(!channel_manager_);
- channel_manager_ = channel_manager;
-}
-
-void Channel::Shutdown() {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
-
- IdToEndpointMap to_destroy;
- {
- base::AutoLock locker(lock_);
- if (!is_running_)
- return;
-
- // Note: Don't reset |raw_channel_|, in case we're being called from within
- // |OnReadMessage()| or |OnError()|.
- raw_channel_->Shutdown();
- is_running_ = false;
-
- // We need to deal with it outside the lock.
- std::swap(to_destroy, local_id_to_endpoint_map_);
- }
-
- size_t num_live = 0;
- size_t num_zombies = 0;
- for (IdToEndpointMap::iterator it = to_destroy.begin();
- it != to_destroy.end(); ++it) {
- if (it->second) {
- num_live++;
- it->second->DetachFromChannel();
- } else {
- num_zombies++;
- }
- }
- DVLOG_IF(2, num_live || num_zombies) << "Shut down Channel with " << num_live
- << " live endpoints and " << num_zombies
- << " zombies";
-}
-
-void Channel::WillShutdownSoon() {
- base::AutoLock locker(lock_);
- is_shutting_down_ = true;
- channel_manager_ = nullptr;
-}
-
-void Channel::SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint) {
- DCHECK(endpoint);
-
- // Used for both local and remote IDs.
- ChannelEndpointId bootstrap_id = ChannelEndpointId::GetBootstrap();
-
- {
- base::AutoLock locker(lock_);
-
- DLOG_IF(WARNING, is_shutting_down_)
- << "SetBootstrapEndpoint() while shutting down";
-
- // Bootstrap endpoint should be the first.
- DCHECK(local_id_to_endpoint_map_.empty());
-
- local_id_to_endpoint_map_[bootstrap_id] = endpoint;
- }
-
- endpoint->AttachAndRun(this, bootstrap_id, bootstrap_id);
-}
-
-bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) {
- base::AutoLock locker(lock_);
- if (!is_running_) {
- // TODO(vtl): I think this is probably not an error condition, but I should
- // think about it (and the shutdown sequence) more carefully.
- LOG(WARNING) << "WriteMessage() after shutdown";
- return false;
- }
-
- DLOG_IF(WARNING, is_shutting_down_) << "WriteMessage() while shutting down";
- return raw_channel_->WriteMessage(message.Pass());
-}
-
-bool Channel::IsWriteBufferEmpty() {
- base::AutoLock locker(lock_);
- if (!is_running_)
- return true;
- return raw_channel_->IsWriteBufferEmpty();
-}
-
-void Channel::DetachEndpoint(ChannelEndpoint* endpoint,
- ChannelEndpointId local_id,
- ChannelEndpointId remote_id) {
- DCHECK(endpoint);
- DCHECK(local_id.is_valid());
-
- if (!remote_id.is_valid())
- return; // Nothing to do.
-
- {
- base::AutoLock locker_(lock_);
- if (!is_running_)
- return;
-
- IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
- // We detach immediately if we receive a remove message, so it's possible
- // that the local ID is no longer in |local_id_to_endpoint_map_|, or even
- // that it's since been reused for another endpoint. In both cases, there's
- // nothing more to do.
- if (it == local_id_to_endpoint_map_.end() || it->second.get() != endpoint)
- return;
-
- DCHECK(it->second);
- it->second = nullptr;
-
- // Send a remove message outside the lock.
- }
-
- if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpoint,
- local_id, remote_id)) {
- HandleLocalError(base::StringPrintf(
- "Failed to send message to remove remote endpoint (local ID %u, remote "
- "ID %u)",
- static_cast<unsigned>(local_id.value()),
- static_cast<unsigned>(remote_id.value())));
- }
-}
-
-size_t Channel::GetSerializedEndpointSize() const {
- return sizeof(SerializedEndpoint);
-}
-
-void Channel::SerializeEndpointWithClosedPeer(
- void* destination,
- MessageInTransitQueue* message_queue) {
- // We can actually just pass no client to |SerializeEndpointWithLocalPeer()|.
- SerializeEndpointWithLocalPeer(destination, message_queue, nullptr, 0);
-}
-
-scoped_refptr<ChannelEndpoint> Channel::SerializeEndpointWithLocalPeer(
- void* destination,
- MessageInTransitQueue* message_queue,
- ChannelEndpointClient* endpoint_client,
- unsigned endpoint_client_port) {
- DCHECK(destination);
- // Allow |endpoint_client| to be null, for use by
- // |SerializeEndpointWithClosedPeer()|.
-
- scoped_refptr<ChannelEndpoint> endpoint(new ChannelEndpoint(
- endpoint_client, endpoint_client_port, message_queue));
-
- SerializedEndpoint* s = static_cast<SerializedEndpoint*>(destination);
- s->receiver_endpoint_id = AttachAndRunEndpoint(endpoint);
- DVLOG(2) << "Serializing endpoint with local or closed peer (remote ID = "
- << s->receiver_endpoint_id << ")";
-
- return endpoint;
-}
-
-void Channel::SerializeEndpointWithRemotePeer(
- void* destination,
- MessageInTransitQueue* message_queue,
- scoped_refptr<ChannelEndpoint> peer_endpoint) {
- DCHECK(destination);
- DCHECK(peer_endpoint);
-
- DLOG(WARNING) << "Direct message pipe passing across multiple channels not "
- "yet implemented; will proxy";
- // Create and set up an |EndpointRelayer| to proxy.
- // TODO(vtl): If we were to own/track the relayer directly (rather than owning
- // it via its |ChannelEndpoint|s), then we might be able to make
- // |ChannelEndpoint|'s |client_| pointer a raw pointer.
- scoped_refptr<EndpointRelayer> relayer(new EndpointRelayer());
- scoped_refptr<ChannelEndpoint> endpoint(
- new ChannelEndpoint(relayer.get(), 0, message_queue));
- relayer->Init(endpoint.get(), peer_endpoint.get());
- peer_endpoint->ReplaceClient(relayer.get(), 1);
-
- SerializedEndpoint* s = static_cast<SerializedEndpoint*>(destination);
- s->receiver_endpoint_id = AttachAndRunEndpoint(endpoint);
- DVLOG(2) << "Serializing endpoint with remote peer (remote ID = "
- << s->receiver_endpoint_id << ")";
-}
-
-scoped_refptr<IncomingEndpoint> Channel::DeserializeEndpoint(
- const void* source) {
- const SerializedEndpoint* s = static_cast<const SerializedEndpoint*>(source);
- ChannelEndpointId local_id = s->receiver_endpoint_id;
- // No need to check the validity of |local_id| -- if it's not valid, it simply
- // won't be in |incoming_endpoints_|.
- DVLOG_IF(2, !local_id.is_valid() || !local_id.is_remote())
- << "Attempt to get incoming endpoint for invalid ID " << local_id;
-
- base::AutoLock locker(lock_);
-
- auto it = incoming_endpoints_.find(local_id);
- if (it == incoming_endpoints_.end()) {
- LOG(ERROR) << "Failed to deserialize endpoint (ID = " << local_id << ")";
- return nullptr;
- }
-
- DVLOG(2) << "Deserializing endpoint (new local ID = " << local_id << ")";
-
- scoped_refptr<IncomingEndpoint> rv;
- rv.swap(it->second);
- incoming_endpoints_.erase(it);
- return rv;
-}
-
-size_t Channel::GetSerializedPlatformHandleSize() const {
- return raw_channel_->GetSerializedPlatformHandleSize();
-}
-
-Channel::~Channel() {
- // The channel should have been shut down first.
- DCHECK(!is_running_);
-}
-
-void Channel::OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
-
- switch (message_view.type()) {
- case MessageInTransit::kTypeEndpoint:
- OnReadMessageForEndpoint(message_view, platform_handles.Pass());
- break;
- case MessageInTransit::kTypeChannel:
- OnReadMessageForChannel(message_view, platform_handles.Pass());
- break;
- default:
- HandleRemoteError(
- base::StringPrintf("Received message of invalid type %u",
- static_cast<unsigned>(message_view.type())));
- break;
- }
-}
-
-void Channel::OnError(Error error) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
-
- switch (error) {
- case ERROR_READ_SHUTDOWN:
- // The other side was cleanly closed, so this isn't actually an error.
- DVLOG(1) << "RawChannel read error (shutdown)";
- break;
- case ERROR_READ_BROKEN: {
- base::AutoLock locker(lock_);
- LOG_IF(ERROR, !is_shutting_down_)
- << "RawChannel read error (connection broken)";
- break;
- }
- case ERROR_READ_BAD_MESSAGE:
- // Receiving a bad message means either a bug, data corruption, or
- // malicious attack (probably due to some other bug).
- LOG(ERROR) << "RawChannel read error (received bad message)";
- break;
- case ERROR_READ_UNKNOWN:
- LOG(ERROR) << "RawChannel read error (unknown)";
- break;
- case ERROR_WRITE:
- // Write errors are slightly notable: they probably shouldn't happen under
- // normal operation (but maybe the other side crashed).
- LOG(WARNING) << "RawChannel write error";
- break;
- }
- Shutdown();
-}
-
-void Channel::OnReadMessageForEndpoint(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
- DCHECK(message_view.type() == MessageInTransit::kTypeEndpoint);
-
- ChannelEndpointId local_id = message_view.destination_id();
- if (!local_id.is_valid()) {
- HandleRemoteError("Received message with no destination ID");
- return;
- }
-
- scoped_refptr<ChannelEndpoint> endpoint;
- {
- base::AutoLock locker(lock_);
-
- // Since we own |raw_channel_|, and this method and |Shutdown()| should only
- // be called from the creation thread, |raw_channel_| should never be null
- // here.
- DCHECK(is_running_);
-
- IdToEndpointMap::const_iterator it =
- local_id_to_endpoint_map_.find(local_id);
- if (it != local_id_to_endpoint_map_.end()) {
- // Ignore messages for zombie endpoints (not an error).
- if (!it->second) {
- DVLOG(2) << "Ignoring downstream message for zombie endpoint (local ID "
- "= " << local_id
- << ", remote ID = " << message_view.source_id() << ")";
- return;
- }
-
- endpoint = it->second;
- }
- }
- if (!endpoint) {
- HandleRemoteError(base::StringPrintf(
- "Received a message for nonexistent local destination ID %u",
- static_cast<unsigned>(local_id.value())));
- // This is strongly indicative of some problem. However, it's not a fatal
- // error, since it may indicate a buggy (or hostile) remote process. Don't
- // die even for Debug builds, since handling this properly needs to be
- // tested (TODO(vtl)).
- DLOG(ERROR) << "This should not happen under normal operation.";
- return;
- }
-
- scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view));
- if (message_view.transport_data_buffer_size() > 0) {
- DCHECK(message_view.transport_data_buffer());
- message->SetDispatchers(TransportData::DeserializeDispatchers(
- message_view.transport_data_buffer(),
- message_view.transport_data_buffer_size(), platform_handles.Pass(),
- this));
- }
-
- endpoint->OnReadMessage(message.Pass());
-}
-
-void Channel::OnReadMessageForChannel(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(message_view.type(), MessageInTransit::kTypeChannel);
-
- // Currently, no channel messages take platform handles.
- if (platform_handles) {
- HandleRemoteError(
- "Received invalid channel message (has platform handles)");
- NOTREACHED();
- return;
- }
-
- switch (message_view.subtype()) {
- case MessageInTransit::kSubtypeChannelAttachAndRunEndpoint:
- DVLOG(2) << "Handling channel message to attach and run endpoint (local "
- "ID " << message_view.destination_id() << ", remote ID "
- << message_view.source_id() << ")";
- if (!OnAttachAndRunEndpoint(message_view.destination_id(),
- message_view.source_id())) {
- HandleRemoteError(
- "Received invalid channel message to attach and run endpoint");
- }
- break;
- case MessageInTransit::kSubtypeChannelRemoveEndpoint:
- DVLOG(2) << "Handling channel message to remove endpoint (local ID "
- << message_view.destination_id() << ", remote ID "
- << message_view.source_id() << ")";
- if (!OnRemoveEndpoint(message_view.destination_id(),
- message_view.source_id())) {
- HandleRemoteError(
- "Received invalid channel message to remove endpoint");
- }
- break;
- case MessageInTransit::kSubtypeChannelRemoveEndpointAck:
- DVLOG(2) << "Handling channel message to ack remove endpoint (local ID "
- << message_view.destination_id() << ", remote ID "
- << message_view.source_id() << ")";
- if (!OnRemoveEndpointAck(message_view.destination_id())) {
- HandleRemoteError(
- "Received invalid channel message to ack remove endpoint");
- }
- break;
- default:
- HandleRemoteError("Received invalid channel message");
- NOTREACHED();
- break;
- }
-}
-
-bool Channel::OnAttachAndRunEndpoint(ChannelEndpointId local_id,
- ChannelEndpointId remote_id) {
- // We should only get this for remotely-created local endpoints, so our local
- // ID should be "remote".
- if (!local_id.is_valid() || !local_id.is_remote()) {
- DVLOG(2) << "Received attach and run endpoint with invalid local ID";
- return false;
- }
-
- // Conversely, the remote end should be "local".
- if (!remote_id.is_valid() || remote_id.is_remote()) {
- DVLOG(2) << "Received attach and run endpoint with invalid remote ID";
- return false;
- }
-
- // Create/initialize an |IncomingEndpoint| and thus an endpoint (outside the
- // lock).
- scoped_refptr<IncomingEndpoint> incoming_endpoint(new IncomingEndpoint());
- scoped_refptr<ChannelEndpoint> endpoint = incoming_endpoint->Init();
-
- bool success = true;
- {
- base::AutoLock locker(lock_);
-
- if (local_id_to_endpoint_map_.find(local_id) ==
- local_id_to_endpoint_map_.end()) {
- DCHECK(incoming_endpoints_.find(local_id) == incoming_endpoints_.end());
-
- // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll
- // avoid some refcount churn.)
- local_id_to_endpoint_map_[local_id] = endpoint;
- incoming_endpoints_[local_id] = incoming_endpoint;
- } else {
- // We need to call |Close()| outside the lock.
- success = false;
- }
- }
- if (!success) {
- DVLOG(2) << "Received attach and run endpoint for existing local ID";
- incoming_endpoint->Close();
- return false;
- }
-
- endpoint->AttachAndRun(this, local_id, remote_id);
- return true;
-}
-
-bool Channel::OnRemoveEndpoint(ChannelEndpointId local_id,
- ChannelEndpointId remote_id) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
-
- scoped_refptr<ChannelEndpoint> endpoint;
- {
- base::AutoLock locker(lock_);
-
- IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
- if (it == local_id_to_endpoint_map_.end()) {
- DVLOG(2) << "Remove endpoint error: not found";
- return false;
- }
-
- if (!it->second) {
- // Remove messages "crossed"; we have to wait for the ack.
- return true;
- }
-
- endpoint = it->second;
- local_id_to_endpoint_map_.erase(it);
- // Detach and send the remove ack message outside the lock.
- }
-
- endpoint->DetachFromChannel();
-
- if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpointAck,
- local_id, remote_id)) {
- HandleLocalError(base::StringPrintf(
- "Failed to send message to ack remove remote endpoint (local ID %u, "
- "remote ID %u)",
- static_cast<unsigned>(local_id.value()),
- static_cast<unsigned>(remote_id.value())));
- }
-
- return true;
-}
-
-bool Channel::OnRemoveEndpointAck(ChannelEndpointId local_id) {
- DCHECK(creation_thread_checker_.CalledOnValidThread());
-
- base::AutoLock locker(lock_);
-
- IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
- if (it == local_id_to_endpoint_map_.end()) {
- DVLOG(2) << "Remove endpoint ack error: not found";
- return false;
- }
-
- if (it->second) {
- DVLOG(2) << "Remove endpoint ack error: wrong state";
- return false;
- }
-
- local_id_to_endpoint_map_.erase(it);
- return true;
-}
-
-void Channel::HandleRemoteError(const base::StringPiece& error_message) {
- // TODO(vtl): Is this how we really want to handle this? Probably we want to
- // terminate the connection, since it's spewing invalid stuff.
- LOG(WARNING) << error_message;
-}
-
-void Channel::HandleLocalError(const base::StringPiece& error_message) {
- // TODO(vtl): Is this how we really want to handle this?
- // Sometimes we'll want to propagate the error back to the message pipe
- // (endpoint), and notify it that the remote is (effectively) closed.
- // Sometimes we'll want to kill the channel (and notify all the endpoints that
- // their remotes are dead.
- LOG(WARNING) << error_message;
-}
-
-// Note: |endpoint| being a |scoped_refptr| makes this function safe, since it
-// keeps the endpoint alive even after the lock is released. Otherwise, there's
-// the temptation to simply pass the result of |new ChannelEndpoint(...)|
-// directly to this function, which wouldn't be sufficient for safety.
-ChannelEndpointId Channel::AttachAndRunEndpoint(
- scoped_refptr<ChannelEndpoint> endpoint) {
- DCHECK(endpoint);
-
- ChannelEndpointId local_id;
- ChannelEndpointId remote_id;
- {
- base::AutoLock locker(lock_);
-
- DLOG_IF(WARNING, is_shutting_down_)
- << "AttachAndRunEndpoint() while shutting down";
-
- do {
- local_id = local_id_generator_.GetNext();
- } while (local_id_to_endpoint_map_.find(local_id) !=
- local_id_to_endpoint_map_.end());
-
- // TODO(vtl): We also need to check for collisions of remote IDs here.
- remote_id = remote_id_generator_.GetNext();
-
- local_id_to_endpoint_map_[local_id] = endpoint;
- }
-
- if (!SendControlMessage(MessageInTransit::kSubtypeChannelAttachAndRunEndpoint,
- local_id, remote_id)) {
- HandleLocalError(base::StringPrintf(
- "Failed to send message to run remote endpoint (local ID %u, remote ID "
- "%u)",
- static_cast<unsigned>(local_id.value()),
- static_cast<unsigned>(remote_id.value())));
- // TODO(vtl): Should we continue on to |AttachAndRun()|?
- }
-
- endpoint->AttachAndRun(this, local_id, remote_id);
- return remote_id;
-}
-
-bool Channel::SendControlMessage(MessageInTransit::Subtype subtype,
- ChannelEndpointId local_id,
- ChannelEndpointId remote_id) {
- DVLOG(2) << "Sending channel control message: subtype " << subtype
- << ", local ID " << local_id << ", remote ID " << remote_id;
- scoped_ptr<MessageInTransit> message(new MessageInTransit(
- MessageInTransit::kTypeChannel, subtype, 0, nullptr));
- message->set_source_id(local_id);
- message->set_destination_id(remote_id);
- return WriteMessage(message.Pass());
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel.h b/mojo/edk/system/channel.h
deleted file mode 100644
index 3961859..0000000
--- a/mojo/edk/system/channel.h
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_CHANNEL_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_H_
-
-#include <stdint.h>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/incoming_endpoint.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/raw_channel.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformSupport;
-}
-
-namespace system {
-
-class ChannelEndpointClient;
-class ChannelManager;
-class MessageInTransitQueue;
-
-// This class is mostly thread-safe. It must be created on an I/O thread.
-// |Init()| must be called on that same thread before it becomes thread-safe (in
-// particular, before references are given to any other thread) and |Shutdown()|
-// must be called on that same thread before destruction. Its public methods are
-// otherwise thread-safe. (Many private methods are restricted to the creation
-// thread.) It may be destroyed on any thread, in the sense that the last
-// reference to it may be released on any thread, with the proviso that
-// |Shutdown()| must have been called first (so the pattern is that a "main"
-// reference is kept on its creation thread and is released after |Shutdown()|
-// is called, but other threads may have temporarily "dangling" references).
-//
-// Note the lock order (in order of allowable acquisition):
-// |ChannelEndpointClient| (e.g., |MessagePipe|), |ChannelEndpoint|, |Channel|.
-// Thus |Channel| may not call into |ChannelEndpoint| with |Channel|'s lock
-// held.
-class MOJO_SYSTEM_IMPL_EXPORT Channel
- : public base::RefCountedThreadSafe<Channel>,
- public RawChannel::Delegate {
- public:
- // |platform_support| (typically owned by |Core|) must remain alive until
- // after |Shutdown()| is called.
- explicit Channel(embedder::PlatformSupport* platform_support);
-
- // This must be called on the creation thread before any other methods are
- // called, and before references to this object are given to any other
- // threads. |raw_channel| should be uninitialized.
- void Init(scoped_ptr<RawChannel> raw_channel);
-
- // Sets the channel manager associated with this channel. This should be set
- // at most once and only called before |WillShutdownSoon()| (and
- // |Shutdown()|).
- void SetChannelManager(ChannelManager* channel_manager);
-
- // This must be called on the creation thread before destruction (which can
- // happen on any thread).
- void Shutdown();
-
- // Signals that |Shutdown()| will be called soon (this may be called from any
- // thread, unlike |Shutdown()|). Warnings will be issued if, e.g., messages
- // are written after this is called; other warnings may be suppressed. (This
- // may be called multiple times, or not at all.)
- //
- // If set, the channel manager associated with this channel will be reset.
- void WillShutdownSoon();
-
- // Called to set (i.e., attach and run) the bootstrap (first) endpoint on the
- // channel. Both the local and remote IDs are the bootstrap ID (given by
- // |ChannelEndpointId::GetBootstrap()|).
- //
- // (Bootstrapping is symmetric: Both sides call this, which will establish the
- // first connection across a channel.)
- void SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint);
-
- // This forwards |message| verbatim to |raw_channel_|.
- bool WriteMessage(scoped_ptr<MessageInTransit> message);
-
- // See |RawChannel::IsWriteBufferEmpty()|.
- // TODO(vtl): Maybe we shouldn't expose this, and instead have a
- // |FlushWriteBufferAndShutdown()| or something like that.
- bool IsWriteBufferEmpty();
-
- // Removes the given endpoint from this channel (|local_id| and |remote_id|
- // are specified as an optimization; the latter should be an invalid
- // |ChannelEndpointId| if the endpoint is not yet running). Note: If this is
- // called, the |Channel| will *not* call
- // |ChannelEndpoint::DetachFromChannel()|.
- void DetachEndpoint(ChannelEndpoint* endpoint,
- ChannelEndpointId local_id,
- ChannelEndpointId remote_id);
-
- // Returns the size of a serialized endpoint (see |SerializeEndpoint...()| and
- // |DeserializeEndpoint()| below). This value will remain constant for a given
- // instance of |Channel|.
- size_t GetSerializedEndpointSize() const;
-
- // Endpoint serialization methods: From the |Channel|'s point of view, there
- // are three cases (discussed further below) and thus three methods.
- //
- // All three methods have a |destination| argument, which should be a buffer
- // to which auxiliary information will be written and which should be
- // transmitted to the peer |Channel| by some other means, but using this
- // |Channel|. It should be a buffer of (at least) the size returned by
- // |GetSerializedEndpointSize()| (exactly that much data will be written).
- //
- // All three also have a |message_queue| argument, which if non-null is the
- // queue of messages already received by the endpoint to be serialized.
- //
- // Note that "serialize" really means "send" -- the |endpoint| will be sent
- // "immediately". The contents of the |destination| buffer can then be used to
- // claim the rematerialized endpoint from the peer |Channel|. (|destination|
- // must be sent using this |Channel|, since otherwise it may be received
- // before it is valid to the peer |Channel|.)
- //
- // Case 1: The endpoint's peer is already closed.
- //
- // Case 2: The endpoint's peer is local (i.e., it has a
- // |ChannelEndpointClient| but no peer |ChannelEndpoint|).
- //
- // Case 3: The endpoint's peer is remote (i.e., it has a peer
- // |ChannelEndpoint|). (This has two subcases: the peer endpoint may be on
- // this |Channel| or another |Channel|.)
- void SerializeEndpointWithClosedPeer(void* destination,
- MessageInTransitQueue* message_queue);
- // This one returns the |ChannelEndpoint| for the serialized endpoint (which
- // can be used by, e.g., a |ProxyMessagePipeEndpoint|.
- scoped_refptr<ChannelEndpoint> SerializeEndpointWithLocalPeer(
- void* destination,
- MessageInTransitQueue* message_queue,
- ChannelEndpointClient* endpoint_client,
- unsigned endpoint_client_port);
- void SerializeEndpointWithRemotePeer(
- void* destination,
- MessageInTransitQueue* message_queue,
- scoped_refptr<ChannelEndpoint> peer_endpoint);
-
- // Deserializes an endpoint that was sent from the peer |Channel| (using
- // |SerializeEndpoint...()|. |source| should be (a copy of) the data that
- // |SerializeEndpoint...()| wrote, and must be (at least)
- // |GetSerializedEndpointSize()| bytes. This returns the deserialized
- // |IncomingEndpoint| (which can be converted into a |MessagePipe|) or null on
- // error.
- scoped_refptr<IncomingEndpoint> DeserializeEndpoint(const void* source);
-
- // See |RawChannel::GetSerializedPlatformHandleSize()|.
- size_t GetSerializedPlatformHandleSize() const;
-
- embedder::PlatformSupport* platform_support() const {
- return platform_support_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<Channel>;
- ~Channel() override;
-
- // |RawChannel::Delegate| implementation (only called on the creation thread):
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override;
- void OnError(Error error) override;
-
- // Helpers for |OnReadMessage| (only called on the creation thread):
- void OnReadMessageForEndpoint(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles);
- void OnReadMessageForChannel(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles);
-
- // Handles "attach and run endpoint" messages.
- bool OnAttachAndRunEndpoint(ChannelEndpointId local_id,
- ChannelEndpointId remote_id);
- // Handles "remove endpoint" messages.
- bool OnRemoveEndpoint(ChannelEndpointId local_id,
- ChannelEndpointId remote_id);
- // Handles "remove endpoint ack" messages.
- bool OnRemoveEndpointAck(ChannelEndpointId local_id);
-
- // Handles errors (e.g., invalid messages) from the remote side. Callable from
- // any thread.
- void HandleRemoteError(const base::StringPiece& error_message);
- // Handles internal errors/failures from the local side. Callable from any
- // thread.
- void HandleLocalError(const base::StringPiece& error_message);
-
- // Helper for |SerializeEndpoint...()|: Attaches the given (non-bootstrap)
- // endpoint to this channel and runs it. This assigns the endpoint both local
- // and remote IDs. This will also send a |kSubtypeChannelAttachAndRunEndpoint|
- // message to the remote side to tell it to create an endpoint as well. This
- // returns the *remote* ID (one for which |is_remote()| returns true).
- //
- // TODO(vtl): Maybe limit the number of attached message pipes.
- ChannelEndpointId AttachAndRunEndpoint(
- scoped_refptr<ChannelEndpoint> endpoint);
-
- // Helper to send channel control messages. Returns true on success. Should be
- // called *without* |lock_| held. Callable from any thread.
- bool SendControlMessage(MessageInTransit::Subtype subtype,
- ChannelEndpointId source_id,
- ChannelEndpointId destination_id);
-
- base::ThreadChecker creation_thread_checker_;
-
- embedder::PlatformSupport* const platform_support_;
-
- // Note: |ChannelEndpointClient|s (in particular, |MessagePipe|s) MUST NOT be
- // used under |lock_|. E.g., |lock_| can only be acquired after
- // |MessagePipe::lock_|, never before. Thus to call into a
- // |ChannelEndpointClient|, a reference should be acquired from
- // |local_id_to_endpoint_map_| under |lock_| and then the lock released.
- base::Lock lock_; // Protects the members below.
-
- scoped_ptr<RawChannel> raw_channel_;
- bool is_running_;
- // Set when |WillShutdownSoon()| is called.
- bool is_shutting_down_;
-
- // Has a reference to us.
- ChannelManager* channel_manager_;
-
- typedef base::hash_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>>
- IdToEndpointMap;
- // Map from local IDs to endpoints. If the endpoint is null, this means that
- // we're just waiting for the remove ack before removing the entry.
- IdToEndpointMap local_id_to_endpoint_map_;
- // Note: The IDs generated by this should be checked for existence before use.
- LocalChannelEndpointIdGenerator local_id_generator_;
-
- typedef base::hash_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>>
- IdToIncomingEndpointMap;
- // Map from local IDs to incoming endpoints (i.e., those received inside other
- // messages, but not yet claimed via |DeserializeEndpoint()|).
- IdToIncomingEndpointMap incoming_endpoints_;
- // TODO(vtl): We need to keep track of remote IDs (so that we don't collide
- // if/when we wrap).
- RemoteChannelEndpointIdGenerator remote_id_generator_;
-
- DISALLOW_COPY_AND_ASSIGN(Channel);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_H_
diff --git a/mojo/edk/system/channel_endpoint.cc b/mojo/edk/system/channel_endpoint.cc
deleted file mode 100644
index 8ef1f40..0000000
--- a/mojo/edk/system/channel_endpoint.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// 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/channel_endpoint.h"
-
-#include "base/logging.h"
-#include "base/threading/platform_thread.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint_client.h"
-
-namespace mojo {
-namespace system {
-
-ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client,
- unsigned client_port,
- MessageInTransitQueue* message_queue)
- : client_(client),
- client_port_(client_port),
- channel_(nullptr),
- is_detached_from_channel_(false) {
- DCHECK(client_ || message_queue);
-
- if (message_queue)
- channel_message_queue_.Swap(message_queue);
-}
-
-bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) {
- DCHECK(message);
-
- base::AutoLock locker(lock_);
-
- if (!channel_) {
- // We may reach here if we haven't been attached/run yet.
- // TODO(vtl): We may also reach here if the channel is shut down early for
- // some reason (with live message pipes on it). Ideally, we'd return false
- // (and not enqueue the message), but we currently don't have a way to check
- // this.
- channel_message_queue_.AddMessage(message.Pass());
- return true;
- }
-
- return WriteMessageNoLock(message.Pass());
-}
-
-bool ChannelEndpoint::ReplaceClient(ChannelEndpointClient* client,
- unsigned client_port) {
- DCHECK(client);
-
- base::AutoLock locker(lock_);
- DCHECK(client_);
- DCHECK(client != client_.get() || client_port != client_port_);
- client_ = client;
- client_port_ = client_port;
- return !is_detached_from_channel_;
-}
-
-void ChannelEndpoint::DetachFromClient() {
- base::AutoLock locker(lock_);
- DCHECK(client_);
- client_ = nullptr;
-
- if (!channel_)
- return;
- channel_->DetachEndpoint(this, local_id_, remote_id_);
- ResetChannelNoLock();
-}
-
-void ChannelEndpoint::AttachAndRun(Channel* channel,
- ChannelEndpointId local_id,
- ChannelEndpointId remote_id) {
- DCHECK(channel);
- DCHECK(local_id.is_valid());
- DCHECK(remote_id.is_valid());
-
- base::AutoLock locker(lock_);
- DCHECK(!channel_);
- DCHECK(!local_id_.is_valid());
- DCHECK(!remote_id_.is_valid());
- channel_ = channel;
- local_id_ = local_id;
- remote_id_ = remote_id;
-
- while (!channel_message_queue_.IsEmpty()) {
- LOG_IF(WARNING, !WriteMessageNoLock(channel_message_queue_.GetMessage()))
- << "Failed to write enqueue message to channel";
- }
-
- if (!client_) {
- channel_->DetachEndpoint(this, local_id_, remote_id_);
- ResetChannelNoLock();
- }
-}
-
-void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) {
- scoped_refptr<ChannelEndpointClient> client;
- unsigned client_port = 0;
-
- // This loop is to make |ReplaceClient()| work. We can't call the client's
- // |OnReadMessage()| under our lock, so by the time we do that, |client| may
- // no longer be our client.
- //
- // In that case, |client| must return false. We'll then yield, and retry with
- // the new client. (Theoretically, the client could be replaced again.)
- //
- // This solution isn't terribly elegant, but it's the least costly way of
- // handling/avoiding this (very unlikely) race. (Other solutions -- e.g.,
- // adding a client message queue, which the client only fetches messages from
- // -- impose significant cost in the common case.)
- for (;;) {
- {
- base::AutoLock locker(lock_);
- if (!channel_ || !client_) {
- // This isn't a failure per se. (It just means that, e.g., the other end
- // of the message point closed first.)
- return;
- }
-
- // If we get here in a second (third, etc.) iteration of the loop, it's
- // because |ReplaceClient()| was called.
- DCHECK(client_ != client || client_port_ != client_port);
-
- // Take a ref, and call |OnReadMessage()| outside the lock.
- client = client_;
- client_port = client_port_;
- }
-
- if (client->OnReadMessage(client_port, message.get())) {
- ignore_result(message.release());
- break;
- }
-
- base::PlatformThread::YieldCurrentThread();
- }
-}
-
-void ChannelEndpoint::DetachFromChannel() {
- scoped_refptr<ChannelEndpointClient> client;
- unsigned client_port = 0;
- {
- base::AutoLock locker(lock_);
-
- if (client_) {
- // Take a ref, and call |OnDetachFromChannel()| outside the lock.
- client = client_;
- client_port = client_port_;
- }
-
- // |channel_| may already be null if we already detached from the channel in
- // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there
- // are racing detaches).
- if (channel_)
- ResetChannelNoLock();
- else
- DCHECK(is_detached_from_channel_);
- }
-
- // If |ReplaceClient()| is called (from another thread) after the above locked
- // section but before we call |OnDetachFromChannel()|, |ReplaceClient()|
- // return false to notify the caller that the channel was already detached.
- // (The old client has to accept the arguably-spurious call to
- // |OnDetachFromChannel()|.)
- if (client)
- client->OnDetachFromChannel(client_port);
-}
-
-ChannelEndpoint::~ChannelEndpoint() {
- DCHECK(!client_);
- DCHECK(!channel_);
- DCHECK(!local_id_.is_valid());
- DCHECK(!remote_id_.is_valid());
-}
-
-bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> message) {
- DCHECK(message);
-
- lock_.AssertAcquired();
-
- DCHECK(channel_);
- DCHECK(local_id_.is_valid());
- DCHECK(remote_id_.is_valid());
-
- message->SerializeAndCloseDispatchers(channel_);
- message->set_source_id(local_id_);
- message->set_destination_id(remote_id_);
- return channel_->WriteMessage(message.Pass());
-}
-
-void ChannelEndpoint::ResetChannelNoLock() {
- DCHECK(channel_);
- DCHECK(local_id_.is_valid());
- DCHECK(remote_id_.is_valid());
- DCHECK(!is_detached_from_channel_);
-
- channel_ = nullptr;
- local_id_ = ChannelEndpointId();
- remote_id_ = ChannelEndpointId();
- is_detached_from_channel_ = true;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_endpoint.h b/mojo/edk/system/channel_endpoint.h
deleted file mode 100644
index 90ee86b..0000000
--- a/mojo/edk/system/channel_endpoint.h
+++ /dev/null
@@ -1,210 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/message_in_transit_queue.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class Channel;
-class ChannelEndpointClient;
-class MessageInTransit;
-
-// TODO(vtl): The plan:
-// - (Done.) Move |Channel::Endpoint| to |ChannelEndpoint|. Make it
-// refcounted, and not copyable. Make |Channel| a friend. Make things work.
-// - (Done.) Give |ChannelEndpoint| a lock. The lock order (in order of
-// allowable acquisition) is: |MessagePipe|, |ChannelEndpoint|, |Channel|.
-// - (Done) Stop having |Channel| as a friend.
-// - (Done) Move logic from |ProxyMessagePipeEndpoint| into |ChannelEndpoint|.
-// Right now, we have to go through lots of contortions to manipulate state
-// owned by |ProxyMessagePipeEndpoint| (in particular, |Channel::Endpoint|
-// doesn't know about the remote ID; the local ID is duplicated in two
-// places). Hollow out |ProxyMessagePipeEndpoint|, and have it just own a
-// reference to |ChannelEndpoint| (hence the refcounting).
-// - In essence, |ChannelEndpoint| becomes the thing that knows about
-// channel-specific aspects of an endpoint (notably local and remote IDs,
-// and knowledge about handshaking), and mediates between the |Channel| and
-// the |MessagePipe|.
-// - In the end state, |Channel| should no longer need to know about
-// |MessagePipe| and ports (but only |ChannelEndpoint|) and
-// |ProxyMessagePipeEndpoint| should no longer need to know about |Channel|
-// (ditto).
-//
-// Things as they are now, before I change everything (TODO(vtl): update this
-// comment appropriately):
-//
-// Terminology:
-// - "Message pipe endpoint": In the implementation, a |MessagePipe| owns
-// two |MessagePipeEndpoint| objects, one for each port. The
-// |MessagePipeEndpoint| objects are only accessed via the |MessagePipe|
-// (which has the lock), with the additional information of the port
-// number. So as far as the channel is concerned, a message pipe endpoint
-// is a pointer to a |MessagePipe| together with the port number.
-// - The value of |port| in |EndpointInfo| refers to the
-// |ProxyMessagePipeEndpoint| (i.e., the endpoint that is logically on
-// the other side). Messages received by a channel for a message pipe
-// are thus written to the *peer* of this port.
-// - "Attached"/"detached": A message pipe endpoint is attached to a channel
-// if it has a pointer to it. It must be detached before the channel gives
-// up its pointer to it in order to break a reference cycle. (This cycle
-// is needed to allow a channel to be shut down cleanly, without shutting
-// down everything else first.)
-// - "Running" (message pipe endpoint): A message pipe endpoint is running
-// if messages written to it (via some |MessagePipeDispatcher|, to which
-// some |MojoHandle| is assigned) are being transmitted through the
-// channel.
-// - Before a message pipe endpoint is run, it will queue messages.
-// - When a message pipe endpoint is detached from a channel, it is also
-// taken out of the running state. After that point, messages should
-// no longer be written to it.
-// - "Normal" message pipe endpoint (state): The channel itself does not
-// have knowledge of whether a message pipe endpoint has started running
-// yet. It will *receive* messages for a message pipe in either state (but
-// the message pipe endpoint won't *send* messages to the channel if it
-// has not started running).
-// - "Zombie" message pipe endpoint (state): A message pipe endpoint is a
-// zombie if it is still in |local_id_to_endpoint_info_map_|, but the
-// channel is no longer forwarding messages to it (even if it may still be
-// receiving messages for it).
-// - There are various types of zombies, depending on the reason the
-// message pipe endpoint cannot yet be removed.
-// - If the remote side is closed, it will send a "remove" control
-// message. After the channel receives that message (to which it
-// responds with a "remove ack" control message), it knows that it
-// shouldn't receive any more messages for that message pipe endpoint
-// (local ID), but it must wait for the endpoint to detach. (It can't
-// do so without a race, since it can't call into the message pipe
-// under |lock_|.) [TODO(vtl): When I add remotely-allocated IDs,
-// we'll have to remove the |EndpointInfo| from
-// |local_id_to_endpoint_info_map_| -- i.e., remove the local ID,
-// since it's no longer valid and may be reused by the remote side --
-// and keep the |EndpointInfo| alive in some other way.]
-// - If the local side is closed and the message pipe endpoint was
-// already running (so there are no queued messages left to send), it
-// will detach the endpoint, and send a "remove" control message.
-// However, the channel may still receive messages for that endpoint
-// until it receives a "remove ack" control message.
-// - If the local side is closed but the message pipe endpoint was not
-// yet running , the detaching is delayed until after it is run and
-// all the queued messages are sent to the channel. On being detached,
-// things proceed as in one of the above cases. The endpoint is *not*
-// a zombie until it is detached (or a "remove" message is received).
-// [TODO(vtl): Maybe we can get rid of this case? It'd only not yet be
-// running since under the current scheme it wouldn't have a remote ID
-// yet.]
-// - Note that even if the local side is closed, it may still receive a
-// "remove" message from the other side (if the other side is closed
-// simultaneously, and both sides send "remove" messages). In that
-// case, it must still remain alive until it receives the "remove
-// ack" (and it must ack the "remove" message that it received).
-class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint
- : public base::RefCountedThreadSafe<ChannelEndpoint> {
- public:
- // Constructor for a |ChannelEndpoint| with the given client (specified by
- // |client| and |client_port|). Optionally takes messages from
- // |*message_queue| if |message_queue| is non-null.
- //
- // |client| may be null if this endpoint will never need to receive messages,
- // in which case |message_queue| should not be null. In that case, this
- // endpoint will simply send queued messages upon being attached to a
- // |Channel| and immediately detach itself.
- ChannelEndpoint(ChannelEndpointClient* client,
- unsigned client_port,
- MessageInTransitQueue* message_queue = nullptr);
-
- // Methods called by |ChannelEndpointClient|:
-
- // Called to enqueue an outbound message. (If |AttachAndRun()| has not yet
- // been called, the message will be enqueued and sent when |AttachAndRun()| is
- // called.)
- bool EnqueueMessage(scoped_ptr<MessageInTransit> message);
-
- // Called to *replace* current client with a new client (which must differ
- // from the existing client). This must not be called after
- // |DetachFromClient()| has been called.
- //
- // This returns true in the typical case, and false if this endpoint has been
- // detached from the channel, in which case the caller should probably call
- // its (new) client's |OnDetachFromChannel()|.
- bool ReplaceClient(ChannelEndpointClient* client, unsigned client_port);
-
- // Called before the |ChannelEndpointClient| gives up its reference to this
- // object.
- void DetachFromClient();
-
- // Methods called by |Channel|:
-
- // Called when the |Channel| takes a reference to this object. This will send
- // all queue messages (in |channel_message_queue_|).
- // TODO(vtl): Maybe rename this "OnAttach"?
- void AttachAndRun(Channel* channel,
- ChannelEndpointId local_id,
- ChannelEndpointId remote_id);
-
- // Called when the |Channel| receives a message for the |ChannelEndpoint|.
- void OnReadMessage(scoped_ptr<MessageInTransit> message);
-
- // Called before the |Channel| gives up its reference to this object.
- void DetachFromChannel();
-
- private:
- friend class base::RefCountedThreadSafe<ChannelEndpoint>;
- ~ChannelEndpoint();
-
- // Must be called with |lock_| held.
- bool WriteMessageNoLock(scoped_ptr<MessageInTransit> message);
-
- // Resets |channel_| to null (and sets |is_detached_from_channel_|). This may
- // only be called if |channel_| is non-null. Must be called with |lock_| held.
- void ResetChannelNoLock();
-
- // Protects the members below.
- base::Lock lock_;
-
- // |client_| must be valid whenever it is non-null. Before |*client_| gives up
- // its reference to this object, it must call |DetachFromClient()|.
- // NOTE: This is a |scoped_refptr<>|, rather than a raw pointer, since the
- // |Channel| needs to keep the |MessagePipe| alive for the "proxy-proxy" case.
- // Possibly we'll be able to eliminate that case when we have full
- // multiprocess support.
- // WARNING: |ChannelEndpointClient| methods must not be called under |lock_|.
- // Thus to make such a call, a reference must first be taken under |lock_| and
- // the lock released.
- // WARNING: Beware of interactions with |ReplaceClient()|. By the time the
- // call is made, the client may have changed. This must be detected and dealt
- // with.
- scoped_refptr<ChannelEndpointClient> client_;
- unsigned client_port_;
-
- // |channel_| must be valid whenever it is non-null. Before |*channel_| gives
- // up its reference to this object, it must call |DetachFromChannel()|.
- // |local_id_| and |remote_id_| are valid if and only |channel_| is non-null.
- Channel* channel_;
- ChannelEndpointId local_id_;
- ChannelEndpointId remote_id_;
- // This distinguishes the two cases of |channel| being null: not yet attached
- // versus detached.
- bool is_detached_from_channel_;
-
- // This queue is used before we're running on a channel and ready to send
- // messages to the channel.
- MessageInTransitQueue channel_message_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelEndpoint);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_
diff --git a/mojo/edk/system/channel_endpoint_client.h b/mojo/edk/system/channel_endpoint_client.h
deleted file mode 100644
index c758e9c..0000000
--- a/mojo/edk/system/channel_endpoint_client.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class MessageInTransit;
-
-// Interface for receivers of messages from |ChannelEndpoint| (hence from
-// |Channel|). |port| is simply the value passed to |ChannelEndpoint| on
-// construction, and provides a lightweight way for an object to be the client
-// of multiple |ChannelEndpoint|s. (|MessagePipe| implements this interface, in
-// which case |port| is the port number for the |ProxyMessagePipeEndpoint|
-// corresdponding to the |ChannelEndpoint|.)
-//
-// Implementations of this class should be thread-safe. |ChannelEndpointClient|
-// *precedes* |ChannelEndpoint| in the lock order, so |ChannelEndpoint| should
-// never call into this class with its lock held. (Instead, it should take a
-// reference under its lock, release its lock, and make any needed call(s).)
-//
-// Note: As a consequence of this, all the client methods may be called even
-// after |ChannelEndpoint::DetachFromClient()| has been called (so the
-// |ChannelEndpoint| has apparently relinquished its pointer to the
-// |ChannelEndpointClient|).
-class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointClient
- : public base::RefCountedThreadSafe<ChannelEndpointClient> {
- public:
- // Called by |ChannelEndpoint| in response to its |OnReadMessage()|, which is
- // called by |Channel| when it receives a message for the |ChannelEndpoint|.
- // (|port| is the value passed to |ChannelEndpoint|'s constructor as
- // |client_port|.)
- //
- // This should return true if it accepted (and took ownership of) |message|.
- virtual bool OnReadMessage(unsigned port, MessageInTransit* message) = 0;
-
- // Called by |ChannelEndpoint| when the |Channel| is relinquishing its pointer
- // to the |ChannelEndpoint| (and vice versa). After this is called,
- // |OnReadMessage()| will no longer be called.
- virtual void OnDetachFromChannel(unsigned port) = 0;
-
- protected:
- ChannelEndpointClient() {}
-
- virtual ~ChannelEndpointClient() {}
- friend class base::RefCountedThreadSafe<ChannelEndpointClient>;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ChannelEndpointClient);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_
diff --git a/mojo/edk/system/channel_endpoint_id.cc b/mojo/edk/system/channel_endpoint_id.cc
deleted file mode 100644
index ed00f6a..0000000
--- a/mojo/edk/system/channel_endpoint_id.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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/channel_endpoint_id.h"
-
-#include "base/compiler_specific.h"
-
-namespace mojo {
-namespace system {
-
-STATIC_CONST_MEMBER_DEFINITION const uint32_t ChannelEndpointId::kRemoteFlag;
-
-ChannelEndpointId LocalChannelEndpointIdGenerator::GetNext() {
- ChannelEndpointId rv = next_;
- next_.value_ = (next_.value_ + 1) & ~ChannelEndpointId::kRemoteFlag;
- // Skip over the invalid value, in case we wrap.
- if (!next_.is_valid())
- next_.value_++;
- return rv;
-}
-
-ChannelEndpointId RemoteChannelEndpointIdGenerator::GetNext() {
- ChannelEndpointId rv = next_;
- next_.value_ = (next_.value_ + 1) | ChannelEndpointId::kRemoteFlag;
- return rv;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_endpoint_id.h b/mojo/edk/system/channel_endpoint_id.h
deleted file mode 100644
index c673258..0000000
--- a/mojo/edk/system/channel_endpoint_id.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <ostream>
-
-#include "base/containers/hash_tables.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// ChannelEndpointId -----------------------------------------------------------
-
-class LocalChannelEndpointIdGenerator;
-FORWARD_DECLARE_TEST(LocalChannelEndpointIdGeneratorTest, WrapAround);
-FORWARD_DECLARE_TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround);
-
-// Represents an ID for an endpoint (i.e., one side of a message pipe) on a
-// |Channel|. This class must be POD.
-//
-// Note: The terminology "remote" for a |ChannelEndpointId| means a destination
-// ID that was actually allocated by the sender, or similarly a source ID that
-// was allocated by the receiver.
-//
-// From the standpoint of the |Channel| with such a remote ID in its endpoint
-// table, such an ID is a "remotely-allocated local ID". From the standpoint of
-// the |Channel| allocating such a remote ID (for its peer |Channel|), it's a
-// "locally-allocated remote ID".
-class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId {
- public:
- ChannelEndpointId() : value_(0) {}
- ChannelEndpointId(const ChannelEndpointId& other) : value_(other.value_) {}
-
- // Returns the local ID to use for the first message pipe endpoint on a
- // channel.
- static ChannelEndpointId GetBootstrap() { return ChannelEndpointId(1); }
-
- bool operator==(const ChannelEndpointId& other) const {
- return value_ == other.value_;
- }
- bool operator!=(const ChannelEndpointId& other) const {
- return !operator==(other);
- }
- // So that we can be used in |std::map|, etc.
- bool operator<(const ChannelEndpointId& other) const {
- return value_ < other.value_;
- }
-
- bool is_valid() const { return !!value_; }
- bool is_remote() const { return !!(value_ & kRemoteFlag); }
- const uint32_t& value() const { return value_; }
-
- // Flag set in |value()| if this is a remote ID.
- static const uint32_t kRemoteFlag = 0x80000000u;
-
- private:
- friend class LocalChannelEndpointIdGenerator;
- FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround);
- friend class RemoteChannelEndpointIdGenerator;
- FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround);
-
- explicit ChannelEndpointId(uint32_t value) : value_(value) {}
-
- uint32_t value_;
-
- // Copying and assignment allowed.
-};
-// This wrapper should add no overhead.
-// TODO(vtl): Rewrite |sizeof(uint32_t)| as |sizeof(ChannelEndpointId::value)|
-// once we have sufficient C++11 support.
-static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t),
- "ChannelEndpointId has incorrect size");
-
-// So logging macros and |DCHECK_EQ()|, etc. work.
-inline std::ostream& operator<<(std::ostream& out,
- const ChannelEndpointId& channel_endpoint_id) {
- return out << channel_endpoint_id.value();
-}
-
-// LocalChannelEndpointIdGenerator ---------------------------------------------
-
-// A generator for "new" local |ChannelEndpointId|s. It does not track
-// used/existing IDs; that must be done separately. (This class is not
-// thread-safe.)
-class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator {
- public:
- LocalChannelEndpointIdGenerator()
- : next_(ChannelEndpointId::GetBootstrap()) {}
-
- ChannelEndpointId GetNext();
-
- private:
- FRIEND_TEST_ALL_PREFIXES(LocalChannelEndpointIdGeneratorTest, WrapAround);
-
- ChannelEndpointId next_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalChannelEndpointIdGenerator);
-};
-
-// RemoteChannelEndpointIdGenerator --------------------------------------------
-
-// A generator for "new" remote |ChannelEndpointId|s, for |Channel|s to
-// locally allocate remote IDs. (See the comment above |ChannelEndpointId| for
-// an explanatory note.) It does not track used/existing IDs; that must be done
-// separately. (This class is not thread-safe.)
-class MOJO_SYSTEM_IMPL_EXPORT RemoteChannelEndpointIdGenerator {
- public:
- RemoteChannelEndpointIdGenerator() : next_(ChannelEndpointId::kRemoteFlag) {}
-
- ChannelEndpointId GetNext();
-
- private:
- FRIEND_TEST_ALL_PREFIXES(RemoteChannelEndpointIdGeneratorTest, WrapAround);
-
- ChannelEndpointId next_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteChannelEndpointIdGenerator);
-};
-
-} // namespace system
-} // namespace mojo
-
-// Define "hash" functions for |ChannelEndpointId|s, so they can be used in hash
-// tables.
-// TODO(vtl): Once we can use |std::unordered_{map,set}|, update this (and
-// remove the base/containers/hash_tables.h include).
-namespace BASE_HASH_NAMESPACE {
-
-template <>
-struct hash<mojo::system::ChannelEndpointId> {
- size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const {
- return static_cast<size_t>(channel_endpoint_id.value());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_
diff --git a/mojo/edk/system/channel_endpoint_id_unittest.cc b/mojo/edk/system/channel_endpoint_id_unittest.cc
deleted file mode 100644
index a5bd14f..0000000
--- a/mojo/edk/system/channel_endpoint_id_unittest.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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/channel_endpoint_id.h"
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-TEST(ChannelEndpointIdTest, Basic) {
- ChannelEndpointId invalid;
- ChannelEndpointId bootstrap(ChannelEndpointId::GetBootstrap());
-
- EXPECT_EQ(invalid, invalid);
- EXPECT_EQ(bootstrap, bootstrap);
- EXPECT_FALSE(invalid == bootstrap);
-
- EXPECT_FALSE(invalid != invalid);
- EXPECT_FALSE(bootstrap != bootstrap);
- EXPECT_NE(invalid, bootstrap);
-
- EXPECT_FALSE(invalid < invalid);
- EXPECT_LT(invalid, bootstrap);
-
- EXPECT_FALSE(invalid.is_valid());
- EXPECT_TRUE(bootstrap.is_valid());
-
- EXPECT_FALSE(invalid.is_remote());
- EXPECT_FALSE(bootstrap.is_remote());
-
- // Test assignment.
- ChannelEndpointId copy;
- copy = bootstrap;
- EXPECT_EQ(copy, bootstrap);
- copy = invalid;
- EXPECT_EQ(copy, invalid);
-}
-
-// Tests values of invalid and bootstrap IDs. (This tests implementation
-// details.)
-TEST(ChannelEndpointIdTest, Value) {
- EXPECT_EQ(0u, ChannelEndpointId().value());
- EXPECT_EQ(1u, ChannelEndpointId::GetBootstrap().value());
-}
-
-// Tests ostream output. (This tests implementation details.)
-TEST(ChannelEndpointIdTest, Ostream) {
- {
- std::ostringstream stream;
- stream << ChannelEndpointId();
- EXPECT_EQ("0", stream.str());
- }
- {
- std::ostringstream stream;
- stream << ChannelEndpointId::GetBootstrap();
- EXPECT_EQ("1", stream.str());
- }
-}
-
-TEST(LocalChannelEndpointIdGeneratorTest, Basic) {
- LocalChannelEndpointIdGenerator gen;
-
- ChannelEndpointId id1;
- EXPECT_FALSE(id1.is_valid()); // Check sanity.
-
- id1 = gen.GetNext();
- EXPECT_TRUE(id1.is_valid());
- EXPECT_FALSE(id1.is_remote());
-
- EXPECT_EQ(ChannelEndpointId::GetBootstrap().value(), id1.value());
-
- ChannelEndpointId id2 = gen.GetNext();
- EXPECT_TRUE(id2.is_valid());
- EXPECT_FALSE(id2.is_remote());
- // Technically, nonequality here is an implementation detail, since, e.g.,
- // random generation of IDs would be a valid implementation.
- EXPECT_NE(id2, id1);
- // ... but right now we just increment to generate IDs.
- EXPECT_EQ(2u, id2.value());
-}
-
-// Note: LocalChannelEndpointIdGeneratorTest.WrapAround is defined further
-// below, outside the anonymous namespace.
-
-TEST(RemoteChannelEndpointIdGeneratorTest, Basic) {
- RemoteChannelEndpointIdGenerator gen;
-
- ChannelEndpointId id1;
- EXPECT_FALSE(id1.is_valid()); // Check sanity.
-
- id1 = gen.GetNext();
- EXPECT_TRUE(id1.is_valid());
- EXPECT_TRUE(id1.is_remote());
-
- // This tests an implementation detail.
- EXPECT_EQ(ChannelEndpointId::kRemoteFlag, id1.value());
-
- ChannelEndpointId id2 = gen.GetNext();
- EXPECT_TRUE(id2.is_valid());
- EXPECT_TRUE(id2.is_remote());
- // Technically, nonequality here is an implementation detail, since, e.g.,
- // random generation of IDs would be a valid implementation.
- EXPECT_NE(id2, id1);
- // ... but right now we just increment to generate IDs.
- EXPECT_EQ(ChannelEndpointId::kRemoteFlag + 1, id2.value());
-}
-
-// Note: RemoteChannelEndpointIdGeneratorTest.WrapAround is defined further
-// below, outside the anonymous namespace.
-
-} // namespace
-
-// Tests that |LocalChannelEndpointIdGenerator| handles wrap-around correctly.
-// (This tests implementation details.) This test isn't in an anonymous
-// namespace, since it needs to be friended.
-TEST(LocalChannelEndpointIdGeneratorTest, WrapAround) {
- LocalChannelEndpointIdGenerator gen;
- gen.next_ = ChannelEndpointId(ChannelEndpointId::kRemoteFlag - 1);
-
- ChannelEndpointId id = gen.GetNext();
- EXPECT_TRUE(id.is_valid());
- EXPECT_FALSE(id.is_remote());
- EXPECT_EQ(ChannelEndpointId::kRemoteFlag - 1, id.value());
-
- id = gen.GetNext();
- EXPECT_TRUE(id.is_valid());
- EXPECT_FALSE(id.is_remote());
- EXPECT_EQ(1u, id.value());
-}
-
-// Tests that |RemoteChannelEndpointIdGenerator| handles wrap-around correctly.
-// (This tests implementation details.) This test isn't in an anonymous
-// namespace, since it needs to be friended.
-TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround) {
- RemoteChannelEndpointIdGenerator gen;
- gen.next_ = ChannelEndpointId(~0u);
-
- ChannelEndpointId id = gen.GetNext();
- EXPECT_TRUE(id.is_valid());
- EXPECT_TRUE(id.is_remote());
- EXPECT_EQ(~0u, id.value());
-
- id = gen.GetNext();
- EXPECT_TRUE(id.is_valid());
- EXPECT_TRUE(id.is_remote());
- EXPECT_EQ(ChannelEndpointId::kRemoteFlag, id.value());
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_info.cc b/mojo/edk/system/channel_info.cc
deleted file mode 100644
index 6d23215..0000000
--- a/mojo/edk/system/channel_info.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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/channel_info.h"
-
-#include <algorithm>
-
-namespace mojo {
-namespace system {
-
-ChannelInfo::ChannelInfo() {
-}
-
-ChannelInfo::ChannelInfo(
- scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner)
- : channel(channel), channel_thread_task_runner(channel_thread_task_runner) {
-}
-
-ChannelInfo::~ChannelInfo() {
-}
-
-void ChannelInfo::Swap(ChannelInfo* other) {
- // Note: Swapping avoids refcount churn.
- std::swap(channel, other->channel);
- std::swap(channel_thread_task_runner, other->channel_thread_task_runner);
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_info.h b/mojo/edk/system/channel_info.h
deleted file mode 100644
index 5167cca..0000000
--- a/mojo/edk/system/channel_info.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_INFO_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_INFO_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/task_runner.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-struct MOJO_SYSTEM_IMPL_EXPORT ChannelInfo {
- ChannelInfo();
- ChannelInfo(scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner);
- ~ChannelInfo();
-
- void Swap(ChannelInfo* other);
-
- scoped_refptr<Channel> channel;
- // The task runner for |channel|'s creation thread (a.k.a. its I/O thread), on
- // which it must, e.g., be shut down.
- scoped_refptr<base::TaskRunner> channel_thread_task_runner;
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_INFO_H_
diff --git a/mojo/edk/system/channel_manager.cc b/mojo/edk/system/channel_manager.cc
deleted file mode 100644
index 4e58f89..0000000
--- a/mojo/edk/system/channel_manager.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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/channel_manager.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-void ShutdownChannelHelper(const ChannelInfo& channel_info) {
- if (base::MessageLoopProxy::current() ==
- channel_info.channel_thread_task_runner) {
- channel_info.channel->Shutdown();
- } else {
- channel_info.channel->WillShutdownSoon();
- channel_info.channel_thread_task_runner->PostTask(
- FROM_HERE, base::Bind(&Channel::Shutdown, channel_info.channel));
- }
-}
-
-} // namespace
-
-ChannelManager::ChannelManager() {
-}
-
-ChannelManager::~ChannelManager() {
- // No need to take the lock.
- for (const auto& map_elem : channel_infos_)
- ShutdownChannelHelper(map_elem.second);
-}
-
-ChannelId ChannelManager::AddChannel(
- scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner) {
- ChannelId channel_id = GetChannelId(channel.get());
-
- {
- base::AutoLock locker(lock_);
- DCHECK(channel_infos_.find(channel_id) == channel_infos_.end());
- channel_infos_[channel_id] =
- ChannelInfo(channel, channel_thread_task_runner);
- }
- channel->SetChannelManager(this);
-
- return channel_id;
-}
-
-void ChannelManager::WillShutdownChannel(ChannelId channel_id) {
- GetChannelInfo(channel_id).channel->WillShutdownSoon();
-}
-
-void ChannelManager::ShutdownChannel(ChannelId channel_id) {
- ChannelInfo channel_info;
- {
- base::AutoLock locker(lock_);
- auto it = channel_infos_.find(channel_id);
- DCHECK(it != channel_infos_.end());
- channel_info.Swap(&it->second);
- channel_infos_.erase(it);
- }
- ShutdownChannelHelper(channel_info);
-}
-
-ChannelInfo ChannelManager::GetChannelInfo(ChannelId channel_id) {
- base::AutoLock locker(lock_);
- auto it = channel_infos_.find(channel_id);
- DCHECK(it != channel_infos_.end());
- return it->second;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_manager.h b/mojo/edk/system/channel_manager.h
deleted file mode 100644
index bb6371b..0000000
--- a/mojo/edk/system/channel_manager.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_
-
-#include <stdint.h>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "base/task_runner.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_info.h"
-
-namespace mojo {
-namespace system {
-
-// IDs for |Channel|s managed by a |ChannelManager|. (IDs should be thought of
-// as specific to a given |ChannelManager|.) 0 is never a valid ID.
-//
-// Note: We currently just use the pointer of the |Channel| casted to a
-// |uintptr_t|, but we reserve the right to change this.
-typedef uintptr_t ChannelId;
-
-// This class manages and "owns" |Channel|s (which typically connect to other
-// processes) for a given process. This class is thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
- public:
- ChannelManager();
- ~ChannelManager();
-
- // Adds |channel| to the set of |Channel|s managed by this |ChannelManager|;
- // |channel_thread_task_runner| should be the task runner for |channel|'s
- // creation (a.k.a. I/O) thread. |channel| should either already be
- // initialized. It should not be managed by any |ChannelManager| yet. Returns
- // the ID for the added channel.
- ChannelId AddChannel(
- scoped_refptr<Channel> channel,
- scoped_refptr<base::TaskRunner> channel_thread_task_runner);
-
- // Informs the channel manager (and thus channel) that it will be shutdown
- // soon (by calling |ShutdownChannel()|). Calling this is optional (and may in
- // fact be called multiple times) but it will suppress certain warnings (e.g.,
- // for the channel being broken) and enable others (if messages are written to
- // the channel).
- void WillShutdownChannel(ChannelId channel_id);
-
- // Shuts down the channel specified by the given ID. It is up to the caller to
- // guarantee that this is only called once per channel (that was added using
- // |AddChannel()|). If called from the chanel's creation thread (i.e.,
- // |base::MessageLoopProxy::current()| is the channel thread's |TaskRunner|),
- // this will complete synchronously.
- void ShutdownChannel(ChannelId channel_id);
-
- private:
- // Gets the ID for a given channel.
- //
- // Note: This is currently a static method and thus may be called under
- // |lock_|. If this is ever made non-static (i.e., made specific to a given
- // |ChannelManager|), those call sites may have to changed.
- static ChannelId GetChannelId(const Channel* channel) {
- return reinterpret_cast<ChannelId>(channel);
- }
-
- // Gets the |ChannelInfo| for the channel specified by the given ID. (This
- // should *not* be called under lock.)
- ChannelInfo GetChannelInfo(ChannelId channel_id);
-
- // Note: |Channel| methods should not be called under |lock_|.
- base::Lock lock_; // Protects the members below.
-
- base::hash_map<ChannelId, ChannelInfo> channel_infos_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelManager);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_
diff --git a/mojo/edk/system/channel_manager_unittest.cc b/mojo/edk/system/channel_manager_unittest.cc
deleted file mode 100644
index 52f3f0e..0000000
--- a/mojo/edk/system/channel_manager_unittest.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// 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/channel_manager.h"
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/run_loop.h"
-#include "base/task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/channel.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-class ChannelManagerTest : public testing::Test {
- public:
- ChannelManagerTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
- ~ChannelManagerTest() override {}
-
- protected:
- embedder::SimplePlatformSupport* platform_support() {
- return &platform_support_;
- }
- base::MessageLoop* message_loop() { return &message_loop_; }
-
- private:
- embedder::SimplePlatformSupport platform_support_;
- base::MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelManagerTest);
-};
-
-TEST_F(ChannelManagerTest, Basic) {
- ChannelManager cm;
-
- // Hang on to a ref to the |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to it.
- scoped_refptr<Channel> ch(new Channel(platform_support()));
- ASSERT_TRUE(ch->HasOneRef());
-
- embedder::PlatformChannelPair channel_pair;
- ch->Init(RawChannel::Create(channel_pair.PassServerHandle()));
-
- ChannelId id = cm.AddChannel(ch, base::MessageLoopProxy::current());
- EXPECT_NE(id, 0u);
- // |ChannelManager| should take a ref.
- EXPECT_FALSE(ch->HasOneRef());
-
- cm.WillShutdownChannel(id);
- // |ChannelManager| should still have a ref.
- EXPECT_FALSE(ch->HasOneRef());
-
- cm.ShutdownChannel(id);
- // On the "I/O" thread, so shutdown should happen synchronously.
- // |ChannelManager| should have given up its ref.
- EXPECT_TRUE(ch->HasOneRef());
-}
-
-TEST_F(ChannelManagerTest, TwoChannels) {
- ChannelManager cm;
-
- // Hang on to a ref to each |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to them.
- scoped_refptr<Channel> ch1(new Channel(platform_support()));
- ASSERT_TRUE(ch1->HasOneRef());
- scoped_refptr<Channel> ch2(new Channel(platform_support()));
- ASSERT_TRUE(ch2->HasOneRef());
-
- embedder::PlatformChannelPair channel_pair;
- ch1->Init(RawChannel::Create(channel_pair.PassServerHandle()));
- ch2->Init(RawChannel::Create(channel_pair.PassClientHandle()));
-
- ChannelId id1 = cm.AddChannel(ch1, base::MessageLoopProxy::current());
- EXPECT_NE(id1, 0u);
- EXPECT_FALSE(ch1->HasOneRef());
-
- ChannelId id2 = cm.AddChannel(ch2, base::MessageLoopProxy::current());
- EXPECT_NE(id2, 0u);
- EXPECT_NE(id2, id1);
- EXPECT_FALSE(ch2->HasOneRef());
-
- // Calling |WillShutdownChannel()| multiple times (on |id1|) is okay.
- cm.WillShutdownChannel(id1);
- cm.WillShutdownChannel(id1);
- EXPECT_FALSE(ch1->HasOneRef());
- // Not calling |WillShutdownChannel()| (on |id2|) is okay too.
-
- cm.ShutdownChannel(id1);
- EXPECT_TRUE(ch1->HasOneRef());
- cm.ShutdownChannel(id2);
- EXPECT_TRUE(ch2->HasOneRef());
-}
-
-class OtherThread : public base::SimpleThread {
- public:
- // Note: We rely on the main thread keeping *exactly one* reference to
- // |channel|.
- OtherThread(scoped_refptr<base::TaskRunner> task_runner,
- ChannelManager* channel_manager,
- Channel* channel,
- base::Closure quit_closure)
- : base::SimpleThread("other_thread"),
- task_runner_(task_runner),
- channel_manager_(channel_manager),
- channel_(channel),
- quit_closure_(quit_closure) {}
- ~OtherThread() override {}
-
- private:
- void Run() override {
- // See comment above constructor.
- ASSERT_TRUE(channel_->HasOneRef());
-
- ChannelId id = channel_manager_->AddChannel(make_scoped_refptr(channel_),
- task_runner_);
- EXPECT_NE(id, 0u);
- // |ChannelManager| should take a ref.
- EXPECT_FALSE(channel_->HasOneRef());
-
- channel_manager_->WillShutdownChannel(id);
- // |ChannelManager| should still have a ref.
- EXPECT_FALSE(channel_->HasOneRef());
-
- channel_manager_->ShutdownChannel(id);
- // This doesn't happen synchronously, so we "wait" until it does.
- // TODO(vtl): Possibly |Channel| should provide some notification of being
- // shut down.
- base::TimeTicks start_time(base::TimeTicks::Now());
- for (;;) {
- if (channel_->HasOneRef())
- break;
-
- // Check, instead of assert, since if things go wrong, dying is more
- // reliable than tearing down.
- CHECK_LT(base::TimeTicks::Now() - start_time,
- TestTimeouts::action_timeout());
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
- }
-
- CHECK(task_runner_->PostTask(FROM_HERE, quit_closure_));
- }
-
- scoped_refptr<base::TaskRunner> task_runner_;
- ChannelManager* channel_manager_;
- Channel* channel_;
- base::Closure quit_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(OtherThread);
-};
-
-TEST_F(ChannelManagerTest, CallsFromOtherThread) {
- ChannelManager cm;
-
- // Hang on to a ref to the |Channel|, so that we can check that the
- // |ChannelManager| takes/releases refs to it.
- scoped_refptr<Channel> ch(new Channel(platform_support()));
- ASSERT_TRUE(ch->HasOneRef());
-
- embedder::PlatformChannelPair channel_pair;
- ch->Init(RawChannel::Create(channel_pair.PassServerHandle()));
-
- base::RunLoop run_loop;
- OtherThread thread(base::MessageLoopProxy::current(), &cm, ch.get(),
- run_loop.QuitClosure());
- thread.Start();
- run_loop.Run();
- thread.Join();
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc
deleted file mode 100644
index e82b321..0000000
--- a/mojo/edk/system/channel_unittest.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// 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/channel.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/test_io_thread.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/raw_channel.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/waiter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-class ChannelTest : public testing::Test {
- public:
- ChannelTest() : io_thread_(base::TestIOThread::kAutoStart) {}
- ~ChannelTest() override {}
-
- void SetUp() override {
- io_thread_.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelTest::SetUpOnIOThread, base::Unretained(this)));
- }
-
- void CreateChannelOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
- channel_ = new Channel(&platform_support_);
- }
-
- void InitChannelOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- CHECK(raw_channel_);
- CHECK(channel_);
- channel_->Init(raw_channel_.Pass());
- }
-
- void ShutdownChannelOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- CHECK(channel_);
- channel_->Shutdown();
- }
-
- base::TestIOThread* io_thread() { return &io_thread_; }
- RawChannel* raw_channel() { return raw_channel_.get(); }
- scoped_ptr<RawChannel>* mutable_raw_channel() { return &raw_channel_; }
- Channel* channel() { return channel_.get(); }
- scoped_refptr<Channel>* mutable_channel() { return &channel_; }
-
- private:
- void SetUpOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- embedder::PlatformChannelPair channel_pair;
- raw_channel_ = RawChannel::Create(channel_pair.PassServerHandle()).Pass();
- other_platform_handle_ = channel_pair.PassClientHandle();
- }
-
- embedder::SimplePlatformSupport platform_support_;
- base::TestIOThread io_thread_;
- scoped_ptr<RawChannel> raw_channel_;
- embedder::ScopedPlatformHandle other_platform_handle_;
- scoped_refptr<Channel> channel_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelTest);
-};
-
-// ChannelTest.InitShutdown ----------------------------------------------------
-
-TEST_F(ChannelTest, InitShutdown) {
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&ChannelTest::CreateChannelOnIOThread,
- base::Unretained(this)));
- ASSERT_TRUE(channel());
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this)));
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread,
- base::Unretained(this)));
-
- // Okay to destroy |Channel| on not-the-I/O-thread.
- EXPECT_TRUE(channel()->HasOneRef());
- *mutable_channel() = nullptr;
-}
-
-// ChannelTest.CloseBeforeAttachAndRun -----------------------------------------
-
-TEST_F(ChannelTest, CloseBeforeRun) {
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&ChannelTest::CreateChannelOnIOThread,
- base::Unretained(this)));
- ASSERT_TRUE(channel());
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this)));
-
- scoped_refptr<ChannelEndpoint> channel_endpoint;
- scoped_refptr<MessagePipe> mp(
- MessagePipe::CreateLocalProxy(&channel_endpoint));
-
- mp->Close(0);
-
- channel()->SetBootstrapEndpoint(channel_endpoint);
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread,
- base::Unretained(this)));
-
- EXPECT_TRUE(channel()->HasOneRef());
-}
-
-// ChannelTest.ShutdownAfterAttachAndRun ---------------------------------------
-
-TEST_F(ChannelTest, ShutdownAfterAttach) {
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&ChannelTest::CreateChannelOnIOThread,
- base::Unretained(this)));
- ASSERT_TRUE(channel());
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this)));
-
- scoped_refptr<ChannelEndpoint> channel_endpoint;
- scoped_refptr<MessagePipe> mp(
- MessagePipe::CreateLocalProxy(&channel_endpoint));
-
- channel()->SetBootstrapEndpoint(channel_endpoint);
-
- Waiter waiter;
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Don't wait for the shutdown to run ...
- io_thread()->PostTask(FROM_HERE,
- base::Bind(&ChannelTest::ShutdownChannelOnIOThread,
- base::Unretained(this)));
-
- // ... since this |Wait()| should fail once the channel is shut down.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr));
- HandleSignalsState hss;
- mp->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->Close(0);
-
- EXPECT_TRUE(channel()->HasOneRef());
-}
-
-// ChannelTest.WaitAfterAttachRunAndShutdown -----------------------------------
-
-TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) {
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&ChannelTest::CreateChannelOnIOThread,
- base::Unretained(this)));
- ASSERT_TRUE(channel());
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this)));
-
- scoped_refptr<ChannelEndpoint> channel_endpoint;
- scoped_refptr<MessagePipe> mp(
- MessagePipe::CreateLocalProxy(&channel_endpoint));
-
- channel()->SetBootstrapEndpoint(channel_endpoint);
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread,
- base::Unretained(this)));
-
- Waiter waiter;
- waiter.Init();
- HandleSignalsState hss;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->Close(0);
-
- EXPECT_TRUE(channel()->HasOneRef());
-}
-
-// TODO(vtl): More. ------------------------------------------------------------
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/configuration.cc b/mojo/edk/system/configuration.cc
deleted file mode 100644
index 4756c99..0000000
--- a/mojo/edk/system/configuration.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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/configuration.h"
-
-namespace mojo {
-namespace system {
-namespace internal {
-
-// These default values should be synced with the documentation in
-// mojo/edk/embedder/configuration.h.
-embedder::Configuration g_configuration = {
- 1000000, // max_handle_table_size
- 1000000, // max_mapping_table_sze
- 1000000, // max_wait_many_num_handles
- 4 * 1024 * 1024, // max_message_num_bytes
- 10000, // max_message_num_handles
- 256 * 1024 * 1024, // max_data_pipe_capacity_bytes
- 1024 * 1024, // default_data_pipe_capacity_bytes
- 16, // data_pipe_buffer_alignment_bytes
- 1024 * 1024 * 1024}; // max_shared_memory_num_bytes
-
-} // namespace internal
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/configuration.h b/mojo/edk/system/configuration.h
deleted file mode 100644
index 007277a..0000000
--- a/mojo/edk/system/configuration.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_CONFIGURATION_H_
-#define MOJO_EDK_SYSTEM_CONFIGURATION_H_
-
-#include "mojo/edk/embedder/configuration.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-namespace internal {
-MOJO_SYSTEM_IMPL_EXPORT extern embedder::Configuration g_configuration;
-} // namespace internal
-
-MOJO_SYSTEM_IMPL_EXPORT inline const embedder::Configuration&
-GetConfiguration() {
- return internal::g_configuration;
-}
-
-MOJO_SYSTEM_IMPL_EXPORT inline embedder::Configuration*
-GetMutableConfiguration() {
- return &internal::g_configuration;
-}
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CONFIGURATION_H_
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc
deleted file mode 100644
index 6189e50..0000000
--- a/mojo/edk/system/core.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2013 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/core.h"
-
-#include <vector>
-
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/embedder/platform_support.h"
-#include "mojo/edk/system/async_waiter.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
-#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/local_data_pipe.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/public/c/system/macros.h"
-
-namespace mojo {
-namespace system {
-
-// Implementation notes
-//
-// Mojo primitives are implemented by the singleton |Core| object. Most calls
-// are for a "primary" handle (the first argument). |Core::GetDispatcher()| is
-// used to look up a |Dispatcher| object for a given handle. That object
-// implements most primitives for that object. The wait primitives are not
-// attached to objects and are implemented by |Core| itself.
-//
-// Some objects have multiple handles associated to them, e.g., message pipes
-// (which have two). In such a case, there is still a |Dispatcher| (e.g.,
-// |MessagePipeDispatcher|) for each handle, with each handle having a strong
-// reference to the common "secondary" object (e.g., |MessagePipe|). This
-// secondary object does NOT have any references to the |Dispatcher|s (even if
-// it did, it wouldn't be able to do anything with them due to lock order
-// requirements -- see below).
-//
-// Waiting is implemented by having the thread that wants to wait call the
-// |Dispatcher|s for the handles that it wants to wait on with a |Waiter|
-// object; this |Waiter| object may be created on the stack of that thread or be
-// kept in thread local storage for that thread (TODO(vtl): future improvement).
-// The |Dispatcher| then adds the |Waiter| to an |AwakableList| that's either
-// owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object
-// (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question --
-// either a |SimpleDispatcher| or a secondary object -- talks to its
-// |AwakableList|.
-
-// Thread-safety notes
-//
-// Mojo primitives calls are thread-safe. We achieve this with relatively
-// fine-grained locking. There is a global handle table lock. This lock should
-// be held as briefly as possible (TODO(vtl): a future improvement would be to
-// switch it to a reader-writer lock). Each |Dispatcher| object then has a lock
-// (which subclasses can use to protect their data).
-//
-// The lock ordering is as follows:
-// 1. global handle table lock, global mapping table lock
-// 2. |Dispatcher| locks
-// 3. secondary object locks
-// ...
-// INF. |Waiter| locks
-//
-// Notes:
-// - While holding a |Dispatcher| lock, you may not unconditionally attempt
-// to take another |Dispatcher| lock. (This has consequences on the
-// concurrency semantics of |MojoWriteMessage()| when passing handles.)
-// Doing so would lead to deadlock.
-// - Locks at the "INF" level may not have any locks taken while they are
-// held.
-
-// TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter.
-Core::Core(scoped_ptr<embedder::PlatformSupport> platform_support)
- : platform_support_(platform_support.Pass()) {
-}
-
-Core::~Core() {
-}
-
-MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) {
- base::AutoLock locker(handle_table_lock_);
- return handle_table_.AddDispatcher(dispatcher);
-}
-
-scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
- if (handle == MOJO_HANDLE_INVALID)
- return nullptr;
-
- base::AutoLock locker(handle_table_lock_);
- return handle_table_.GetDispatcher(handle);
-}
-
-MojoResult Core::AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback) {
- scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
- DCHECK(dispatcher);
-
- scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback));
- MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr);
- if (rv == MOJO_RESULT_OK)
- ignore_result(waiter.release());
- return rv;
-}
-
-MojoTimeTicks Core::GetTimeTicksNow() {
- return base::TimeTicks::Now().ToInternalValue();
-}
-
-MojoResult Core::Close(MojoHandle handle) {
- if (handle == MOJO_HANDLE_INVALID)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- scoped_refptr<Dispatcher> dispatcher;
- {
- base::AutoLock locker(handle_table_lock_);
- MojoResult result =
- handle_table_.GetAndRemoveDispatcher(handle, &dispatcher);
- if (result != MOJO_RESULT_OK)
- return result;
- }
-
- // The dispatcher doesn't have a say in being closed, but gets notified of it.
- // Note: This is done outside of |handle_table_lock_|. As a result, there's a
- // race condition that the dispatcher must handle; see the comment in
- // |Dispatcher| in dispatcher.h.
- return dispatcher->Close();
-}
-
-MojoResult Core::Wait(MojoHandle handle,
- MojoHandleSignals signals,
- MojoDeadline deadline,
- UserPointer<MojoHandleSignalsState> signals_state) {
- uint32_t unused = static_cast<uint32_t>(-1);
- HandleSignalsState hss;
- MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused,
- signals_state.IsNull() ? nullptr : &hss);
- if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull())
- signals_state.Put(hss);
- return rv;
-}
-
-MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles,
- UserPointer<const MojoHandleSignals> signals,
- uint32_t num_handles,
- MojoDeadline deadline,
- UserPointer<uint32_t> result_index,
- UserPointer<MojoHandleSignalsState> signals_states) {
- if (num_handles < 1)
- return MOJO_RESULT_INVALID_ARGUMENT;
- if (num_handles > GetConfiguration().max_wait_many_num_handles)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles);
- UserPointer<const MojoHandleSignals>::Reader signals_reader(signals,
- num_handles);
- uint32_t index = static_cast<uint32_t>(-1);
- MojoResult rv;
- if (signals_states.IsNull()) {
- rv = WaitManyInternal(handles_reader.GetPointer(),
- signals_reader.GetPointer(), num_handles, deadline,
- &index, nullptr);
- } else {
- UserPointer<MojoHandleSignalsState>::Writer signals_states_writer(
- signals_states, num_handles);
- // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
- // subclass of |MojoHandleSignalsState| that doesn't add any data members.
- rv = WaitManyInternal(handles_reader.GetPointer(),
- signals_reader.GetPointer(), num_handles, deadline,
- &index, reinterpret_cast<HandleSignalsState*>(
- signals_states_writer.GetPointer()));
- if (rv != MOJO_RESULT_INVALID_ARGUMENT)
- signals_states_writer.Commit();
- }
- if (index != static_cast<uint32_t>(-1) && !result_index.IsNull())
- result_index.Put(index);
- return rv;
-}
-
-MojoResult Core::CreateMessagePipe(
- UserPointer<const MojoCreateMessagePipeOptions> options,
- UserPointer<MojoHandle> message_pipe_handle0,
- UserPointer<MojoHandle> message_pipe_handle1) {
- MojoCreateMessagePipeOptions validated_options = {};
- MojoResult result =
- MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options);
- if (result != MOJO_RESULT_OK)
- return result;
-
- scoped_refptr<MessagePipeDispatcher> dispatcher0(
- new MessagePipeDispatcher(validated_options));
- scoped_refptr<MessagePipeDispatcher> dispatcher1(
- new MessagePipeDispatcher(validated_options));
-
- std::pair<MojoHandle, MojoHandle> handle_pair;
- {
- base::AutoLock locker(handle_table_lock_);
- handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1);
- }
- if (handle_pair.first == MOJO_HANDLE_INVALID) {
- DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID);
- LOG(ERROR) << "Handle table full";
- dispatcher0->Close();
- dispatcher1->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
-
- scoped_refptr<MessagePipe> message_pipe(MessagePipe::CreateLocalLocal());
- dispatcher0->Init(message_pipe, 0);
- dispatcher1->Init(message_pipe, 1);
-
- message_pipe_handle0.Put(handle_pair.first);
- message_pipe_handle1.Put(handle_pair.second);
- return MOJO_RESULT_OK;
-}
-
-// Implementation note: To properly cancel waiters and avoid other races, this
-// does not transfer dispatchers from one handle to another, even when sending a
-// message in-process. Instead, it must transfer the "contents" of the
-// dispatcher to a new dispatcher, and then close the old dispatcher. If this
-// isn't done, in the in-process case, calls on the old handle may complete
-// after the the message has been received and a new handle created (and
-// possibly even after calls have been made on the new handle).
-MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- UserPointer<const MojoHandle> handles,
- uint32_t num_handles,
- MojoWriteMessageFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- // Easy case: not sending any handles.
- if (num_handles == 0)
- return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags);
-
- // We have to handle |handles| here, since we have to mark them busy in the
- // global handle table. We can't delegate this to the dispatcher, since the
- // handle table lock must be acquired before the dispatcher lock.
- //
- // (This leads to an oddity: |handles|/|num_handles| are always verified for
- // validity, even for dispatchers that don't support |WriteMessage()| and will
- // simply return failure unconditionally. It also breaks the usual
- // left-to-right verification order of arguments.)
- if (num_handles > GetConfiguration().max_message_num_handles)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles);
-
- // We'll need to hold on to the dispatchers so that we can pass them on to
- // |WriteMessage()| and also so that we can unlock their locks afterwards
- // without accessing the handle table. These can be dumb pointers, since their
- // entries in the handle table won't get removed (since they'll be marked as
- // busy).
- std::vector<DispatcherTransport> transports(num_handles);
-
- // When we pass handles, we have to try to take all their dispatchers' locks
- // and mark the handles as busy. If the call succeeds, we then remove the
- // handles from the handle table.
- {
- base::AutoLock locker(handle_table_lock_);
- MojoResult result = handle_table_.MarkBusyAndStartTransport(
- message_pipe_handle, handles_reader.GetPointer(), num_handles,
- &transports);
- if (result != MOJO_RESULT_OK)
- return result;
- }
-
- MojoResult rv =
- dispatcher->WriteMessage(bytes, num_bytes, &transports, flags);
-
- // We need to release the dispatcher locks before we take the handle table
- // lock.
- for (uint32_t i = 0; i < num_handles; i++)
- transports[i].End();
-
- {
- base::AutoLock locker(handle_table_lock_);
- if (rv == MOJO_RESULT_OK) {
- handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles);
- } else {
- handle_table_.RestoreBusyHandles(handles_reader.GetPointer(),
- num_handles);
- }
- }
-
- return rv;
-}
-
-MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- UserPointer<MojoHandle> handles,
- UserPointer<uint32_t> num_handles,
- MojoReadMessageFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get();
-
- MojoResult rv;
- if (num_handles_value == 0) {
- // Easy case: won't receive any handles.
- rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value,
- flags);
- } else {
- DispatcherVector dispatchers;
- rv = dispatcher->ReadMessage(bytes, num_bytes, &dispatchers,
- &num_handles_value, flags);
- if (!dispatchers.empty()) {
- DCHECK_EQ(rv, MOJO_RESULT_OK);
- DCHECK(!num_handles.IsNull());
- DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value));
-
- bool success;
- UserPointer<MojoHandle>::Writer handles_writer(handles,
- dispatchers.size());
- {
- base::AutoLock locker(handle_table_lock_);
- success = handle_table_.AddDispatcherVector(
- dispatchers, handles_writer.GetPointer());
- }
- if (success) {
- handles_writer.Commit();
- } else {
- LOG(ERROR) << "Received message with " << dispatchers.size()
- << " handles, but handle table full";
- // Close dispatchers (outside the lock).
- for (size_t i = 0; i < dispatchers.size(); i++) {
- if (dispatchers[i])
- dispatchers[i]->Close();
- }
- if (rv == MOJO_RESULT_OK)
- rv = MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
- }
- }
-
- if (!num_handles.IsNull())
- num_handles.Put(num_handles_value);
- return rv;
-}
-
-MojoResult Core::CreateDataPipe(
- UserPointer<const MojoCreateDataPipeOptions> options,
- UserPointer<MojoHandle> data_pipe_producer_handle,
- UserPointer<MojoHandle> data_pipe_consumer_handle) {
- MojoCreateDataPipeOptions validated_options = {};
- MojoResult result =
- DataPipe::ValidateCreateOptions(options, &validated_options);
- if (result != MOJO_RESULT_OK)
- return result;
-
- scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher(
- new DataPipeProducerDispatcher());
- scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher(
- new DataPipeConsumerDispatcher());
-
- std::pair<MojoHandle, MojoHandle> handle_pair;
- {
- base::AutoLock locker(handle_table_lock_);
- handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher,
- consumer_dispatcher);
- }
- if (handle_pair.first == MOJO_HANDLE_INVALID) {
- DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID);
- LOG(ERROR) << "Handle table full";
- producer_dispatcher->Close();
- consumer_dispatcher->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
- DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID);
-
- scoped_refptr<DataPipe> data_pipe(new LocalDataPipe(validated_options));
- producer_dispatcher->Init(data_pipe);
- consumer_dispatcher->Init(data_pipe);
-
- data_pipe_producer_handle.Put(handle_pair.first);
- data_pipe_consumer_handle.Put(handle_pair.second);
- return MOJO_RESULT_OK;
-}
-
-MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_producer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->WriteData(elements, num_bytes, flags);
-}
-
-MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_producer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
-}
-
-MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
- uint32_t num_bytes_written) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_producer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->EndWriteData(num_bytes_written);
-}
-
-MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
- UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_consumer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->ReadData(elements, num_bytes, flags);
-}
-
-MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_consumer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
-}
-
-MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
- uint32_t num_bytes_read) {
- scoped_refptr<Dispatcher> dispatcher(
- GetDispatcher(data_pipe_consumer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->EndReadData(num_bytes_read);
-}
-
-MojoResult Core::CreateSharedBuffer(
- UserPointer<const MojoCreateSharedBufferOptions> options,
- uint64_t num_bytes,
- UserPointer<MojoHandle> shared_buffer_handle) {
- MojoCreateSharedBufferOptions validated_options = {};
- MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
- options, &validated_options);
- if (result != MOJO_RESULT_OK)
- return result;
-
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- result = SharedBufferDispatcher::Create(platform_support(), validated_options,
- num_bytes, &dispatcher);
- if (result != MOJO_RESULT_OK) {
- DCHECK(!dispatcher);
- return result;
- }
-
- MojoHandle h = AddDispatcher(dispatcher);
- if (h == MOJO_HANDLE_INVALID) {
- LOG(ERROR) << "Handle table full";
- dispatcher->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
-
- shared_buffer_handle.Put(h);
- return MOJO_RESULT_OK;
-}
-
-MojoResult Core::DuplicateBufferHandle(
- MojoHandle buffer_handle,
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- UserPointer<MojoHandle> new_buffer_handle) {
- scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- // Don't verify |options| here; that's the dispatcher's job.
- scoped_refptr<Dispatcher> new_dispatcher;
- MojoResult result =
- dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
- if (result != MOJO_RESULT_OK)
- return result;
-
- MojoHandle new_handle = AddDispatcher(new_dispatcher);
- if (new_handle == MOJO_HANDLE_INVALID) {
- LOG(ERROR) << "Handle table full";
- dispatcher->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
-
- new_buffer_handle.Put(new_handle);
- return MOJO_RESULT_OK;
-}
-
-MojoResult Core::MapBuffer(MojoHandle buffer_handle,
- uint64_t offset,
- uint64_t num_bytes,
- UserPointer<void*> buffer,
- MojoMapBufferFlags flags) {
- scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
- MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
- if (result != MOJO_RESULT_OK)
- return result;
-
- DCHECK(mapping);
- void* address = mapping->GetBase();
- {
- base::AutoLock locker(mapping_table_lock_);
- result = mapping_table_.AddMapping(mapping.Pass());
- }
- if (result != MOJO_RESULT_OK)
- return result;
-
- buffer.Put(address);
- return MOJO_RESULT_OK;
-}
-
-MojoResult Core::UnmapBuffer(UserPointer<void> buffer) {
- base::AutoLock locker(mapping_table_lock_);
- return mapping_table_.RemoveMapping(buffer.GetPointerValue());
-}
-
-// Note: We allow |handles| to repeat the same handle multiple times, since
-// different flags may be specified.
-// TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this
-// more carefully and address it if necessary.
-MojoResult Core::WaitManyInternal(const MojoHandle* handles,
- const MojoHandleSignals* signals,
- uint32_t num_handles,
- MojoDeadline deadline,
- uint32_t* result_index,
- HandleSignalsState* signals_states) {
- DCHECK_GT(num_handles, 0u);
- DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));
-
- DispatcherVector dispatchers;
- dispatchers.reserve(num_handles);
- for (uint32_t i = 0; i < num_handles; i++) {
- scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]);
- if (!dispatcher) {
- *result_index = i;
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
- dispatchers.push_back(dispatcher);
- }
-
- // TODO(vtl): Should make the waiter live (permanently) in TLS.
- Waiter waiter;
- waiter.Init();
-
- uint32_t i;
- MojoResult rv = MOJO_RESULT_OK;
- for (i = 0; i < num_handles; i++) {
- rv = dispatchers[i]->AddAwakable(
- &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr);
- if (rv != MOJO_RESULT_OK) {
- *result_index = i;
- break;
- }
- }
- uint32_t num_added = i;
-
- if (rv == MOJO_RESULT_ALREADY_EXISTS)
- rv = MOJO_RESULT_OK; // The i-th one is already "triggered".
- else if (rv == MOJO_RESULT_OK)
- rv = waiter.Wait(deadline, result_index);
-
- // Make sure no other dispatchers try to wake |waiter| for the current
- // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
- // destroyed, but this would still be required if the waiter were in TLS.)
- for (i = 0; i < num_added; i++) {
- dispatchers[i]->RemoveAwakable(
- &waiter, signals_states ? &signals_states[i] : nullptr);
- }
- if (signals_states) {
- for (; i < num_handles; i++)
- signals_states[i] = dispatchers[i]->GetHandleSignalsState();
- }
-
- return rv;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h
deleted file mode 100644
index 0ff9c01..0000000
--- a/mojo/edk/system/core.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_CORE_H_
-#define MOJO_EDK_SYSTEM_CORE_H_
-
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/handle_table.h"
-#include "mojo/edk/system/mapping_table.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/buffer.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/message_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformSupport;
-}
-
-namespace system {
-
-class Dispatcher;
-struct HandleSignalsState;
-
-// |Core| is an object that implements the Mojo system calls. All public methods
-// are thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT Core {
- public:
- // ---------------------------------------------------------------------------
-
- // These methods are only to be used by via the embedder API (and internally):
- explicit Core(scoped_ptr<embedder::PlatformSupport> platform_support);
- virtual ~Core();
-
- // Adds |dispatcher| to the handle table, returning the handle for it. Returns
- // |MOJO_HANDLE_INVALID| on failure, namely if the handle table is full.
- MojoHandle AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher);
-
- // Looks up the dispatcher for the given handle. Returns null if the handle is
- // invalid.
- scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
-
- // Watches on the given handle for the given signals, calling |callback| when
- // a signal is satisfied or when all signals become unsatisfiable. |callback|
- // must satisfy stringent requirements -- see |Awakable::Awake()| in
- // awakable.h. In particular, it must not call any Mojo system functions.
- MojoResult AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback);
-
- embedder::PlatformSupport* platform_support() const {
- return platform_support_.get();
- }
-
- // ---------------------------------------------------------------------------
-
- // System calls implementation:
- MojoTimeTicks GetTimeTicksNow();
- MojoResult Close(MojoHandle handle);
- MojoResult Wait(MojoHandle handle,
- MojoHandleSignals signals,
- MojoDeadline deadline,
- UserPointer<MojoHandleSignalsState> signals_state);
- MojoResult WaitMany(UserPointer<const MojoHandle> handles,
- UserPointer<const MojoHandleSignals> signals,
- uint32_t num_handles,
- MojoDeadline deadline,
- UserPointer<uint32_t> result_index,
- UserPointer<MojoHandleSignalsState> signals_states);
- MojoResult CreateMessagePipe(
- UserPointer<const MojoCreateMessagePipeOptions> options,
- UserPointer<MojoHandle> message_pipe_handle0,
- UserPointer<MojoHandle> message_pipe_handle1);
- MojoResult WriteMessage(MojoHandle message_pipe_handle,
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- UserPointer<const MojoHandle> handles,
- uint32_t num_handles,
- MojoWriteMessageFlags flags);
- MojoResult ReadMessage(MojoHandle message_pipe_handle,
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- UserPointer<MojoHandle> handles,
- UserPointer<uint32_t> num_handles,
- MojoReadMessageFlags flags);
- MojoResult CreateDataPipe(
- UserPointer<const MojoCreateDataPipeOptions> options,
- UserPointer<MojoHandle> data_pipe_producer_handle,
- UserPointer<MojoHandle> data_pipe_consumer_handle);
- MojoResult WriteData(MojoHandle data_pipe_producer_handle,
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags);
- MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle,
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags);
- MojoResult EndWriteData(MojoHandle data_pipe_producer_handle,
- uint32_t num_bytes_written);
- MojoResult ReadData(MojoHandle data_pipe_consumer_handle,
- UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags);
- MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle,
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags);
- MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
- uint32_t num_bytes_read);
- MojoResult CreateSharedBuffer(
- UserPointer<const MojoCreateSharedBufferOptions> options,
- uint64_t num_bytes,
- UserPointer<MojoHandle> shared_buffer_handle);
- MojoResult DuplicateBufferHandle(
- MojoHandle buffer_handle,
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- UserPointer<MojoHandle> new_buffer_handle);
- MojoResult MapBuffer(MojoHandle buffer_handle,
- uint64_t offset,
- uint64_t num_bytes,
- UserPointer<void*> buffer,
- MojoMapBufferFlags flags);
- MojoResult UnmapBuffer(UserPointer<void> buffer);
-
- private:
- friend bool internal::ShutdownCheckNoLeaks(Core*);
-
- // Internal implementation of |Wait()| and |WaitMany()|; doesn't do basic
- // validation of arguments. |*result_index| is only set if the result (whether
- // success or failure) applies to a specific handle, so its value should be
- // preinitialized to |static_cast<uint32_t>(-1)|.
- MojoResult WaitManyInternal(const MojoHandle* handles,
- const MojoHandleSignals* signals,
- uint32_t num_handles,
- MojoDeadline deadline,
- uint32_t* result_index,
- HandleSignalsState* signals_states);
-
- const scoped_ptr<embedder::PlatformSupport> platform_support_;
-
- // TODO(vtl): |handle_table_lock_| should be a reader-writer lock (if only we
- // had them).
- base::Lock handle_table_lock_; // Protects |handle_table_|.
- HandleTable handle_table_;
-
- base::Lock mapping_table_lock_; // Protects |mapping_table_|.
- MappingTable mapping_table_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CORE_H_
diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc
deleted file mode 100644
index b81a051..0000000
--- a/mojo/edk/system/core_test_base.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2013 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/core_test_base.h"
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/memory.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-namespace {
-
-// MockDispatcher --------------------------------------------------------------
-
-class MockDispatcher : public Dispatcher {
- public:
- explicit MockDispatcher(CoreTestBase::MockHandleInfo* info) : info_(info) {
- CHECK(info_);
- info_->IncrementCtorCallCount();
- }
-
- // |Dispatcher| private methods:
- Type GetType() const override { return kTypeUnknown; }
-
- private:
- ~MockDispatcher() override { info_->IncrementDtorCallCount(); }
-
- // |Dispatcher| protected methods:
- void CloseImplNoLock() override {
- info_->IncrementCloseCallCount();
- lock().AssertAcquired();
- }
-
- MojoResult WriteMessageImplNoLock(
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags /*flags*/) override {
- info_->IncrementWriteMessageCallCount();
- lock().AssertAcquired();
-
- if (num_bytes > GetConfiguration().max_message_num_bytes)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- if (transports)
- return MOJO_RESULT_UNIMPLEMENTED;
-
- return MOJO_RESULT_OK;
- }
-
- MojoResult ReadMessageImplNoLock(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags /*flags*/) override {
- info_->IncrementReadMessageCallCount();
- lock().AssertAcquired();
-
- if (num_dispatchers) {
- *num_dispatchers = 1;
- if (dispatchers) {
- // Okay to leave an invalid dispatcher.
- dispatchers->resize(1);
- }
- }
-
- return MOJO_RESULT_OK;
- }
-
- MojoResult WriteDataImplNoLock(UserPointer<const void> /*elements*/,
- UserPointer<uint32_t> /*num_bytes*/,
- MojoWriteDataFlags /*flags*/) override {
- info_->IncrementWriteDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult BeginWriteDataImplNoLock(
- UserPointer<void*> /*buffer*/,
- UserPointer<uint32_t> /*buffer_num_bytes*/,
- MojoWriteDataFlags /*flags*/) override {
- info_->IncrementBeginWriteDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) override {
- info_->IncrementEndWriteDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult ReadDataImplNoLock(UserPointer<void> /*elements*/,
- UserPointer<uint32_t> /*num_bytes*/,
- MojoReadDataFlags /*flags*/) override {
- info_->IncrementReadDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult BeginReadDataImplNoLock(UserPointer<const void*> /*buffer*/,
- UserPointer<uint32_t> /*buffer_num_bytes*/,
- MojoReadDataFlags /*flags*/) override {
- info_->IncrementBeginReadDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) override {
- info_->IncrementEndReadDataCallCount();
- lock().AssertAcquired();
- return MOJO_RESULT_UNIMPLEMENTED;
- }
-
- MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals /*signals*/,
- uint32_t /*context*/,
- HandleSignalsState* signals_state) override {
- info_->IncrementAddAwakableCallCount();
- lock().AssertAcquired();
- if (signals_state)
- *signals_state = HandleSignalsState();
- if (info_->IsAddAwakableAllowed()) {
- info_->AwakableWasAdded(awakable);
- return MOJO_RESULT_OK;
- }
-
- return MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- void RemoveAwakableImplNoLock(Awakable* /*awakable*/,
- HandleSignalsState* signals_state) override {
- info_->IncrementRemoveAwakableCallCount();
- lock().AssertAcquired();
- if (signals_state)
- *signals_state = HandleSignalsState();
- }
-
- void CancelAllAwakablesNoLock() override {
- info_->IncrementCancelAllAwakablesCallCount();
- lock().AssertAcquired();
- }
-
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override {
- return scoped_refptr<Dispatcher>(new MockDispatcher(info_));
- }
-
- CoreTestBase::MockHandleInfo* const info_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
-};
-
-} // namespace
-
-// CoreTestBase ----------------------------------------------------------------
-
-CoreTestBase::CoreTestBase() {
-}
-
-CoreTestBase::~CoreTestBase() {
-}
-
-void CoreTestBase::SetUp() {
- core_ = new Core(make_scoped_ptr(new embedder::SimplePlatformSupport()));
-}
-
-void CoreTestBase::TearDown() {
- delete core_;
- core_ = nullptr;
-}
-
-MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) {
- CHECK(core_);
- scoped_refptr<MockDispatcher> dispatcher(new MockDispatcher(info));
- return core_->AddDispatcher(dispatcher);
-}
-
-// CoreTestBase_MockHandleInfo -------------------------------------------------
-
-CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo()
- : ctor_call_count_(0),
- dtor_call_count_(0),
- close_call_count_(0),
- write_message_call_count_(0),
- read_message_call_count_(0),
- write_data_call_count_(0),
- begin_write_data_call_count_(0),
- end_write_data_call_count_(0),
- read_data_call_count_(0),
- begin_read_data_call_count_(0),
- end_read_data_call_count_(0),
- add_awakable_call_count_(0),
- remove_awakable_call_count_(0),
- cancel_all_awakables_call_count_(0),
- add_awakable_allowed_(false) {
-}
-
-CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() {
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetCtorCallCount() const {
- base::AutoLock locker(lock_);
- return ctor_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetDtorCallCount() const {
- base::AutoLock locker(lock_);
- return dtor_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetCloseCallCount() const {
- base::AutoLock locker(lock_);
- return close_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetWriteMessageCallCount() const {
- base::AutoLock locker(lock_);
- return write_message_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetReadMessageCallCount() const {
- base::AutoLock locker(lock_);
- return read_message_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetWriteDataCallCount() const {
- base::AutoLock locker(lock_);
- return write_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetBeginWriteDataCallCount() const {
- base::AutoLock locker(lock_);
- return begin_write_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetEndWriteDataCallCount() const {
- base::AutoLock locker(lock_);
- return end_write_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetReadDataCallCount() const {
- base::AutoLock locker(lock_);
- return read_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetBeginReadDataCallCount() const {
- base::AutoLock locker(lock_);
- return begin_read_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetEndReadDataCallCount() const {
- base::AutoLock locker(lock_);
- return end_read_data_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetAddAwakableCallCount() const {
- base::AutoLock locker(lock_);
- return add_awakable_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetRemoveAwakableCallCount() const {
- base::AutoLock locker(lock_);
- return remove_awakable_call_count_;
-}
-
-unsigned CoreTestBase_MockHandleInfo::GetCancelAllAwakablesCallCount() const {
- base::AutoLock locker(lock_);
- return cancel_all_awakables_call_count_;
-}
-
-size_t CoreTestBase_MockHandleInfo::GetAddedAwakableSize() const {
- base::AutoLock locker(lock_);
- return added_awakables_.size();
-}
-
-Awakable* CoreTestBase_MockHandleInfo::GetAddedAwakableAt(unsigned i) const {
- base::AutoLock locker(lock_);
- return added_awakables_[i];
-}
-
-void CoreTestBase_MockHandleInfo::IncrementCtorCallCount() {
- base::AutoLock locker(lock_);
- ctor_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementDtorCallCount() {
- base::AutoLock locker(lock_);
- dtor_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementCloseCallCount() {
- base::AutoLock locker(lock_);
- close_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementWriteMessageCallCount() {
- base::AutoLock locker(lock_);
- write_message_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementReadMessageCallCount() {
- base::AutoLock locker(lock_);
- read_message_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementWriteDataCallCount() {
- base::AutoLock locker(lock_);
- write_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementBeginWriteDataCallCount() {
- base::AutoLock locker(lock_);
- begin_write_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementEndWriteDataCallCount() {
- base::AutoLock locker(lock_);
- end_write_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementReadDataCallCount() {
- base::AutoLock locker(lock_);
- read_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementBeginReadDataCallCount() {
- base::AutoLock locker(lock_);
- begin_read_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementEndReadDataCallCount() {
- base::AutoLock locker(lock_);
- end_read_data_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementAddAwakableCallCount() {
- base::AutoLock locker(lock_);
- add_awakable_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementRemoveAwakableCallCount() {
- base::AutoLock locker(lock_);
- remove_awakable_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::IncrementCancelAllAwakablesCallCount() {
- base::AutoLock locker(lock_);
- cancel_all_awakables_call_count_++;
-}
-
-void CoreTestBase_MockHandleInfo::AllowAddAwakable(bool alllow) {
- base::AutoLock locker(lock_);
- add_awakable_allowed_ = alllow;
-}
-
-bool CoreTestBase_MockHandleInfo::IsAddAwakableAllowed() const {
- base::AutoLock locker(lock_);
- return add_awakable_allowed_;
-}
-
-void CoreTestBase_MockHandleInfo::AwakableWasAdded(Awakable* awakable) {
- base::AutoLock locker(lock_);
- added_awakables_.push_back(awakable);
-}
-
-} // namespace test
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h
deleted file mode 100644
index c2b5ee2..0000000
--- a/mojo/edk/system/core_test_base.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_CORE_TEST_BASE_H_
-#define MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "mojo/public/c/system/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-
-class Core;
-class Awakable;
-
-namespace test {
-
-class CoreTestBase_MockHandleInfo;
-
-class CoreTestBase : public testing::Test {
- public:
- typedef CoreTestBase_MockHandleInfo MockHandleInfo;
-
- CoreTestBase();
- ~CoreTestBase() override;
-
- void SetUp() override;
- void TearDown() override;
-
- protected:
- // |info| must remain alive until the returned handle is closed.
- MojoHandle CreateMockHandle(MockHandleInfo* info);
-
- Core* core() { return core_; }
-
- private:
- Core* core_;
-
- DISALLOW_COPY_AND_ASSIGN(CoreTestBase);
-};
-
-class CoreTestBase_MockHandleInfo {
- public:
- CoreTestBase_MockHandleInfo();
- ~CoreTestBase_MockHandleInfo();
-
- unsigned GetCtorCallCount() const;
- unsigned GetDtorCallCount() const;
- unsigned GetCloseCallCount() const;
- unsigned GetWriteMessageCallCount() const;
- unsigned GetReadMessageCallCount() const;
- unsigned GetWriteDataCallCount() const;
- unsigned GetBeginWriteDataCallCount() const;
- unsigned GetEndWriteDataCallCount() const;
- unsigned GetReadDataCallCount() const;
- unsigned GetBeginReadDataCallCount() const;
- unsigned GetEndReadDataCallCount() const;
- unsigned GetAddAwakableCallCount() const;
- unsigned GetRemoveAwakableCallCount() const;
- unsigned GetCancelAllAwakablesCallCount() const;
-
- size_t GetAddedAwakableSize() const;
- Awakable* GetAddedAwakableAt(unsigned i) const;
-
- // For use by |MockDispatcher|:
- void IncrementCtorCallCount();
- void IncrementDtorCallCount();
- void IncrementCloseCallCount();
- void IncrementWriteMessageCallCount();
- void IncrementReadMessageCallCount();
- void IncrementWriteDataCallCount();
- void IncrementBeginWriteDataCallCount();
- void IncrementEndWriteDataCallCount();
- void IncrementReadDataCallCount();
- void IncrementBeginReadDataCallCount();
- void IncrementEndReadDataCallCount();
- void IncrementAddAwakableCallCount();
- void IncrementRemoveAwakableCallCount();
- void IncrementCancelAllAwakablesCallCount();
-
- void AllowAddAwakable(bool alllow);
- bool IsAddAwakableAllowed() const;
- void AwakableWasAdded(Awakable*);
-
- private:
- mutable base::Lock lock_; // Protects the following members.
- unsigned ctor_call_count_;
- unsigned dtor_call_count_;
- unsigned close_call_count_;
- unsigned write_message_call_count_;
- unsigned read_message_call_count_;
- unsigned write_data_call_count_;
- unsigned begin_write_data_call_count_;
- unsigned end_write_data_call_count_;
- unsigned read_data_call_count_;
- unsigned begin_read_data_call_count_;
- unsigned end_read_data_call_count_;
- unsigned add_awakable_call_count_;
- unsigned remove_awakable_call_count_;
- unsigned cancel_all_awakables_call_count_;
-
- bool add_awakable_allowed_;
- std::vector<Awakable*> added_awakables_;
-
- DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo);
-};
-
-} // namespace test
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
deleted file mode 100644
index b789301..0000000
--- a/mojo/edk/system/core_unittest.cc
+++ /dev/null
@@ -1,1317 +0,0 @@
-// Copyright 2013 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/core.h"
-
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/bind.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "mojo/edk/system/awakable.h"
-#include "mojo/edk/system/core_test_base.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
-const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
-const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED;
-
-typedef test::CoreTestBase CoreTest;
-
-TEST_F(CoreTest, GetTimeTicksNow) {
- const MojoTimeTicks start = core()->GetTimeTicksNow();
- EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
- << "GetTimeTicksNow should return nonzero value";
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(15));
- const MojoTimeTicks finish = core()->GetTimeTicksNow();
- // Allow for some fuzz in sleep.
- EXPECT_GE((finish - start), static_cast<MojoTimeTicks>(8000))
- << "Sleeping should result in increasing time ticks";
-}
-
-TEST_F(CoreTest, Basic) {
- MockHandleInfo info;
-
- EXPECT_EQ(0u, info.GetCtorCallCount());
- MojoHandle h = CreateMockHandle(&info);
- EXPECT_EQ(1u, info.GetCtorCallCount());
- EXPECT_NE(h, MOJO_HANDLE_INVALID);
-
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-
- EXPECT_EQ(0u, info.GetReadMessageCallCount());
- uint32_t num_bytes = 0;
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->ReadMessage(h, NullUserPointer(), MakeUserPointer(&num_bytes),
- NullUserPointer(), NullUserPointer(),
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetReadMessageCallCount());
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(h, NullUserPointer(), NullUserPointer(),
- NullUserPointer(), NullUserPointer(),
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(2u, info.GetReadMessageCallCount());
-
- EXPECT_EQ(0u, info.GetWriteDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->WriteData(h, NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteDataCallCount());
-
- EXPECT_EQ(0u, info.GetBeginWriteDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->BeginWriteData(h, NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(1u, info.GetBeginWriteDataCallCount());
-
- EXPECT_EQ(0u, info.GetEndWriteDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0));
- EXPECT_EQ(1u, info.GetEndWriteDataCallCount());
-
- EXPECT_EQ(0u, info.GetReadDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->ReadData(h, NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(1u, info.GetReadDataCallCount());
-
- EXPECT_EQ(0u, info.GetBeginReadDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->BeginReadData(h, NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(1u, info.GetBeginReadDataCallCount());
-
- EXPECT_EQ(0u, info.GetEndReadDataCallCount());
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0));
- EXPECT_EQ(1u, info.GetEndReadDataCallCount());
-
- EXPECT_EQ(0u, info.GetAddAwakableCallCount());
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE,
- NullUserPointer()));
- EXPECT_EQ(1u, info.GetAddAwakableCallCount());
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer()));
- EXPECT_EQ(2u, info.GetAddAwakableCallCount());
- MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE,
- MakeUserPointer(&hss)));
- EXPECT_EQ(3u, info.GetAddAwakableCallCount());
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer()));
- EXPECT_EQ(4u, info.GetAddAwakableCallCount());
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(5u, info.GetAddAwakableCallCount());
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- EXPECT_EQ(6u, info.GetAddAwakableCallCount());
- uint32_t result_index = static_cast<uint32_t>(-1);
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- NullUserPointer()));
- EXPECT_EQ(7u, info.GetAddAwakableCallCount());
- EXPECT_EQ(0u, result_index);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- MakeUserPointer(&hss)));
- EXPECT_EQ(8u, info.GetAddAwakableCallCount());
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- result_index = static_cast<uint32_t>(-1);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(&hss)));
- EXPECT_EQ(9u, info.GetAddAwakableCallCount());
- EXPECT_EQ(0u, result_index);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- EXPECT_EQ(0u, info.GetDtorCallCount());
- EXPECT_EQ(0u, info.GetCloseCallCount());
- EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount());
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount());
- EXPECT_EQ(1u, info.GetCloseCallCount());
- EXPECT_EQ(1u, info.GetDtorCallCount());
-
- // No awakables should ever have ever been added.
- EXPECT_EQ(0u, info.GetRemoveAwakableCallCount());
-}
-
-TEST_F(CoreTest, InvalidArguments) {
- // |Close()|:
- {
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(MOJO_HANDLE_INVALID));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(10));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(1000000000));
-
- // Test a double-close.
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- EXPECT_EQ(1u, info.GetCloseCallCount());
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h));
- EXPECT_EQ(1u, info.GetCloseCallCount());
- }
-
- // |Wait()|:
- {
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer()));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer()));
-
- MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss)));
- // On invalid argument, it shouldn't modify the handle signals state.
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
- hss.satisfied_signals);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
- hss.satisfiable_signals);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss)));
- // On invalid argument, it shouldn't modify the handle signals state.
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
- hss.satisfied_signals);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
- hss.satisfiable_signals);
- }
-
- // |WaitMany()|:
- {
- MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
- MojoHandleSignals signals[2] = {~MOJO_HANDLE_SIGNAL_NONE,
- ~MOJO_HANDLE_SIGNAL_NONE};
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 0,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- // If |num_handles| is invalid, it should leave |result_index| and
- // |signals_states| alone.
- // (We use -1 internally; make sure that doesn't leak.)
- uint32_t result_index = 123;
- MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0,
- MOJO_DEADLINE_INDEFINITE,
- MakeUserPointer(&result_index),
- MakeUserPointer(&hss)));
- EXPECT_EQ(123u, result_index);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
- hss.satisfied_signals);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
- hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(MakeUserPointer(handles), NullUserPointer(), 0,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 1,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- // But if a handle is bad, then it should set |result_index| but still leave
- // |signals_states| alone.
- result_index = static_cast<uint32_t>(-1);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(
- MakeUserPointer(handles), MakeUserPointer(signals), 1,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(&hss)));
- EXPECT_EQ(0u, result_index);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
- hss.satisfied_signals);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
- hss.satisfiable_signals);
-
- MockHandleInfo info[2];
- handles[0] = CreateMockHandle(&info[0]);
-
- result_index = static_cast<uint32_t>(-1);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(
- MakeUserPointer(handles), MakeUserPointer(signals), 1,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(&hss)));
- EXPECT_EQ(0u, result_index);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- // On invalid argument, it'll leave |signals_states| alone.
- result_index = static_cast<uint32_t>(-1);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(
- MakeUserPointer(handles), MakeUserPointer(signals), 2,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(&hss)));
- EXPECT_EQ(1u, result_index);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
- hss.satisfied_signals);
- EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
- hss.satisfiable_signals);
- handles[1] = handles[0] + 1; // Invalid handle.
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
- handles[1] = CreateMockHandle(&info[1]);
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()));
-
- // TODO(vtl): Test one where we get "failed precondition" only for the
- // second handle (and the first one is valid to wait on).
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1]));
- }
-
- // |CreateMessagePipe()|: Nothing to check (apart from things that cause
- // death).
-
- // |WriteMessage()|:
- // Only check arguments checked by |Core|, namely |handle|, |handles|, and
- // |num_handles|.
- {
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(MOJO_HANDLE_INVALID, NullUserPointer(), 0,
- NullUserPointer(), 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
- MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
-
- // Huge handle count (implausibly big on some systems -- more than can be
- // stored in a 32-bit address space).
- // Note: This may return either |MOJO_RESULT_INVALID_ARGUMENT| or
- // |MOJO_RESULT_RESOURCE_EXHAUSTED|, depending on whether it's plausible or
- // not.
- EXPECT_NE(
- MOJO_RESULT_OK,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- std::numeric_limits<uint32_t>::max(),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
- // Huge handle count (plausibly big).
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- core()->WriteMessage(
- h, NullUserPointer(), 0, MakeUserPointer(handles),
- std::numeric_limits<uint32_t>::max() / sizeof(handles[0]),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
- // Invalid handle in |handles|.
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
- // Two invalid handles in |handles|.
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 2, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
- // Can't send a handle over itself.
- handles[0] = h;
- EXPECT_EQ(
- MOJO_RESULT_BUSY,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
- MockHandleInfo info2;
- MojoHandle h2 = CreateMockHandle(&info2);
-
- // This is "okay", but |MockDispatcher| doesn't implement it.
- handles[0] = h2;
- EXPECT_EQ(
- MOJO_RESULT_UNIMPLEMENTED,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-
- // One of the |handles| is still invalid.
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 2, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-
- // One of the |handles| is the same as |handle|.
- handles[1] = h;
- EXPECT_EQ(
- MOJO_RESULT_BUSY,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 2, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-
- // Can't send a handle twice in the same message.
- handles[1] = h2;
- EXPECT_EQ(
- MOJO_RESULT_BUSY,
- core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles),
- 2, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-
- // Note: Since we never successfully sent anything with it, |h2| should
- // still be valid.
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h2));
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- }
-
- // |ReadMessage()|:
- // Only check arguments checked by |Core|, namely |handle|, |handles|, and
- // |num_handles|.
- {
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadMessage(MOJO_HANDLE_INVALID, NullUserPointer(),
- NullUserPointer(), NullUserPointer(),
- NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE));
-
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
-
- // Okay.
- uint32_t handle_count = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h, NullUserPointer(), NullUserPointer(), NullUserPointer(),
- MakeUserPointer(&handle_count), MOJO_READ_MESSAGE_FLAG_NONE));
- // Checked by |Core|, shouldn't go through to the dispatcher.
- EXPECT_EQ(1u, info.GetReadMessageCallCount());
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- }
-}
-
-// These test invalid arguments that should cause death if we're being paranoid
-// about checking arguments (which we would want to do if, e.g., we were in a
-// true "kernel" situation, but we might not want to do otherwise for
-// performance reasons). Probably blatant errors like passing in null pointers
-// (for required pointer arguments) will still cause death, but perhaps not
-// predictably.
-TEST_F(CoreTest, InvalidArgumentsDeath) {
- const char kMemoryCheckFailedRegex[] = "Check failed";
-
- // |WaitMany()|:
- {
- MojoHandle handle = MOJO_HANDLE_INVALID;
- MojoHandleSignals signals = ~MOJO_HANDLE_SIGNAL_NONE;
- EXPECT_DEATH_IF_SUPPORTED(
- core()->WaitMany(NullUserPointer(), MakeUserPointer(&signals), 1,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()),
- kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(
- core()->WaitMany(MakeUserPointer(&handle), NullUserPointer(), 1,
- MOJO_DEADLINE_INDEFINITE, NullUserPointer(),
- NullUserPointer()),
- kMemoryCheckFailedRegex);
- // TODO(vtl): |result_index| and |signals_states| are optional. Test them
- // with non-null invalid pointers?
- }
-
- // |CreateMessagePipe()|:
- {
- MojoHandle h;
- EXPECT_DEATH_IF_SUPPORTED(
- core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(),
- NullUserPointer()),
- kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(
- core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h),
- NullUserPointer()),
- kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(
- core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(),
- MakeUserPointer(&h)),
- kMemoryCheckFailedRegex);
- }
-
- // |WriteMessage()|:
- // Only check arguments checked by |Core|, namely |handle|, |handles|, and
- // |num_handles|.
- {
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
-
- // Null |handles| with nonzero |num_handles|.
- EXPECT_DEATH_IF_SUPPORTED(
- core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- kMemoryCheckFailedRegex);
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- }
-
- // |ReadMessage()|:
- // Only check arguments checked by |Core|, namely |handle|, |handles|, and
- // |num_handles|.
- {
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
-
- uint32_t handle_count = 1;
- EXPECT_DEATH_IF_SUPPORTED(
- core()->ReadMessage(h, NullUserPointer(), NullUserPointer(),
- NullUserPointer(), MakeUserPointer(&handle_count),
- MOJO_READ_MESSAGE_FLAG_NONE),
- kMemoryCheckFailedRegex);
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
- }
-}
-
-// TODO(vtl): test |Wait()| and |WaitMany()| properly
-// - including |WaitMany()| with the same handle more than once (with
-// same/different signals)
-
-TEST_F(CoreTest, MessagePipe) {
- MojoHandle h[2];
- MojoHandleSignalsState hss[2];
- uint32_t result_index;
-
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h[0]),
- MakeUserPointer(&h[1])));
- // Should get two distinct, valid handles.
- EXPECT_NE(h[0], MOJO_HANDLE_INVALID);
- EXPECT_NE(h[1], MOJO_HANDLE_INVALID);
- EXPECT_NE(h[0], h[1]);
-
- // Neither should be readable.
- MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_HANDLE_SIGNAL_READABLE};
- result_index = static_cast<uint32_t>(-1);
- hss[0] = kEmptyMojoHandleSignalsState;
- hss[1] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_DEADLINE_EXCEEDED,
- core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, 0,
- MakeUserPointer(&result_index), MakeUserPointer(hss)));
- EXPECT_EQ(static_cast<uint32_t>(-1), result_index);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
-
- // Try to read anyway.
- char buffer[1] = {'a'};
- uint32_t buffer_size = 1;
- EXPECT_EQ(
- MOJO_RESULT_SHOULD_WAIT,
- core()->ReadMessage(h[0], UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), NullUserPointer(),
- NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE));
- // Check that it left its inputs alone.
- EXPECT_EQ('a', buffer[0]);
- EXPECT_EQ(1u, buffer_size);
-
- // Both should be writable.
- hss[0] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE,
- 1000000000, MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
- hss[0] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE,
- 1000000000, MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
-
- // Also check that |h[1]| is writable using |WaitMany()|.
- signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
- signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE;
- result_index = static_cast<uint32_t>(-1);
- hss[0] = kEmptyMojoHandleSignalsState;
- hss[1] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(hss)));
- EXPECT_EQ(1u, result_index);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
-
- // Write to |h[1]|.
- buffer[0] = 'b';
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1,
- NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Check that |h[0]| is now readable.
- signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
- signals[1] = MOJO_HANDLE_SIGNAL_READABLE;
- result_index = static_cast<uint32_t>(-1);
- hss[0] = kEmptyMojoHandleSignalsState;
- hss[1] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2,
- MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index),
- MakeUserPointer(hss)));
- EXPECT_EQ(0u, result_index);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
-
- // Read from |h[0]|.
- // First, get only the size.
- buffer_size = 0;
- EXPECT_EQ(
- MOJO_RESULT_RESOURCE_EXHAUSTED,
- core()->ReadMessage(h[0], NullUserPointer(),
- MakeUserPointer(&buffer_size), NullUserPointer(),
- NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(1u, buffer_size);
- // Then actually read it.
- buffer[0] = 'c';
- buffer_size = 1;
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->ReadMessage(h[0], UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), NullUserPointer(),
- NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ('b', buffer[0]);
- EXPECT_EQ(1u, buffer_size);
-
- // |h[0]| should no longer be readable.
- hss[0] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0,
- MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
-
- // Write to |h[0]|.
- buffer[0] = 'd';
- EXPECT_EQ(
- MOJO_RESULT_OK,
- core()->WriteMessage(h[0], UserPointer<const void>(buffer), 1,
- NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Close |h[0]|.
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0]));
-
- // Check that |h[1]| is no longer writable (and will never be).
- hss[0] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000,
- MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[0].satisfiable_signals);
-
- // Check that |h[1]| is still readable (for the moment).
- hss[0] = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE,
- 1000000000, MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[0].satisfiable_signals);
-
- // Discard a message from |h[1]|.
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- core()->ReadMessage(h[1], NullUserPointer(), NullUserPointer(),
- NullUserPointer(), NullUserPointer(),
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- // |h[1]| is no longer readable (and will never be).
- hss[0] = kFullMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfiable_signals);
-
- // Try writing to |h[1]|.
- buffer[0] = 'e';
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1,
- NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[1]));
-}
-
-// Tests passing a message pipe handle.
-TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
- const char kHello[] = "hello";
- const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
- const char kWorld[] = "world!!!";
- const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
- char buffer[100];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t num_bytes;
- MojoHandle handles[10];
- uint32_t num_handles;
- MojoHandleSignalsState hss;
- MojoHandle h_received;
-
- MojoHandle h_passing[2];
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateMessagePipe(NullUserPointer(),
- MakeUserPointer(&h_passing[0]),
- MakeUserPointer(&h_passing[1])));
-
- // Make sure that |h_passing[]| work properly.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, NullUserPointer(), 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(0u, num_handles);
-
- // Make sure that you can't pass either of the message pipe's handles over
- // itself.
- EXPECT_EQ(MOJO_RESULT_BUSY,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&h_passing[0]), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&h_passing[1]), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- MojoHandle h_passed[2];
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateMessagePipe(NullUserPointer(),
- MakeUserPointer(&h_passed[0]),
- MakeUserPointer(&h_passed[1])));
-
- // Make sure that |h_passed[]| work properly.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello),
- kHelloSize, NullUserPointer(), 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passed[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passed[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(0u, num_handles);
-
- // Send |h_passed[1]| from |h_passing[0]| to |h_passing[1]|.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld),
- kWorldSize, MakeUserPointer(&h_passed[1]), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kWorldSize, num_bytes);
- EXPECT_STREQ(kWorld, buffer);
- EXPECT_EQ(1u, num_handles);
- h_received = handles[0];
- EXPECT_NE(h_received, MOJO_HANDLE_INVALID);
- EXPECT_NE(h_received, h_passing[0]);
- EXPECT_NE(h_received, h_passing[1]);
- EXPECT_NE(h_received, h_passed[0]);
-
- // Note: We rely on the Mojo system not re-using handle values very often.
- EXPECT_NE(h_received, h_passed[1]);
-
- // |h_passed[1]| should no longer be valid; check that trying to close it
- // fails. See above note.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1]));
-
- // Write to |h_passed[0]|. Should receive on |h_received|.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello),
- kHelloSize, NullUserPointer(), 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_received, UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(0u, num_handles);
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passed[0]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_received));
-}
-
-TEST_F(CoreTest, DataPipe) {
- MojoHandle ph, ch; // p is for producer and c is for consumer.
- MojoHandleSignalsState hss;
-
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph),
- MakeUserPointer(&ch)));
- // Should get two distinct, valid handles.
- EXPECT_NE(ph, MOJO_HANDLE_INVALID);
- EXPECT_NE(ch, MOJO_HANDLE_INVALID);
- EXPECT_NE(ph, ch);
-
- // Producer should be never-readable, but already writable.
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Consumer should be never-writable, and not yet readable.
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_DEADLINE_EXCEEDED,
- core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Write.
- signed char elements[2] = {'A', 'B'};
- uint32_t num_bytes = 2u;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteData(ph, UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(2u, num_bytes);
-
- // Consumer should now be readable.
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Peek one character.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = 1u;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadData(
- ch, UserPointer<void>(elements), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK));
- EXPECT_EQ('A', elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Read one character.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = 1u;
- EXPECT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, UserPointer<void>(elements),
- MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ('A', elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Two-phase write.
- void* write_ptr = nullptr;
- num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->BeginWriteData(ph, MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_NONE));
- // We count on the default options providing a decent buffer size.
- ASSERT_GE(num_bytes, 3u);
-
- // Trying to do a normal write during a two-phase write should fail.
- elements[0] = 'X';
- num_bytes = 1u;
- EXPECT_EQ(MOJO_RESULT_BUSY,
- core()->WriteData(ph, UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_NONE));
-
- // Actually write the data, and complete it now.
- static_cast<char*>(write_ptr)[0] = 'C';
- static_cast<char*>(write_ptr)[1] = 'D';
- static_cast<char*>(write_ptr)[2] = 'E';
- EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u));
-
- // Query how much data we have.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_QUERY));
- EXPECT_EQ(4u, num_bytes);
-
- // Try to query with peek. Should fail.
- num_bytes = 0;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK));
- EXPECT_EQ(0u, num_bytes);
-
- // Try to discard ten characters, in all-or-none mode. Should fail.
- num_bytes = 10;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- core()->ReadData(
- ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
-
- // Try to discard two characters, in peek mode. Should fail.
- num_bytes = 2;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK));
-
- // Discard two characters.
- num_bytes = 2;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadData(
- ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
-
- // Try a two-phase read of the remaining two bytes with peek. Should fail.
- const void* read_ptr = nullptr;
- num_bytes = 2;
- ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->BeginReadData(ch, MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_PEEK));
-
- // Read the remaining two characters, in two-phase mode (all-or-none).
- num_bytes = 2;
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->BeginReadData(ch, MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
- // Note: Count on still being able to do the contiguous read here.
- ASSERT_EQ(2u, num_bytes);
-
- // Discarding right now should fail.
- num_bytes = 1;
- EXPECT_EQ(MOJO_RESULT_BUSY,
- core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_DISCARD));
-
- // Actually check our data and end the two-phase read.
- EXPECT_EQ('D', static_cast<const char*>(read_ptr)[0]);
- EXPECT_EQ('E', static_cast<const char*>(read_ptr)[1]);
- EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u));
-
- // Consumer should now be no longer readable.
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_DEADLINE_EXCEEDED,
- core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // TODO(vtl): More.
-
- // Close the producer.
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph));
-
- // The consumer should now be never-readable.
- hss = kFullMojoHandleSignalsState;
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
-}
-
-// Tests passing data pipe producer and consumer handles.
-TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
- const char kHello[] = "hello";
- const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
- const char kWorld[] = "world!!!";
- const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
- char buffer[100];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t num_bytes;
- MojoHandle handles[10];
- uint32_t num_handles;
- MojoHandleSignalsState hss;
-
- MojoHandle h_passing[2];
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateMessagePipe(NullUserPointer(),
- MakeUserPointer(&h_passing[0]),
- MakeUserPointer(&h_passing[1])));
-
- MojoHandle ph, ch;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph),
- MakeUserPointer(&ch)));
-
- // Send |ch| from |h_passing[0]| to |h_passing[1]|.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&ch), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(1u, num_handles);
- MojoHandle ch_received = handles[0];
- EXPECT_NE(ch_received, MOJO_HANDLE_INVALID);
- EXPECT_NE(ch_received, h_passing[0]);
- EXPECT_NE(ch_received, h_passing[1]);
- EXPECT_NE(ch_received, ph);
-
- // Note: We rely on the Mojo system not re-using handle values very often.
- EXPECT_NE(ch_received, ch);
-
- // |ch| should no longer be valid; check that trying to close it fails. See
- // above note.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch));
-
- // Write to |ph|. Should receive on |ch_received|.
- num_bytes = kWorldSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteData(ph, UserPointer<const void>(kWorld),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- num_bytes = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadData(ch_received, UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes),
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kWorldSize, num_bytes);
- EXPECT_STREQ(kWorld, buffer);
-
- // Now pass |ph| in the same direction.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld),
- kWorldSize, MakeUserPointer(&ph), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kWorldSize, num_bytes);
- EXPECT_STREQ(kWorld, buffer);
- EXPECT_EQ(1u, num_handles);
- MojoHandle ph_received = handles[0];
- EXPECT_NE(ph_received, MOJO_HANDLE_INVALID);
- EXPECT_NE(ph_received, h_passing[0]);
- EXPECT_NE(ph_received, h_passing[1]);
- EXPECT_NE(ph_received, ch_received);
-
- // Again, rely on the Mojo system not re-using handle values very often.
- EXPECT_NE(ph_received, ph);
-
- // |ph| should no longer be valid; check that trying to close it fails. See
- // above note.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph));
-
- // Write to |ph_received|. Should receive on |ch_received|.
- num_bytes = kHelloSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteData(ph_received, UserPointer<const void>(kHello),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- num_bytes = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadData(ch_received, UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes),
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
-
- ph = ph_received;
- ph_received = MOJO_HANDLE_INVALID;
- ch = ch_received;
- ch_received = MOJO_HANDLE_INVALID;
-
- // Make sure that |ph| can't be sent if it's in a two-phase write.
- void* write_ptr = nullptr;
- num_bytes = 0;
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->BeginWriteData(ph, MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes),
- MOJO_WRITE_DATA_FLAG_NONE));
- ASSERT_GE(num_bytes, 1u);
- EXPECT_EQ(MOJO_RESULT_BUSY,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&ph), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // But |ch| can, even if |ph| is in a two-phase write.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&ch), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- ch = MOJO_HANDLE_INVALID;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- NullUserPointer()));
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kHelloSize, num_bytes);
- EXPECT_STREQ(kHello, buffer);
- EXPECT_EQ(1u, num_handles);
- ch = handles[0];
- EXPECT_NE(ch, MOJO_HANDLE_INVALID);
-
- // Complete the two-phase write.
- static_cast<char*>(write_ptr)[0] = 'x';
- EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1));
-
- // Wait for |ch| to be readable.
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE,
- 1000000000, MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Make sure that |ch| can't be sent if it's in a two-phase read.
- const void* read_ptr = nullptr;
- num_bytes = 1;
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->BeginReadData(ch, MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes),
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
- EXPECT_EQ(MOJO_RESULT_BUSY,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&ch), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // But |ph| can, even if |ch| is in a two-phase read.
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld),
- kWorldSize, MakeUserPointer(&ph), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- ph = MOJO_HANDLE_INVALID;
- hss = kEmptyMojoHandleSignalsState;
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
- MakeUserPointer(&hss)));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- num_bytes = kBufferSize;
- num_handles = arraysize(handles);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(
- h_passing[1], UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), MakeUserPointer(handles),
- MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kWorldSize, num_bytes);
- EXPECT_STREQ(kWorld, buffer);
- EXPECT_EQ(1u, num_handles);
- ph = handles[0];
- EXPECT_NE(ph, MOJO_HANDLE_INVALID);
-
- // Complete the two-phase read.
- EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]);
- EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 1));
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1]));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph));
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
-}
-
-struct TestAsyncWaiter {
- TestAsyncWaiter() : result(MOJO_RESULT_UNKNOWN) {}
-
- void Awake(MojoResult r) { result = r; }
-
- MojoResult result;
-};
-
-TEST_F(CoreTest, AsyncWait) {
- TestAsyncWaiter waiter;
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
-
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter))));
- EXPECT_EQ(0u, info.GetAddedAwakableSize());
-
- info.AllowAddAwakable(true);
- EXPECT_EQ(MOJO_RESULT_OK,
- core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter))));
- EXPECT_EQ(1u, info.GetAddedAwakableSize());
-
- EXPECT_FALSE(info.GetAddedAwakableAt(0)->Awake(MOJO_RESULT_BUSY, 0));
- EXPECT_EQ(MOJO_RESULT_BUSY, waiter.result);
-
- EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
-}
-
-// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|.
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/data_pipe.cc b/mojo/edk/system/data_pipe.cc
deleted file mode 100644
index 2f433bd..0000000
--- a/mojo/edk/system/data_pipe.cc
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2013 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/data_pipe.h"
-
-#include <string.h>
-
-#include <algorithm>
-#include <limits>
-
-#include "base/logging.h"
-#include "mojo/edk/system/awakable_list.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/options_validation.h"
-
-namespace mojo {
-namespace system {
-
-// static
-MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() {
- MojoCreateDataPipeOptions result = {
- static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)),
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
- 1u,
- static_cast<uint32_t>(
- GetConfiguration().default_data_pipe_capacity_bytes)};
- return result;
-}
-
-// static
-MojoResult DataPipe::ValidateCreateOptions(
- UserPointer<const MojoCreateDataPipeOptions> in_options,
- MojoCreateDataPipeOptions* out_options) {
- const MojoCreateDataPipeOptionsFlags kKnownFlags =
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD;
-
- *out_options = GetDefaultCreateOptions();
- if (in_options.IsNull())
- return MOJO_RESULT_OK;
-
- UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options);
- if (!reader.is_valid())
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, 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|:
-
- if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes,
- reader))
- return MOJO_RESULT_OK;
- if (reader.options().element_num_bytes == 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
- out_options->element_num_bytes = reader.options().element_num_bytes;
-
- if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes,
- reader) ||
- reader.options().capacity_num_bytes == 0) {
- // Round the default capacity down to a multiple of the element size (but at
- // least one element).
- size_t default_data_pipe_capacity_bytes =
- GetConfiguration().default_data_pipe_capacity_bytes;
- out_options->capacity_num_bytes =
- std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes -
- (default_data_pipe_capacity_bytes %
- out_options->element_num_bytes)),
- out_options->element_num_bytes);
- return MOJO_RESULT_OK;
- }
- if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
- if (reader.options().capacity_num_bytes >
- GetConfiguration().max_data_pipe_capacity_bytes)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- out_options->capacity_num_bytes = reader.options().capacity_num_bytes;
-
- return MOJO_RESULT_OK;
-}
-
-void DataPipe::ProducerCancelAllAwakables() {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
- producer_awakable_list_->CancelAll();
-}
-
-void DataPipe::ProducerClose() {
- base::AutoLock locker(lock_);
- DCHECK(producer_open_);
- producer_open_ = false;
- DCHECK(has_local_producer_no_lock());
- producer_awakable_list_.reset();
- // Not a bug, except possibly in "user" code.
- DVLOG_IF(2, producer_in_two_phase_write_no_lock())
- << "Producer closed with active two-phase write";
- producer_two_phase_max_num_bytes_written_ = 0;
- ProducerCloseImplNoLock();
- AwakeConsumerAwakablesForStateChangeNoLock(
- ConsumerGetHandleSignalsStateImplNoLock());
-}
-
-MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- bool all_or_none) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
-
- if (producer_in_two_phase_write_no_lock())
- return MOJO_RESULT_BUSY;
- if (!consumer_open_no_lock())
- return MOJO_RESULT_FAILED_PRECONDITION;
-
- // Returning "busy" takes priority over "invalid argument".
- uint32_t max_num_bytes_to_write = num_bytes.Get();
- if (max_num_bytes_to_write % element_num_bytes_ != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (max_num_bytes_to_write == 0)
- return MOJO_RESULT_OK; // Nothing to do.
-
- uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0;
-
- HandleSignalsState old_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ProducerWriteDataImplNoLock(
- elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write);
- HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- if (!new_consumer_state.equals(old_consumer_state))
- AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
- return rv;
-}
-
-MojoResult DataPipe::ProducerBeginWriteData(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- bool all_or_none) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
-
- if (producer_in_two_phase_write_no_lock())
- return MOJO_RESULT_BUSY;
- if (!consumer_open_no_lock())
- return MOJO_RESULT_FAILED_PRECONDITION;
-
- uint32_t min_num_bytes_to_write = 0;
- if (all_or_none) {
- min_num_bytes_to_write = buffer_num_bytes.Get();
- if (min_num_bytes_to_write % element_num_bytes_ != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-
- MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes,
- min_num_bytes_to_write);
- if (rv != MOJO_RESULT_OK)
- return rv;
- // Note: No need to awake producer awakables, even though we're going from
- // writable to non-writable (since you can't wait on non-writability).
- // Similarly, though this may have discarded data (in "may discard" mode),
- // making it non-readable, there's still no need to awake consumer awakables.
- DCHECK(producer_in_two_phase_write_no_lock());
- return MOJO_RESULT_OK;
-}
-
-MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
-
- if (!producer_in_two_phase_write_no_lock())
- return MOJO_RESULT_FAILED_PRECONDITION;
- // Note: Allow successful completion of the two-phase write even if the
- // consumer has been closed.
-
- HandleSignalsState old_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- MojoResult rv;
- if (num_bytes_written > producer_two_phase_max_num_bytes_written_ ||
- num_bytes_written % element_num_bytes_ != 0) {
- rv = MOJO_RESULT_INVALID_ARGUMENT;
- producer_two_phase_max_num_bytes_written_ = 0;
- } else {
- rv = ProducerEndWriteDataImplNoLock(num_bytes_written);
- }
- // Two-phase write ended even on failure.
- DCHECK(!producer_in_two_phase_write_no_lock());
- // If we're now writable, we *became* writable (since we weren't writable
- // during the two-phase write), so awake producer awakables.
- HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE))
- AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
- HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- if (!new_consumer_state.equals(old_consumer_state))
- AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
- return rv;
-}
-
-HandleSignalsState DataPipe::ProducerGetHandleSignalsState() {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
- return ProducerGetHandleSignalsStateImplNoLock();
-}
-
-MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
-
- HandleSignalsState producer_state = ProducerGetHandleSignalsStateImplNoLock();
- if (producer_state.satisfies(signals)) {
- if (signals_state)
- *signals_state = producer_state;
- return MOJO_RESULT_ALREADY_EXISTS;
- }
- if (!producer_state.can_satisfy(signals)) {
- if (signals_state)
- *signals_state = producer_state;
- return MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- producer_awakable_list_->Add(awakable, signals, context);
- return MOJO_RESULT_OK;
-}
-
-void DataPipe::ProducerRemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_producer_no_lock());
- producer_awakable_list_->Remove(awakable);
- if (signals_state)
- *signals_state = ProducerGetHandleSignalsStateImplNoLock();
-}
-
-bool DataPipe::ProducerIsBusy() const {
- base::AutoLock locker(lock_);
- return producer_in_two_phase_write_no_lock();
-}
-
-void DataPipe::ConsumerCancelAllAwakables() {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
- consumer_awakable_list_->CancelAll();
-}
-
-void DataPipe::ConsumerClose() {
- base::AutoLock locker(lock_);
- DCHECK(consumer_open_);
- consumer_open_ = false;
- DCHECK(has_local_consumer_no_lock());
- consumer_awakable_list_.reset();
- // Not a bug, except possibly in "user" code.
- DVLOG_IF(2, consumer_in_two_phase_read_no_lock())
- << "Consumer closed with active two-phase read";
- consumer_two_phase_max_num_bytes_read_ = 0;
- ConsumerCloseImplNoLock();
- AwakeProducerAwakablesForStateChangeNoLock(
- ProducerGetHandleSignalsStateImplNoLock());
-}
-
-MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- bool all_or_none,
- bool peek) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- if (consumer_in_two_phase_read_no_lock())
- return MOJO_RESULT_BUSY;
-
- uint32_t max_num_bytes_to_read = num_bytes.Get();
- if (max_num_bytes_to_read % element_num_bytes_ != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (max_num_bytes_to_read == 0)
- return MOJO_RESULT_OK; // Nothing to do.
-
- uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0;
-
- HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ConsumerReadDataImplNoLock(
- elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek);
- HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- if (!new_producer_state.equals(old_producer_state))
- AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
- return rv;
-}
-
-MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
- bool all_or_none) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- if (consumer_in_two_phase_read_no_lock())
- return MOJO_RESULT_BUSY;
-
- uint32_t max_num_bytes_to_discard = num_bytes.Get();
- if (max_num_bytes_to_discard % element_num_bytes_ != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (max_num_bytes_to_discard == 0)
- return MOJO_RESULT_OK; // Nothing to do.
-
- uint32_t min_num_bytes_to_discard =
- all_or_none ? max_num_bytes_to_discard : 0;
-
- HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ConsumerDiscardDataImplNoLock(
- num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard);
- HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- if (!new_producer_state.equals(old_producer_state))
- AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
- return rv;
-}
-
-MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- if (consumer_in_two_phase_read_no_lock())
- return MOJO_RESULT_BUSY;
-
- // Note: Don't need to validate |*num_bytes| for query.
- return ConsumerQueryDataImplNoLock(num_bytes);
-}
-
-MojoResult DataPipe::ConsumerBeginReadData(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- bool all_or_none) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- if (consumer_in_two_phase_read_no_lock())
- return MOJO_RESULT_BUSY;
-
- uint32_t min_num_bytes_to_read = 0;
- if (all_or_none) {
- min_num_bytes_to_read = buffer_num_bytes.Get();
- if (min_num_bytes_to_read % element_num_bytes_ != 0)
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-
- MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes,
- min_num_bytes_to_read);
- if (rv != MOJO_RESULT_OK)
- return rv;
- DCHECK(consumer_in_two_phase_read_no_lock());
- return MOJO_RESULT_OK;
-}
-
-MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- if (!consumer_in_two_phase_read_no_lock())
- return MOJO_RESULT_FAILED_PRECONDITION;
-
- HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- MojoResult rv;
- if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ ||
- num_bytes_read % element_num_bytes_ != 0) {
- rv = MOJO_RESULT_INVALID_ARGUMENT;
- consumer_two_phase_max_num_bytes_read_ = 0;
- } else {
- rv = ConsumerEndReadDataImplNoLock(num_bytes_read);
- }
- // Two-phase read ended even on failure.
- DCHECK(!consumer_in_two_phase_read_no_lock());
- // If we're now readable, we *became* readable (since we weren't readable
- // during the two-phase read), so awake consumer awakables.
- HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE))
- AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
- HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- if (!new_producer_state.equals(old_producer_state))
- AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
- return rv;
-}
-
-HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
- return ConsumerGetHandleSignalsStateImplNoLock();
-}
-
-MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
-
- HandleSignalsState consumer_state = ConsumerGetHandleSignalsStateImplNoLock();
- if (consumer_state.satisfies(signals)) {
- if (signals_state)
- *signals_state = consumer_state;
- return MOJO_RESULT_ALREADY_EXISTS;
- }
- if (!consumer_state.can_satisfy(signals)) {
- if (signals_state)
- *signals_state = consumer_state;
- return MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- consumer_awakable_list_->Add(awakable, signals, context);
- return MOJO_RESULT_OK;
-}
-
-void DataPipe::ConsumerRemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state) {
- base::AutoLock locker(lock_);
- DCHECK(has_local_consumer_no_lock());
- consumer_awakable_list_->Remove(awakable);
- if (signals_state)
- *signals_state = ConsumerGetHandleSignalsStateImplNoLock();
-}
-
-bool DataPipe::ConsumerIsBusy() const {
- base::AutoLock locker(lock_);
- return consumer_in_two_phase_read_no_lock();
-}
-
-DataPipe::DataPipe(bool has_local_producer,
- bool has_local_consumer,
- const MojoCreateDataPipeOptions& validated_options)
- : may_discard_((validated_options.flags &
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)),
- element_num_bytes_(validated_options.element_num_bytes),
- capacity_num_bytes_(validated_options.capacity_num_bytes),
- producer_open_(true),
- consumer_open_(true),
- producer_awakable_list_(has_local_producer ? new AwakableList()
- : nullptr),
- consumer_awakable_list_(has_local_consumer ? new AwakableList()
- : nullptr),
- producer_two_phase_max_num_bytes_written_(0),
- consumer_two_phase_max_num_bytes_read_(0) {
- // Check that the passed in options actually are validated.
- MojoCreateDataPipeOptions unused = {0};
- DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused),
- MOJO_RESULT_OK);
-}
-
-DataPipe::~DataPipe() {
- DCHECK(!producer_open_);
- DCHECK(!consumer_open_);
- DCHECK(!producer_awakable_list_);
- DCHECK(!consumer_awakable_list_);
-}
-
-void DataPipe::AwakeProducerAwakablesForStateChangeNoLock(
- const HandleSignalsState& new_producer_state) {
- lock_.AssertAcquired();
- if (!has_local_producer_no_lock())
- return;
- producer_awakable_list_->AwakeForStateChange(new_producer_state);
-}
-
-void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock(
- const HandleSignalsState& new_consumer_state) {
- lock_.AssertAcquired();
- if (!has_local_consumer_no_lock())
- return;
- consumer_awakable_list_->AwakeForStateChange(new_consumer_state);
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/data_pipe.h b/mojo/edk/system/data_pipe.h
deleted file mode 100644
index d893465..0000000
--- a/mojo/edk/system/data_pipe.h
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_DATA_PIPE_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-class Awakable;
-class AwakableList;
-
-// |DataPipe| is a base class for secondary objects implementing data pipes,
-// similar to |MessagePipe| (see the explanatory comment in core.cc). It is
-// typically owned by the dispatcher(s) corresponding to the local endpoints.
-// Its subclasses implement the three cases: local producer and consumer, local
-// producer and remote consumer, and remote producer and local consumer. This
-// class is thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT DataPipe
- : public base::RefCountedThreadSafe<DataPipe> {
- public:
- // The default options for |MojoCreateDataPipe()|. (Real uses should obtain
- // this via |ValidateCreateOptions()| with a null |in_options|; this is
- // exposed directly for testing convenience.)
- static MojoCreateDataPipeOptions GetDefaultCreateOptions();
-
- // Validates and/or sets default options for |MojoCreateDataPipeOptions|. If
- // non-null, |in_options| must point to a struct of at least
- // |in_options->struct_size| bytes. |out_options| must point to a (current)
- // |MojoCreateDataPipeOptions| and will be entirely overwritten on success (it
- // may be partly overwritten on failure).
- static MojoResult ValidateCreateOptions(
- UserPointer<const MojoCreateDataPipeOptions> in_options,
- MojoCreateDataPipeOptions* out_options);
-
- // These are called by the producer dispatcher to implement its methods of
- // corresponding names.
- void ProducerCancelAllAwakables();
- void ProducerClose();
- MojoResult ProducerWriteData(UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- bool all_or_none);
- MojoResult ProducerBeginWriteData(UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- bool all_or_none);
- MojoResult ProducerEndWriteData(uint32_t num_bytes_written);
- HandleSignalsState ProducerGetHandleSignalsState();
- MojoResult ProducerAddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- void ProducerRemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state);
- bool ProducerIsBusy() const;
-
- // These are called by the consumer dispatcher to implement its methods of
- // corresponding names.
- void ConsumerCancelAllAwakables();
- void ConsumerClose();
- // This does not validate its arguments, except to check that |*num_bytes| is
- // a multiple of |element_num_bytes_|.
- MojoResult ConsumerReadData(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- bool all_or_none,
- bool peek);
- MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
- bool all_or_none);
- MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes);
- MojoResult ConsumerBeginReadData(UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- bool all_or_none);
- MojoResult ConsumerEndReadData(uint32_t num_bytes_read);
- HandleSignalsState ConsumerGetHandleSignalsState();
- MojoResult ConsumerAddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- void ConsumerRemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state);
- bool ConsumerIsBusy() const;
-
- protected:
- DataPipe(bool has_local_producer,
- bool has_local_consumer,
- const MojoCreateDataPipeOptions& validated_options);
-
- friend class base::RefCountedThreadSafe<DataPipe>;
- virtual ~DataPipe();
-
- virtual void ProducerCloseImplNoLock() = 0;
- // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ProducerWriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_write,
- uint32_t min_num_bytes_to_write) = 0;
- virtual MojoResult ProducerBeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_write) = 0;
- virtual MojoResult ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) = 0;
- // Note: A producer should not be writable during a two-phase write.
- virtual HandleSignalsState ProducerGetHandleSignalsStateImplNoLock()
- const = 0;
-
- virtual void ConsumerCloseImplNoLock() = 0;
- // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ConsumerReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) = 0;
- virtual MojoResult ConsumerDiscardDataImplNoLock(
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_discard,
- uint32_t min_num_bytes_to_discard) = 0;
- // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ConsumerQueryDataImplNoLock(
- UserPointer<uint32_t> num_bytes) = 0;
- virtual MojoResult ConsumerBeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_read) = 0;
- virtual MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) = 0;
- // Note: A consumer should not be writable during a two-phase read.
- virtual HandleSignalsState ConsumerGetHandleSignalsStateImplNoLock()
- const = 0;
-
- // Thread-safe and fast (they don't take the lock):
- bool may_discard() const { return may_discard_; }
- size_t element_num_bytes() const { return element_num_bytes_; }
- size_t capacity_num_bytes() const { return capacity_num_bytes_; }
-
- // Must be called under lock.
- bool producer_open_no_lock() const {
- lock_.AssertAcquired();
- return producer_open_;
- }
- bool consumer_open_no_lock() const {
- lock_.AssertAcquired();
- return consumer_open_;
- }
- uint32_t producer_two_phase_max_num_bytes_written_no_lock() const {
- lock_.AssertAcquired();
- return producer_two_phase_max_num_bytes_written_;
- }
- uint32_t consumer_two_phase_max_num_bytes_read_no_lock() const {
- lock_.AssertAcquired();
- return consumer_two_phase_max_num_bytes_read_;
- }
- void set_producer_two_phase_max_num_bytes_written_no_lock(
- uint32_t num_bytes) {
- lock_.AssertAcquired();
- producer_two_phase_max_num_bytes_written_ = num_bytes;
- }
- void set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes) {
- lock_.AssertAcquired();
- consumer_two_phase_max_num_bytes_read_ = num_bytes;
- }
- bool producer_in_two_phase_write_no_lock() const {
- lock_.AssertAcquired();
- return producer_two_phase_max_num_bytes_written_ > 0;
- }
- bool consumer_in_two_phase_read_no_lock() const {
- lock_.AssertAcquired();
- return consumer_two_phase_max_num_bytes_read_ > 0;
- }
-
- private:
- void AwakeProducerAwakablesForStateChangeNoLock(
- const HandleSignalsState& new_producer_state);
- void AwakeConsumerAwakablesForStateChangeNoLock(
- const HandleSignalsState& new_consumer_state);
-
- bool has_local_producer_no_lock() const {
- lock_.AssertAcquired();
- return !!producer_awakable_list_;
- }
- bool has_local_consumer_no_lock() const {
- lock_.AssertAcquired();
- return !!consumer_awakable_list_;
- }
-
- const bool may_discard_;
- const size_t element_num_bytes_;
- const size_t capacity_num_bytes_;
-
- mutable base::Lock lock_; // Protects the following members.
- // *Known* state of producer or consumer.
- bool producer_open_;
- bool consumer_open_;
- // Non-null only if the producer or consumer, respectively, is local.
- scoped_ptr<AwakableList> producer_awakable_list_;
- scoped_ptr<AwakableList> consumer_awakable_list_;
- // These are nonzero if and only if a two-phase write/read is in progress.
- uint32_t producer_two_phase_max_num_bytes_written_;
- uint32_t consumer_two_phase_max_num_bytes_read_;
-
- DISALLOW_COPY_AND_ASSIGN(DataPipe);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_H_
diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc
deleted file mode 100644
index 21127c6..0000000
--- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2013 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/data_pipe_consumer_dispatcher.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/memory.h"
-
-namespace mojo {
-namespace system {
-
-DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() {
-}
-
-void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) {
- DCHECK(data_pipe);
- data_pipe_ = data_pipe;
-}
-
-Dispatcher::Type DataPipeConsumerDispatcher::GetType() const {
- return kTypeDataPipeConsumer;
-}
-
-DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() {
- // |Close()|/|CloseImplNoLock()| should have taken care of the pipe.
- DCHECK(!data_pipe_);
-}
-
-void DataPipeConsumerDispatcher::CancelAllAwakablesNoLock() {
- lock().AssertAcquired();
- data_pipe_->ConsumerCancelAllAwakables();
-}
-
-void DataPipeConsumerDispatcher::CloseImplNoLock() {
- lock().AssertAcquired();
- data_pipe_->ConsumerClose();
- data_pipe_ = nullptr;
-}
-
-scoped_refptr<Dispatcher>
-DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
- lock().AssertAcquired();
-
- scoped_refptr<DataPipeConsumerDispatcher> rv =
- new DataPipeConsumerDispatcher();
- rv->Init(data_pipe_);
- data_pipe_ = nullptr;
- return scoped_refptr<Dispatcher>(rv.get());
-}
-
-MojoResult DataPipeConsumerDispatcher::ReadDataImplNoLock(
- UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags) {
- lock().AssertAcquired();
-
- if ((flags & MOJO_READ_DATA_FLAG_DISCARD)) {
- // These flags are mutally exclusive.
- if ((flags & MOJO_READ_DATA_FLAG_QUERY) ||
- (flags & MOJO_READ_DATA_FLAG_PEEK))
- return MOJO_RESULT_INVALID_ARGUMENT;
- DVLOG_IF(2, !elements.IsNull())
- << "Discard mode: ignoring non-null |elements|";
- return data_pipe_->ConsumerDiscardData(
- num_bytes, (flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE));
- }
-
- if ((flags & MOJO_READ_DATA_FLAG_QUERY)) {
- if ((flags & MOJO_READ_DATA_FLAG_PEEK))
- return MOJO_RESULT_INVALID_ARGUMENT;
- DCHECK(!(flags & MOJO_READ_DATA_FLAG_DISCARD)); // Handled above.
- DVLOG_IF(2, !elements.IsNull())
- << "Query mode: ignoring non-null |elements|";
- return data_pipe_->ConsumerQueryData(num_bytes);
- }
-
- return data_pipe_->ConsumerReadData(
- elements, num_bytes, !!(flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE),
- !!(flags & MOJO_READ_DATA_FLAG_PEEK));
-}
-
-MojoResult DataPipeConsumerDispatcher::BeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags) {
- lock().AssertAcquired();
-
- // These flags may not be used in two-phase mode.
- if ((flags & MOJO_READ_DATA_FLAG_DISCARD) ||
- (flags & MOJO_READ_DATA_FLAG_QUERY) || (flags & MOJO_READ_DATA_FLAG_PEEK))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return data_pipe_->ConsumerBeginReadData(
- buffer, buffer_num_bytes, (flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE));
-}
-
-MojoResult DataPipeConsumerDispatcher::EndReadDataImplNoLock(
- uint32_t num_bytes_read) {
- lock().AssertAcquired();
-
- return data_pipe_->ConsumerEndReadData(num_bytes_read);
-}
-
-HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsStateImplNoLock()
- const {
- lock().AssertAcquired();
- return data_pipe_->ConsumerGetHandleSignalsState();
-}
-
-MojoResult DataPipeConsumerDispatcher::AddAwakableImplNoLock(
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- return data_pipe_->ConsumerAddAwakable(awakable, signals, context,
- signals_state);
-}
-
-void DataPipeConsumerDispatcher::RemoveAwakableImplNoLock(
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- data_pipe_->ConsumerRemoveAwakable(awakable, signals_state);
-}
-
-bool DataPipeConsumerDispatcher::IsBusyNoLock() const {
- lock().AssertAcquired();
- return data_pipe_->ConsumerIsBusy();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h
deleted file mode 100644
index 10a3d94..0000000
--- a/mojo/edk/system/data_pipe_consumer_dispatcher.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class DataPipe;
-
-// This is the |Dispatcher| implementation for the consumer handle for data
-// pipes (created by the Mojo primitive |MojoCreateDataPipe()|). This class is
-// thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher : public Dispatcher {
- public:
- DataPipeConsumerDispatcher();
-
- // Must be called before any other methods.
- void Init(scoped_refptr<DataPipe> data_pipe);
-
- // |Dispatcher| public methods:
- Type GetType() const override;
-
- private:
- ~DataPipeConsumerDispatcher() override;
-
- // |Dispatcher| protected methods:
- void CancelAllAwakablesNoLock() override;
- void CloseImplNoLock() override;
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
- MojoResult ReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags) override;
- MojoResult BeginReadDataImplNoLock(UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags) override;
- MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read) override;
- HandleSignalsState GetHandleSignalsStateImplNoLock() const override;
- MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) override;
- void RemoveAwakableImplNoLock(Awakable* awakable,
- HandleSignalsState* signals_state) override;
- bool IsBusyNoLock() const override;
-
- // Protected by |lock()|:
- scoped_refptr<DataPipe> data_pipe_; // This will be null if closed.
-
- DISALLOW_COPY_AND_ASSIGN(DataPipeConsumerDispatcher);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.cc b/mojo/edk/system/data_pipe_producer_dispatcher.cc
deleted file mode 100644
index 0531126..0000000
--- a/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2013 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/data_pipe_producer_dispatcher.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/memory.h"
-
-namespace mojo {
-namespace system {
-
-DataPipeProducerDispatcher::DataPipeProducerDispatcher() {
-}
-
-void DataPipeProducerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) {
- DCHECK(data_pipe);
- data_pipe_ = data_pipe;
-}
-
-Dispatcher::Type DataPipeProducerDispatcher::GetType() const {
- return kTypeDataPipeProducer;
-}
-
-DataPipeProducerDispatcher::~DataPipeProducerDispatcher() {
- // |Close()|/|CloseImplNoLock()| should have taken care of the pipe.
- DCHECK(!data_pipe_);
-}
-
-void DataPipeProducerDispatcher::CancelAllAwakablesNoLock() {
- lock().AssertAcquired();
- data_pipe_->ProducerCancelAllAwakables();
-}
-
-void DataPipeProducerDispatcher::CloseImplNoLock() {
- lock().AssertAcquired();
- data_pipe_->ProducerClose();
- data_pipe_ = nullptr;
-}
-
-scoped_refptr<Dispatcher>
-DataPipeProducerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
- lock().AssertAcquired();
-
- scoped_refptr<DataPipeProducerDispatcher> rv =
- new DataPipeProducerDispatcher();
- rv->Init(data_pipe_);
- data_pipe_ = nullptr;
- return scoped_refptr<Dispatcher>(rv.get());
-}
-
-MojoResult DataPipeProducerDispatcher::WriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags) {
- lock().AssertAcquired();
- return data_pipe_->ProducerWriteData(
- elements, num_bytes, (flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
-}
-
-MojoResult DataPipeProducerDispatcher::BeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags) {
- lock().AssertAcquired();
-
- return data_pipe_->ProducerBeginWriteData(
- buffer, buffer_num_bytes, (flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
-}
-
-MojoResult DataPipeProducerDispatcher::EndWriteDataImplNoLock(
- uint32_t num_bytes_written) {
- lock().AssertAcquired();
-
- return data_pipe_->ProducerEndWriteData(num_bytes_written);
-}
-
-HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsStateImplNoLock()
- const {
- lock().AssertAcquired();
- return data_pipe_->ProducerGetHandleSignalsState();
-}
-
-MojoResult DataPipeProducerDispatcher::AddAwakableImplNoLock(
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- return data_pipe_->ProducerAddAwakable(awakable, signals, context,
- signals_state);
-}
-
-void DataPipeProducerDispatcher::RemoveAwakableImplNoLock(
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- data_pipe_->ProducerRemoveAwakable(awakable, signals_state);
-}
-
-bool DataPipeProducerDispatcher::IsBusyNoLock() const {
- lock().AssertAcquired();
- return data_pipe_->ProducerIsBusy();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h
deleted file mode 100644
index 39c070c..0000000
--- a/mojo/edk/system/data_pipe_producer_dispatcher.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class DataPipe;
-
-// This is the |Dispatcher| implementation for the producer handle for data
-// pipes (created by the Mojo primitive |MojoCreateDataPipe()|). This class is
-// thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher : public Dispatcher {
- public:
- DataPipeProducerDispatcher();
-
- // Must be called before any other methods.
- void Init(scoped_refptr<DataPipe> data_pipe);
-
- // |Dispatcher| public methods:
- Type GetType() const override;
-
- private:
- ~DataPipeProducerDispatcher() override;
-
- // |Dispatcher| protected methods:
- void CancelAllAwakablesNoLock() override;
- void CloseImplNoLock() override;
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
- MojoResult WriteDataImplNoLock(UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags) override;
- MojoResult BeginWriteDataImplNoLock(UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags) override;
- MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written) override;
- HandleSignalsState GetHandleSignalsStateImplNoLock() const override;
- MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) override;
- void RemoveAwakableImplNoLock(Awakable* awakable,
- HandleSignalsState* signals_state) override;
- bool IsBusyNoLock() const override;
-
- // Protected by |lock()|:
- scoped_refptr<DataPipe> data_pipe_; // This will be null if closed.
-
- DISALLOW_COPY_AND_ASSIGN(DataPipeProducerDispatcher);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
diff --git a/mojo/edk/system/data_pipe_unittest.cc b/mojo/edk/system/data_pipe_unittest.cc
deleted file mode 100644
index ad02222..0000000
--- a/mojo/edk/system/data_pipe_unittest.cc
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2013 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/data_pipe.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "mojo/edk/system/configuration.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const uint32_t kSizeOfCreateOptions =
- static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions));
-
-// Does a cursory sanity check of |validated_options|. Calls
-// |ValidateCreateOptions()| on already-validated options. The validated options
-// should be valid, and the revalidated copy should be the same.
-void RevalidateCreateOptions(
- const MojoCreateDataPipeOptions& validated_options) {
- EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size);
- // Nothing to check for flags.
- EXPECT_GT(validated_options.element_num_bytes, 0u);
- EXPECT_GT(validated_options.capacity_num_bytes, 0u);
- EXPECT_EQ(0u, validated_options.capacity_num_bytes %
- validated_options.element_num_bytes);
-
- MojoCreateDataPipeOptions revalidated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&validated_options),
- &revalidated_options));
- EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
- EXPECT_EQ(validated_options.element_num_bytes,
- revalidated_options.element_num_bytes);
- EXPECT_EQ(validated_options.capacity_num_bytes,
- revalidated_options.capacity_num_bytes);
- EXPECT_EQ(validated_options.flags, revalidated_options.flags);
-}
-
-// Checks that a default-computed capacity is correct. (Does not duplicate the
-// checks done by |RevalidateCreateOptions()|.)
-void CheckDefaultCapacity(const MojoCreateDataPipeOptions& validated_options) {
- EXPECT_LE(validated_options.capacity_num_bytes,
- GetConfiguration().default_data_pipe_capacity_bytes);
- EXPECT_GT(validated_options.capacity_num_bytes +
- validated_options.element_num_bytes,
- GetConfiguration().default_data_pipe_capacity_bytes);
-}
-
-// Tests valid inputs to |ValidateCreateOptions()|.
-TEST(DataPipeTest, ValidateCreateOptionsValid) {
- // Default options.
- {
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- NullUserPointer(), &validated_options));
- RevalidateCreateOptions(validated_options);
- CheckDefaultCapacity(validated_options);
- }
-
- // Size member, but nothing beyond.
- {
- MojoCreateDataPipeOptions options = {
- offsetof(MojoCreateDataPipeOptions, flags) // |struct_size|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- RevalidateCreateOptions(validated_options);
- CheckDefaultCapacity(validated_options);
- }
-
- // Different flags.
- MojoCreateDataPipeOptionsFlags flags_values[] = {
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD};
- for (size_t i = 0; i < arraysize(flags_values); i++) {
- const MojoCreateDataPipeOptionsFlags flags = flags_values[i];
-
- // Flags member, but nothing beyond.
- {
- MojoCreateDataPipeOptions options = {
- // |struct_size|.
- offsetof(MojoCreateDataPipeOptions, element_num_bytes),
- flags // |flags|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- CheckDefaultCapacity(validated_options);
- }
-
- // Different capacities (size 1).
- for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags, // |flags|.
- 1, // |element_num_bytes|.
- capacity // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << capacity;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes, validated_options.element_num_bytes);
- EXPECT_EQ(options.capacity_num_bytes,
- validated_options.capacity_num_bytes);
- }
-
- // Small sizes.
- for (uint32_t size = 1; size < 100; size++) {
- // Different capacities.
- for (uint32_t elements = 1; elements <= 1000 * 1000; elements *= 10) {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags, // |flags|.
- size, // |element_num_bytes|.
- size * elements // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size << ", " << elements;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- EXPECT_EQ(options.capacity_num_bytes,
- validated_options.capacity_num_bytes);
- }
-
- // Default capacity.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags, // |flags|.
- size, // |element_num_bytes|.
- 0 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- CheckDefaultCapacity(validated_options);
- }
-
- // No capacity field.
- {
- MojoCreateDataPipeOptions options = {
- // |struct_size|.
- offsetof(MojoCreateDataPipeOptions, capacity_num_bytes),
- flags, // |flags|.
- size // |element_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- CheckDefaultCapacity(validated_options);
- }
- }
-
- // Larger sizes.
- for (uint32_t size = 100; size <= 100 * 1000; size *= 10) {
- // Capacity of 1000 elements.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags, // |flags|.
- size, // |element_num_bytes|.
- 1000 * size // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- EXPECT_EQ(options.capacity_num_bytes,
- validated_options.capacity_num_bytes);
- }
-
- // Default capacity.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags, // |flags|.
- size, // |element_num_bytes|.
- 0 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- CheckDefaultCapacity(validated_options);
- }
-
- // No capacity field.
- {
- MojoCreateDataPipeOptions options = {
- // |struct_size|.
- offsetof(MojoCreateDataPipeOptions, capacity_num_bytes),
- flags, // |flags|.
- size // |element_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options))
- << size;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- EXPECT_EQ(options.element_num_bytes,
- validated_options.element_num_bytes);
- CheckDefaultCapacity(validated_options);
- }
- }
- }
-}
-
-TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
- // Invalid |struct_size|.
- {
- MojoCreateDataPipeOptions options = {
- 1, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1, // |element_num_bytes|.
- 0 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
-
- // Unknown |flags|.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- ~0u, // |flags|.
- 1, // |element_num_bytes|.
- 0 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_UNIMPLEMENTED,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
-
- // Invalid |element_num_bytes|.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 0, // |element_num_bytes|.
- 1000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
- // |element_num_bytes| too big.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- std::numeric_limits<uint32_t>::max(), // |element_num_bytes|.
- std::numeric_limits<uint32_t>::max() // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- std::numeric_limits<uint32_t>::max() - 1000, // |element_num_bytes|.
- std::numeric_limits<uint32_t>::max() - 1000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
-
- // Invalid |capacity_num_bytes|.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 2, // |element_num_bytes|.
- 1 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 2, // |element_num_bytes|.
- 111 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 5, // |element_num_bytes|.
- 104 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
- // |capacity_num_bytes| too big.
- {
- MojoCreateDataPipeOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 8, // |element_num_bytes|.
- 0xffff0000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions unused;
- EXPECT_EQ(
- MOJO_RESULT_RESOURCE_EXHAUSTED,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
- }
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc
deleted file mode 100644
index e2f2b87..0000000
--- a/mojo/edk/system/dispatcher.cc
+++ /dev/null
@@ -1,492 +0,0 @@
-// Copyright 2013 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/dispatcher.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-
-namespace mojo {
-namespace system {
-
-namespace test {
-
-// TODO(vtl): Maybe this should be defined in a test-only file instead.
-DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
- return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
-}
-
-} // namespace test
-
-// Dispatcher ------------------------------------------------------------------
-
-// static
-DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
- Dispatcher* dispatcher) {
- DCHECK(dispatcher);
-
- if (!dispatcher->lock_.Try())
- return DispatcherTransport();
-
- // We shouldn't race with things that close dispatchers, since closing can
- // only take place either under |handle_table_lock_| or when the handle is
- // marked as busy.
- DCHECK(!dispatcher->is_closed_);
-
- return DispatcherTransport(dispatcher);
-}
-
-// static
-void Dispatcher::TransportDataAccess::StartSerialize(
- Dispatcher* dispatcher,
- Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) {
- DCHECK(dispatcher);
- dispatcher->StartSerialize(channel, max_size, max_platform_handles);
-}
-
-// static
-bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
- Dispatcher* dispatcher,
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) {
- DCHECK(dispatcher);
- return dispatcher->EndSerializeAndClose(channel, destination, actual_size,
- platform_handles);
-}
-
-// static
-scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
- Channel* channel,
- int32_t type,
- const void* source,
- size_t size,
- embedder::PlatformHandleVector* platform_handles) {
- switch (static_cast<int32_t>(type)) {
- case kTypeUnknown:
- DVLOG(2) << "Deserializing invalid handle";
- return nullptr;
- case kTypeMessagePipe:
- return scoped_refptr<Dispatcher>(
- MessagePipeDispatcher::Deserialize(channel, source, size));
- case kTypeDataPipeProducer:
- case kTypeDataPipeConsumer:
- // TODO(vtl): Implement.
- LOG(WARNING) << "Deserialization of dispatcher type " << type
- << " not supported";
- return nullptr;
- case kTypeSharedBuffer:
- return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize(
- channel, source, size, platform_handles));
- case kTypePlatformHandle:
- return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize(
- channel, source, size, platform_handles));
- }
- LOG(WARNING) << "Unknown dispatcher type " << type;
- return nullptr;
-}
-
-MojoResult Dispatcher::Close() {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- CloseNoLock();
- return MOJO_RESULT_OK;
-}
-
-MojoResult Dispatcher::WriteMessage(
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags) {
- DCHECK(!transports ||
- (transports->size() > 0 &&
- transports->size() < GetConfiguration().max_message_num_handles));
-
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
-}
-
-MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) {
- DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
- (dispatchers && dispatchers->empty()));
-
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers,
- flags);
-}
-
-MojoResult Dispatcher::WriteData(UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return WriteDataImplNoLock(elements, num_bytes, flags);
-}
-
-MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
-}
-
-MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return EndWriteDataImplNoLock(num_bytes_written);
-}
-
-MojoResult Dispatcher::ReadData(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return ReadDataImplNoLock(elements, num_bytes, flags);
-}
-
-MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
-}
-
-MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return EndReadDataImplNoLock(num_bytes_read);
-}
-
-MojoResult Dispatcher::DuplicateBufferHandle(
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- scoped_refptr<Dispatcher>* new_dispatcher) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
-}
-
-MojoResult Dispatcher::MapBuffer(
- uint64_t offset,
- uint64_t num_bytes,
- MojoMapBufferFlags flags,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
-}
-
-HandleSignalsState Dispatcher::GetHandleSignalsState() const {
- base::AutoLock locker(lock_);
- if (is_closed_)
- return HandleSignalsState();
-
- return GetHandleSignalsStateImplNoLock();
-}
-
-MojoResult Dispatcher::AddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- base::AutoLock locker(lock_);
- if (is_closed_) {
- if (signals_state)
- *signals_state = HandleSignalsState();
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-
- return AddAwakableImplNoLock(awakable, signals, context, signals_state);
-}
-
-void Dispatcher::RemoveAwakable(Awakable* awakable,
- HandleSignalsState* handle_signals_state) {
- base::AutoLock locker(lock_);
- if (is_closed_) {
- if (handle_signals_state)
- *handle_signals_state = HandleSignalsState();
- return;
- }
-
- RemoveAwakableImplNoLock(awakable, handle_signals_state);
-}
-
-Dispatcher::Dispatcher() : is_closed_(false) {
-}
-
-Dispatcher::~Dispatcher() {
- // Make sure that |Close()| was called.
- DCHECK(is_closed_);
-}
-
-void Dispatcher::CancelAllAwakablesNoLock() {
- lock_.AssertAcquired();
- DCHECK(is_closed_);
- // By default, waiting isn't supported. Only dispatchers that can be waited on
- // will do something nontrivial.
-}
-
-void Dispatcher::CloseImplNoLock() {
- lock_.AssertAcquired();
- DCHECK(is_closed_);
- // This may not need to do anything. Dispatchers should override this to do
- // any actual close-time cleanup necessary.
-}
-
-MojoResult Dispatcher::WriteMessageImplNoLock(
- UserPointer<const void> /*bytes*/,
- uint32_t /*num_bytes*/,
- std::vector<DispatcherTransport>* /*transports*/,
- MojoWriteMessageFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for message pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::ReadMessageImplNoLock(
- UserPointer<void> /*bytes*/,
- UserPointer<uint32_t> /*num_bytes*/,
- DispatcherVector* /*dispatchers*/,
- uint32_t* /*num_dispatchers*/,
- MojoReadMessageFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for message pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/,
- UserPointer<uint32_t> /*num_bytes*/,
- MojoWriteDataFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::BeginWriteDataImplNoLock(
- UserPointer<void*> /*buffer*/,
- UserPointer<uint32_t> /*buffer_num_bytes*/,
- MojoWriteDataFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/,
- UserPointer<uint32_t> /*num_bytes*/,
- MojoReadDataFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::BeginReadDataImplNoLock(
- UserPointer<const void*> /*buffer*/,
- UserPointer<uint32_t> /*buffer_num_bytes*/,
- MojoReadDataFlags /*flags*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for data pipe dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
- UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
- scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for buffer dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::MapBufferImplNoLock(
- uint64_t /*offset*/,
- uint64_t /*num_bytes*/,
- MojoMapBufferFlags /*flags*/,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, not supported. Only needed for buffer dispatchers.
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, waiting isn't supported. Only dispatchers that can be waited on
- // will do something nontrivial.
- return HandleSignalsState();
-}
-
-MojoResult Dispatcher::AddAwakableImplNoLock(
- Awakable* /*awakable*/,
- MojoHandleSignals /*signals*/,
- uint32_t /*context*/,
- HandleSignalsState* signals_state) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, waiting isn't supported. Only dispatchers that can be waited on
- // will do something nontrivial.
- if (signals_state)
- *signals_state = HandleSignalsState();
- return MOJO_RESULT_FAILED_PRECONDITION;
-}
-
-void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/,
- HandleSignalsState* signals_state) {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // By default, waiting isn't supported. Only dispatchers that can be waited on
- // will do something nontrivial.
- if (signals_state)
- *signals_state = HandleSignalsState();
-}
-
-void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
- size_t* max_size,
- size_t* max_platform_handles) {
- DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
- DCHECK(!is_closed_);
- *max_size = 0;
- *max_platform_handles = 0;
-}
-
-bool Dispatcher::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(is_closed_);
- // By default, serializing isn't supported, so just close.
- CloseImplNoLock();
- return false;
-}
-
-bool Dispatcher::IsBusyNoLock() const {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
- // Most dispatchers support only "atomic" operations, so they are never busy
- // (in this sense).
- return false;
-}
-
-void Dispatcher::CloseNoLock() {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
-
- is_closed_ = true;
- CancelAllAwakablesNoLock();
- CloseImplNoLock();
-}
-
-scoped_refptr<Dispatcher>
-Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
- lock_.AssertAcquired();
- DCHECK(!is_closed_);
-
- is_closed_ = true;
- CancelAllAwakablesNoLock();
- return CreateEquivalentDispatcherAndCloseImplNoLock();
-}
-
-void Dispatcher::StartSerialize(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) {
- DCHECK(channel);
- DCHECK(max_size);
- DCHECK(max_platform_handles);
- DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
- DCHECK(!is_closed_);
- StartSerializeImplNoLock(channel, max_size, max_platform_handles);
-}
-
-bool Dispatcher::EndSerializeAndClose(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) {
- DCHECK(channel);
- DCHECK(actual_size);
- DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
- DCHECK(!is_closed_);
-
- // Like other |...Close()| methods, we mark ourselves as closed before calling
- // the impl. But there's no need to cancel waiters: we shouldn't have any (and
- // shouldn't be in |Core|'s handle table.
- is_closed_ = true;
-
-#if !defined(NDEBUG)
- // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
- // isn't actually needed, but we need to satisfy assertions (which we don't
- // want to remove or weaken).
- base::AutoLock locker(lock_);
-#endif
-
- return EndSerializeAndCloseImplNoLock(channel, destination, actual_size,
- platform_handles);
-}
-
-// DispatcherTransport ---------------------------------------------------------
-
-void DispatcherTransport::End() {
- DCHECK(dispatcher_);
- dispatcher_->lock_.Release();
- dispatcher_ = nullptr;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h
deleted file mode 100644
index c069269..0000000
--- a/mojo/edk/system/dispatcher.h
+++ /dev/null
@@ -1,405 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DISPATCHER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/buffer.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/message_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformSharedBufferMapping;
-}
-
-namespace system {
-
-class Channel;
-class Core;
-class Dispatcher;
-class DispatcherTransport;
-class HandleTable;
-class LocalMessagePipeEndpoint;
-class ProxyMessagePipeEndpoint;
-class TransportData;
-class Awakable;
-
-typedef std::vector<scoped_refptr<Dispatcher>> DispatcherVector;
-
-namespace test {
-
-// Test helper. We need to declare it here so we can friend it.
-MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport
-DispatcherTryStartTransport(Dispatcher* dispatcher);
-
-} // namespace test
-
-// A |Dispatcher| implements Mojo primitives that are "attached" to a particular
-// handle. This includes most (all?) primitives except for |MojoWait...()|. This
-// object is thread-safe, with its state being protected by a single lock
-// |lock_|, which is also made available to implementation subclasses (via the
-// |lock()| method).
-class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
- : public base::RefCountedThreadSafe<Dispatcher> {
- public:
- enum Type {
- kTypeUnknown = 0,
- kTypeMessagePipe,
- kTypeDataPipeProducer,
- kTypeDataPipeConsumer,
- kTypeSharedBuffer,
-
- // "Private" types (not exposed via the public interface):
- kTypePlatformHandle = -1
- };
- virtual Type GetType() const = 0;
-
- // These methods implement the various primitives named |Mojo...()|. These
- // take |lock_| and handle races with |Close()|. Then they call out to
- // subclasses' |...ImplNoLock()| methods (still under |lock_|), which actually
- // implement the primitives.
- // NOTE(vtl): This puts a big lock around each dispatcher (i.e., handle), and
- // prevents the various |...ImplNoLock()|s from releasing the lock as soon as
- // possible. If this becomes an issue, we can rethink this.
- MojoResult Close();
-
- // |transports| may be non-null if and only if there are handles to be
- // written; not that |this| must not be in |transports|. On success, all the
- // dispatchers in |transports| must have been moved to a closed state; on
- // failure, they should remain in their original state.
- MojoResult WriteMessage(UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags);
- // |dispatchers| must be non-null but empty, if |num_dispatchers| is non-null
- // and nonzero. On success, it will be set to the dispatchers to be received
- // (and assigned handles) as part of the message.
- MojoResult ReadMessage(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags);
- MojoResult WriteData(UserPointer<const void> elements,
- UserPointer<uint32_t> elements_num_bytes,
- MojoWriteDataFlags flags);
- MojoResult BeginWriteData(UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags);
- MojoResult EndWriteData(uint32_t num_bytes_written);
- MojoResult ReadData(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags);
- MojoResult BeginReadData(UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags);
- MojoResult EndReadData(uint32_t num_bytes_read);
- // |options| may be null. |new_dispatcher| must not be null, but
- // |*new_dispatcher| should be null (and will contain the dispatcher for the
- // new handle on success).
- MojoResult DuplicateBufferHandle(
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- scoped_refptr<Dispatcher>* new_dispatcher);
- MojoResult MapBuffer(
- uint64_t offset,
- uint64_t num_bytes,
- MojoMapBufferFlags flags,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping);
-
- // Gets the current handle signals state. (The default implementation simply
- // returns a default-constructed |HandleSignalsState|, i.e., no signals
- // satisfied or satisfiable.) Note: The state is subject to change from other
- // threads.
- HandleSignalsState GetHandleSignalsState() const;
-
- // Adds an awakable to this dispatcher, which will be woken up when this
- // object changes state to satisfy |signals| with context |context|. It will
- // also be woken up when it becomes impossible for the object to ever satisfy
- // |signals| with a suitable error status.
- //
- // If |signals_state| is non-null, on *failure* |*signals_state| will be set
- // to the current handle signals state (on success, it is left untouched).
- //
- // Returns:
- // - |MOJO_RESULT_OK| if the awakable was added;
- // - |MOJO_RESULT_ALREADY_EXISTS| if |signals| is already satisfied;
- // - |MOJO_RESULT_INVALID_ARGUMENT| if the dispatcher has been closed; and
- // - |MOJO_RESULT_FAILED_PRECONDITION| if it is not (or no longer) possible
- // that |signals| will ever be satisfied.
- MojoResult AddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- // Removes an awakable from this dispatcher. (It is valid to call this
- // multiple times for the same |awakable| on the same object, so long as
- // |AddAwakable()| was called at most once.) If |signals_state| is non-null,
- // |*signals_state| will be set to the current handle signals state.
- void RemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state);
-
- // A dispatcher must be put into a special state in order to be sent across a
- // message pipe. Outside of tests, only |HandleTableAccess| is allowed to do
- // this, since there are requirements on the handle table (see below).
- //
- // In this special state, only a restricted set of operations is allowed.
- // These are the ones available as |DispatcherTransport| methods. Other
- // |Dispatcher| methods must not be called until |DispatcherTransport::End()|
- // has been called.
- class HandleTableAccess {
- private:
- friend class Core;
- friend class HandleTable;
- // Tests also need this, to avoid needing |Core|.
- friend DispatcherTransport test::DispatcherTryStartTransport(Dispatcher*);
-
- // This must be called under the handle table lock and only if the handle
- // table entry is not marked busy. The caller must maintain a reference to
- // |dispatcher| until |DispatcherTransport::End()| is called.
- static DispatcherTransport TryStartTransport(Dispatcher* dispatcher);
- };
-
- // A |TransportData| may serialize dispatchers that are given to it (and which
- // were previously attached to the |MessageInTransit| that is creating it) to
- // a given |Channel| and then (probably in a different process) deserialize.
- // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these
- // dispatchers, so there are no locking issues. (There's no lock ordering
- // issue, and in fact no need to take dispatcher locks at all.)
- // TODO(vtl): Consider making another wrapper similar to |DispatcherTransport|
- // (but with an owning, unique reference), and having
- // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and
- // |MessageInTransit|, etc. only holding on to such wrappers).
- class TransportDataAccess {
- private:
- friend class TransportData;
-
- // Serialization API. These functions may only be called on such
- // dispatchers. (|channel| is the |Channel| to which the dispatcher is to be
- // serialized.) See the |Dispatcher| methods of the same names for more
- // details.
- static void StartSerialize(Dispatcher* dispatcher,
- Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles);
- static bool EndSerializeAndClose(
- Dispatcher* dispatcher,
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles);
-
- // Deserialization API.
- // Note: This "clears" (i.e., reset to the invalid handle) any platform
- // handles that it takes ownership of.
- static scoped_refptr<Dispatcher> Deserialize(
- Channel* channel,
- int32_t type,
- const void* source,
- size_t size,
- embedder::PlatformHandleVector* platform_handles);
- };
-
- protected:
- friend class base::RefCountedThreadSafe<Dispatcher>;
-
- Dispatcher();
- virtual ~Dispatcher();
-
- // These are to be overridden by subclasses (if necessary). They are called
- // exactly once -- first |CancelAllAwakablesNoLock()|, then
- // |CloseImplNoLock()|,
- // when the dispatcher is being closed. They are called under |lock_|.
- virtual void CancelAllAwakablesNoLock();
- virtual void CloseImplNoLock();
- virtual scoped_refptr<Dispatcher>
- CreateEquivalentDispatcherAndCloseImplNoLock() = 0;
-
- // These are to be overridden by subclasses (if necessary). They are never
- // called after the dispatcher has been closed. They are called under |lock_|.
- // See the descriptions of the methods without the "ImplNoLock" for more
- // information.
- virtual MojoResult WriteMessageImplNoLock(
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags);
- virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags);
- virtual MojoResult WriteDataImplNoLock(UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoWriteDataFlags flags);
- virtual MojoResult BeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoWriteDataFlags flags);
- virtual MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written);
- virtual MojoResult ReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- MojoReadDataFlags flags);
- virtual MojoResult BeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- MojoReadDataFlags flags);
- virtual MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read);
- virtual MojoResult DuplicateBufferHandleImplNoLock(
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- scoped_refptr<Dispatcher>* new_dispatcher);
- virtual MojoResult MapBufferImplNoLock(
- uint64_t offset,
- uint64_t num_bytes,
- MojoMapBufferFlags flags,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping);
- virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const;
- virtual MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- virtual void RemoveAwakableImplNoLock(Awakable* awakable,
- HandleSignalsState* signals_state);
-
- // These implement the API used to serialize dispatchers to a |Channel|
- // (described below). They will only be called on a dispatcher that's attached
- // to and "owned" by a |MessageInTransit|. See the non-"impl" versions for
- // more information.
- //
- // Note: |StartSerializeImplNoLock()| is actually called with |lock_| NOT
- // held, since the dispatcher should only be accessible to the calling thread.
- // On Debug builds, |EndSerializeAndCloseImplNoLock()| is called with |lock_|
- // held, to satisfy any |lock_.AssertAcquired()| (e.g., in |CloseImplNoLock()|
- // -- and anything it calls); disentangling those assertions is
- // difficult/fragile, and would weaken our general checking of invariants.
- //
- // TODO(vtl): Consider making these pure virtual once most things support
- // being passed over a message pipe.
- virtual void StartSerializeImplNoLock(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles);
- virtual bool EndSerializeAndCloseImplNoLock(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles);
-
- // Available to subclasses. (Note: Returns a non-const reference, just like
- // |base::AutoLock|'s constructor takes a non-const reference.)
- base::Lock& lock() const { return lock_; }
-
- private:
- friend class DispatcherTransport;
-
- // This should be overridden to return true if/when there's an ongoing
- // operation (e.g., two-phase read/writes on data pipes) that should prevent a
- // handle from being sent over a message pipe (with status "busy").
- virtual bool IsBusyNoLock() const;
-
- // Closes the dispatcher. This must be done under lock, and unlike |Close()|,
- // the dispatcher must not be closed already. (This is the "equivalent" of
- // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the
- // dispatcher must be disposed of instead of "transferred".)
- void CloseNoLock();
-
- // Creates an equivalent dispatcher -- representing the same resource as this
- // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this
- // dispatcher will look as though it was closed, but the resource it
- // represents will be assigned to the new dispatcher. This must be called
- // under the dispatcher's lock.
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock();
-
- // API to serialize dispatchers to a |Channel|, exposed to only
- // |TransportData| (via |TransportData|). They may only be called on a
- // dispatcher attached to a |MessageInTransit| (and in particular not in
- // |CoreImpl|'s handle table).
- //
- // Starts the serialization. Returns (via the two "out" parameters) the
- // maximum amount of space that may be needed to serialize this dispatcher to
- // the given |Channel| (no more than
- // |TransportData::kMaxSerializedDispatcherSize|) and the maximum number of
- // |PlatformHandle|s that may need to be attached (no more than
- // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this
- // dispatcher cannot be serialized to the given |Channel|, |*max_size| and
- // |*max_platform_handles| should be set to zero. A call to this method will
- // ALWAYS be followed by a call to |EndSerializeAndClose()| (even if this
- // dispatcher cannot be serialized to the given |Channel|).
- void StartSerialize(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles);
- // Completes the serialization of this dispatcher to the given |Channel| and
- // closes it. (This call will always follow an earlier call to
- // |StartSerialize()|, with the same |Channel|.) This does so by writing to
- // |destination| and appending any |PlatformHandle|s needed to
- // |platform_handles| (which may be null if no platform handles were indicated
- // to be required to |StartSerialize()|). This may write no more than the
- // amount indicated by |StartSerialize()|. (WARNING: Beware of races, e.g., if
- // something can be mutated between the two calls!) Returns true on success,
- // in which case |*actual_size| is set to the amount it actually wrote to
- // |destination|. On failure, |*actual_size| should not be modified; however,
- // the dispatcher will still be closed.
- bool EndSerializeAndClose(Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles);
-
- // This protects the following members as well as any state added by
- // subclasses.
- mutable base::Lock lock_;
- bool is_closed_;
-
- DISALLOW_COPY_AND_ASSIGN(Dispatcher);
-};
-
-// Wrapper around a |Dispatcher| pointer, while it's being processed to be
-// passed in a message pipe. See the comment about
-// |Dispatcher::HandleTableAccess| for more details.
-//
-// Note: This class is deliberately "thin" -- no more expensive than a
-// |Dispatcher*|.
-class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport {
- public:
- DispatcherTransport() : dispatcher_(nullptr) {}
-
- void End();
-
- Dispatcher::Type GetType() const { return dispatcher_->GetType(); }
- bool IsBusy() const { return dispatcher_->IsBusyNoLock(); }
- void Close() { dispatcher_->CloseNoLock(); }
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndClose() {
- return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock();
- }
-
- bool is_valid() const { return !!dispatcher_; }
-
- protected:
- Dispatcher* dispatcher() { return dispatcher_; }
-
- private:
- friend class Dispatcher::HandleTableAccess;
-
- explicit DispatcherTransport(Dispatcher* dispatcher)
- : dispatcher_(dispatcher) {}
-
- Dispatcher* dispatcher_;
-
- // Copy and assign allowed.
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_DISPATCHER_H_
diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc
deleted file mode 100644
index 97e2eed..0000000
--- a/mojo/edk/system/dispatcher_unittest.cc
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2013 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/dispatcher.h"
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/simple_thread.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/waiter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-// Trivial subclass that makes the constructor public.
-class TrivialDispatcher : public Dispatcher {
- public:
- TrivialDispatcher() {}
-
- Type GetType() const override { return kTypeUnknown; }
-
- private:
- friend class base::RefCountedThreadSafe<TrivialDispatcher>;
- ~TrivialDispatcher() override {}
-
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override {
- lock().AssertAcquired();
- return scoped_refptr<Dispatcher>(new TrivialDispatcher());
- }
-
- DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher);
-};
-
-TEST(DispatcherTest, Basic) {
- scoped_refptr<Dispatcher> d(new TrivialDispatcher());
-
- EXPECT_EQ(Dispatcher::kTypeUnknown, d->GetType());
-
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->WriteMessage(NullUserPointer(), 0, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->WriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->BeginWriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->ReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->BeginReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0));
- Waiter w;
- w.Init();
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- // Okay to remove even if it wasn't added (or was already removed).
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
-
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->WriteMessage(NullUserPointer(), 0, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->WriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->BeginWriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->ReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->BeginReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0));
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-}
-
-class ThreadSafetyStressThread : public base::SimpleThread {
- public:
- enum DispatcherOp {
- CLOSE = 0,
- WRITE_MESSAGE,
- READ_MESSAGE,
- WRITE_DATA,
- BEGIN_WRITE_DATA,
- END_WRITE_DATA,
- READ_DATA,
- BEGIN_READ_DATA,
- END_READ_DATA,
- DUPLICATE_BUFFER_HANDLE,
- MAP_BUFFER,
- ADD_WAITER,
- REMOVE_WAITER,
- DISPATCHER_OP_COUNT
- };
-
- ThreadSafetyStressThread(base::WaitableEvent* event,
- scoped_refptr<Dispatcher> dispatcher,
- DispatcherOp op)
- : base::SimpleThread("thread_safety_stress_thread"),
- event_(event),
- dispatcher_(dispatcher),
- op_(op) {
- CHECK_LE(0, op_);
- CHECK_LT(op_, DISPATCHER_OP_COUNT);
- }
-
- ~ThreadSafetyStressThread() override { Join(); }
-
- private:
- void Run() override {
- event_->Wait();
-
- waiter_.Init();
- switch (op_) {
- case CLOSE: {
- MojoResult r = dispatcher_->Close();
- EXPECT_TRUE(r == MOJO_RESULT_OK || r == MOJO_RESULT_INVALID_ARGUMENT)
- << "Result: " << r;
- break;
- }
- case WRITE_MESSAGE:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->WriteMessage(NullUserPointer(), 0, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- break;
- case READ_MESSAGE:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->ReadMessage(NullUserPointer(), NullUserPointer(),
- nullptr, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- break;
- case WRITE_DATA:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->WriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- break;
- case BEGIN_WRITE_DATA:
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->BeginWriteData(NullUserPointer(), NullUserPointer(),
- MOJO_WRITE_DATA_FLAG_NONE));
- break;
- case END_WRITE_DATA:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndWriteData(0));
- break;
- case READ_DATA:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->ReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- break;
- case BEGIN_READ_DATA:
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->BeginReadData(NullUserPointer(), NullUserPointer(),
- MOJO_READ_DATA_FLAG_NONE));
- break;
- case END_READ_DATA:
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndReadData(0));
- break;
- case DUPLICATE_BUFFER_HANDLE: {
- scoped_refptr<Dispatcher> unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->DuplicateBufferHandle(NullUserPointer(), &unused));
- break;
- }
- case MAP_BUFFER: {
- scoped_ptr<embedder::PlatformSharedBufferMapping> unused;
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused));
- break;
- }
- case ADD_WAITER: {
- HandleSignalsState hss;
- MojoResult r = dispatcher_->AddAwakable(
- &waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss);
- EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION ||
- r == MOJO_RESULT_INVALID_ARGUMENT);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- break;
- }
- case REMOVE_WAITER: {
- HandleSignalsState hss;
- dispatcher_->RemoveAwakable(&waiter_, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
-
- // Always try to remove the waiter, in case we added it.
- HandleSignalsState hss;
- dispatcher_->RemoveAwakable(&waiter_, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- }
-
- base::WaitableEvent* const event_;
- const scoped_refptr<Dispatcher> dispatcher_;
- const DispatcherOp op_;
-
- Waiter waiter_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadSafetyStressThread);
-};
-
-TEST(DispatcherTest, ThreadSafetyStress) {
- static const size_t kRepeatCount = 20;
- static const size_t kNumThreads = 100;
-
- for (size_t i = 0; i < kRepeatCount; i++) {
- // Manual reset, not initially signalled.
- base::WaitableEvent event(true, false);
- scoped_refptr<Dispatcher> d(new TrivialDispatcher());
-
- {
- ScopedVector<ThreadSafetyStressThread> threads;
- for (size_t j = 0; j < kNumThreads; j++) {
- ThreadSafetyStressThread::DispatcherOp op =
- static_cast<ThreadSafetyStressThread::DispatcherOp>(
- (i + j) % ThreadSafetyStressThread::DISPATCHER_OP_COUNT);
- threads.push_back(new ThreadSafetyStressThread(&event, d, op));
- threads.back()->Start();
- }
- // Kicks off real work on the threads:
- event.Signal();
- } // Joins all the threads.
-
- // One of the threads should already have closed the dispatcher.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->Close());
- }
-}
-
-TEST(DispatcherTest, ThreadSafetyStressNoClose) {
- static const size_t kRepeatCount = 20;
- static const size_t kNumThreads = 100;
-
- for (size_t i = 0; i < kRepeatCount; i++) {
- // Manual reset, not initially signalled.
- base::WaitableEvent event(true, false);
- scoped_refptr<Dispatcher> d(new TrivialDispatcher());
-
- {
- ScopedVector<ThreadSafetyStressThread> threads;
- for (size_t j = 0; j < kNumThreads; j++) {
- ThreadSafetyStressThread::DispatcherOp op =
- static_cast<ThreadSafetyStressThread::DispatcherOp>(
- (i + j) % (ThreadSafetyStressThread::DISPATCHER_OP_COUNT - 1) +
- 1);
- threads.push_back(new ThreadSafetyStressThread(&event, d, op));
- threads.back()->Start();
- }
- // Kicks off real work on the threads:
- event.Signal();
- } // Joins all the threads.
-
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- }
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/endpoint_relayer.cc b/mojo/edk/system/endpoint_relayer.cc
deleted file mode 100644
index 52faefa..0000000
--- a/mojo/edk/system/endpoint_relayer.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// 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/endpoint_relayer.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/message_in_transit.h"
-
-namespace mojo {
-namespace system {
-
-EndpointRelayer::EndpointRelayer() {
-}
-
-// static
-unsigned EndpointRelayer::GetPeerPort(unsigned port) {
- DCHECK(port == 0 || port == 1);
- return port ^ 1;
-}
-
-void EndpointRelayer::Init(ChannelEndpoint* endpoint0,
- ChannelEndpoint* endpoint1) {
- DCHECK(endpoint0);
- DCHECK(endpoint1);
- DCHECK(!endpoints_[0]);
- DCHECK(!endpoints_[1]);
- endpoints_[0] = endpoint0;
- endpoints_[1] = endpoint1;
-}
-
-bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) {
- DCHECK(message);
-
- base::AutoLock locker(lock_);
-
- // If we're no longer the client, then reject the message.
- if (!endpoints_[port])
- return false;
-
- // Otherwise, consume it even if the peer port is closed.
- unsigned peer_port = GetPeerPort(port);
- if (endpoints_[peer_port])
- endpoints_[peer_port]->EnqueueMessage(make_scoped_ptr(message));
- return true;
-}
-
-void EndpointRelayer::OnDetachFromChannel(unsigned port) {
- base::AutoLock locker(lock_);
-
- if (endpoints_[port]) {
- endpoints_[port]->DetachFromClient();
- endpoints_[port] = nullptr;
- }
-
- unsigned peer_port = GetPeerPort(port);
- if (endpoints_[peer_port]) {
- endpoints_[peer_port]->DetachFromClient();
- endpoints_[peer_port] = nullptr;
- }
-}
-
-EndpointRelayer::~EndpointRelayer() {
- DCHECK(!endpoints_[0]);
- DCHECK(!endpoints_[1]);
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/endpoint_relayer.h b/mojo/edk/system/endpoint_relayer.h
deleted file mode 100644
index a0a93a4..0000000
--- a/mojo/edk/system/endpoint_relayer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_
-#define MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/channel_endpoint_client.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class ChannelEndpoint;
-
-// This is a simple |ChannelEndpointClient| that just relays messages between
-// two |ChannelEndpoint|s (without the overhead of |MessagePipe|).
-class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer : public ChannelEndpointClient {
- public:
- EndpointRelayer();
-
- // Gets the other port number (i.e., 0 -> 1, 1 -> 0).
- static unsigned GetPeerPort(unsigned port);
-
- // Initialize this object. This must be called before any other method.
- void Init(ChannelEndpoint* endpoint0, ChannelEndpoint* endpoint1);
-
- // |ChannelEndpointClient| methods:
- bool OnReadMessage(unsigned port, MessageInTransit* message) override;
- void OnDetachFromChannel(unsigned port) override;
-
- private:
- ~EndpointRelayer() override;
-
- // TODO(vtl): We could probably get away without the lock if we had a
- // thread-safe |scoped_refptr|.
- base::Lock lock_; // Protects the following members.
- scoped_refptr<ChannelEndpoint> endpoints_[2];
-
- DISALLOW_COPY_AND_ASSIGN(EndpointRelayer);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_
diff --git a/mojo/edk/system/handle_signals_state.h b/mojo/edk/system/handle_signals_state.h
deleted file mode 100644
index 3391ea0..0000000
--- a/mojo/edk/system/handle_signals_state.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
-#define MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
-
-#include "base/macros.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-// Just "add" some constructors and methods to the C struct
-// |MojoHandleSignalsState| (for convenience). This should add no overhead.
-struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState
- : public MojoHandleSignalsState {
- HandleSignalsState() {
- satisfied_signals = MOJO_HANDLE_SIGNAL_NONE;
- satisfiable_signals = MOJO_HANDLE_SIGNAL_NONE;
- }
- HandleSignalsState(MojoHandleSignals satisfied,
- MojoHandleSignals satisfiable) {
- satisfied_signals = satisfied;
- satisfiable_signals = satisfiable;
- }
-
- bool equals(const HandleSignalsState& other) const {
- return satisfied_signals == other.satisfied_signals &&
- satisfiable_signals == other.satisfiable_signals;
- }
-
- bool satisfies(MojoHandleSignals signals) const {
- return !!(satisfied_signals & signals);
- }
-
- bool can_satisfy(MojoHandleSignals signals) const {
- return !!(satisfiable_signals & signals);
- }
-
- // (Copy and assignment allowed.)
-};
-static_assert(sizeof(HandleSignalsState) == sizeof(MojoHandleSignalsState),
- "HandleSignalsState should add no overhead");
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
diff --git a/mojo/edk/system/handle_table.cc b/mojo/edk/system/handle_table.cc
deleted file mode 100644
index e054919..0000000
--- a/mojo/edk/system/handle_table.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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/handle_table.h"
-
-#include <limits>
-#include "base/logging.h"
-#include "base/macros.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/dispatcher.h"
-
-namespace mojo {
-namespace system {
-
-HandleTable::Entry::Entry() : busy(false) {
-}
-
-HandleTable::Entry::Entry(const scoped_refptr<Dispatcher>& dispatcher)
- : dispatcher(dispatcher), busy(false) {
-}
-
-HandleTable::Entry::~Entry() {
- DCHECK(!busy);
-}
-
-HandleTable::HandleTable() : next_handle_(MOJO_HANDLE_INVALID + 1) {
-}
-
-HandleTable::~HandleTable() {
- // This should usually not be reached (the only instance should be owned by
- // the singleton |Core|, which lives forever), except in tests.
-}
-
-Dispatcher* HandleTable::GetDispatcher(MojoHandle handle) {
- DCHECK_NE(handle, MOJO_HANDLE_INVALID);
-
- HandleToEntryMap::iterator it = handle_to_entry_map_.find(handle);
- if (it == handle_to_entry_map_.end())
- return nullptr;
- return it->second.dispatcher.get();
-}
-
-MojoResult HandleTable::GetAndRemoveDispatcher(
- MojoHandle handle,
- scoped_refptr<Dispatcher>* dispatcher) {
- DCHECK_NE(handle, MOJO_HANDLE_INVALID);
- DCHECK(dispatcher);
-
- HandleToEntryMap::iterator it = handle_to_entry_map_.find(handle);
- if (it == handle_to_entry_map_.end())
- return MOJO_RESULT_INVALID_ARGUMENT;
- if (it->second.busy)
- return MOJO_RESULT_BUSY;
- *dispatcher = it->second.dispatcher;
- handle_to_entry_map_.erase(it);
-
- return MOJO_RESULT_OK;
-}
-
-MojoHandle HandleTable::AddDispatcher(
- const scoped_refptr<Dispatcher>& dispatcher) {
- if (handle_to_entry_map_.size() >= GetConfiguration().max_handle_table_size)
- return MOJO_HANDLE_INVALID;
- return AddDispatcherNoSizeCheck(dispatcher);
-}
-
-std::pair<MojoHandle, MojoHandle> HandleTable::AddDispatcherPair(
- const scoped_refptr<Dispatcher>& dispatcher0,
- const scoped_refptr<Dispatcher>& dispatcher1) {
- if (handle_to_entry_map_.size() + 1 >=
- GetConfiguration().max_handle_table_size)
- return std::make_pair(MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID);
- return std::make_pair(AddDispatcherNoSizeCheck(dispatcher0),
- AddDispatcherNoSizeCheck(dispatcher1));
-}
-
-bool HandleTable::AddDispatcherVector(const DispatcherVector& dispatchers,
- MojoHandle* handles) {
- size_t max_message_num_handles = GetConfiguration().max_message_num_handles;
- size_t max_handle_table_size = GetConfiguration().max_handle_table_size;
-
- DCHECK_LE(dispatchers.size(), max_message_num_handles);
- DCHECK(handles);
- DCHECK_LT(
- static_cast<uint64_t>(max_handle_table_size) + max_message_num_handles,
- std::numeric_limits<size_t>::max())
- << "Addition may overflow";
-
- if (handle_to_entry_map_.size() + dispatchers.size() > max_handle_table_size)
- return false;
-
- for (size_t i = 0; i < dispatchers.size(); i++) {
- if (dispatchers[i]) {
- handles[i] = AddDispatcherNoSizeCheck(dispatchers[i]);
- } else {
- LOG(WARNING) << "Invalid dispatcher at index " << i;
- handles[i] = MOJO_HANDLE_INVALID;
- }
- }
- return true;
-}
-
-MojoResult HandleTable::MarkBusyAndStartTransport(
- MojoHandle disallowed_handle,
- const MojoHandle* handles,
- uint32_t num_handles,
- std::vector<DispatcherTransport>* transports) {
- DCHECK_NE(disallowed_handle, MOJO_HANDLE_INVALID);
- DCHECK(handles);
- DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles);
- DCHECK(transports);
- DCHECK_EQ(transports->size(), num_handles);
-
- std::vector<Entry*> entries(num_handles);
-
- // First verify all the handles and get their dispatchers.
- uint32_t i;
- MojoResult error_result = MOJO_RESULT_INTERNAL;
- for (i = 0; i < num_handles; i++) {
- // Sending your own handle is not allowed (and, for consistency, returns
- // "busy").
- if (handles[i] == disallowed_handle) {
- error_result = MOJO_RESULT_BUSY;
- break;
- }
-
- HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]);
- if (it == handle_to_entry_map_.end()) {
- error_result = MOJO_RESULT_INVALID_ARGUMENT;
- break;
- }
-
- entries[i] = &it->second;
- if (entries[i]->busy) {
- error_result = MOJO_RESULT_BUSY;
- break;
- }
- // Note: By marking the handle as busy here, we're also preventing the
- // same handle from being sent multiple times in the same message.
- entries[i]->busy = true;
-
- // Try to start the transport.
- DispatcherTransport transport =
- Dispatcher::HandleTableAccess::TryStartTransport(
- entries[i]->dispatcher.get());
- if (!transport.is_valid()) {
- // Only log for Debug builds, since this is not a problem with the system
- // code, but with user code.
- DLOG(WARNING) << "Likely race condition in user code detected: attempt "
- "to transfer handle " << handles[i]
- << " while it is in use on a different thread";
-
- // Unset the busy flag (since it won't be unset below).
- entries[i]->busy = false;
- error_result = MOJO_RESULT_BUSY;
- break;
- }
-
- // Check if the dispatcher is busy (e.g., in a two-phase read/write).
- // (Note that this must be done after the dispatcher's lock is acquired.)
- if (transport.IsBusy()) {
- // Unset the busy flag and end the transport (since it won't be done
- // below).
- entries[i]->busy = false;
- transport.End();
- error_result = MOJO_RESULT_BUSY;
- break;
- }
-
- // Hang on to the transport (which we'll need to end the transport).
- (*transports)[i] = transport;
- }
- if (i < num_handles) {
- DCHECK_NE(error_result, MOJO_RESULT_INTERNAL);
-
- // Unset the busy flags and release the locks.
- for (uint32_t j = 0; j < i; j++) {
- DCHECK(entries[j]->busy);
- entries[j]->busy = false;
- (*transports)[j].End();
- }
- return error_result;
- }
-
- return MOJO_RESULT_OK;
-}
-
-MojoHandle HandleTable::AddDispatcherNoSizeCheck(
- const scoped_refptr<Dispatcher>& dispatcher) {
- DCHECK(dispatcher);
- DCHECK_LT(handle_to_entry_map_.size(),
- GetConfiguration().max_handle_table_size);
- DCHECK_NE(next_handle_, MOJO_HANDLE_INVALID);
-
- // TODO(vtl): Maybe we want to do something different/smarter. (Or maybe try
- // assigning randomly?)
- while (handle_to_entry_map_.find(next_handle_) !=
- handle_to_entry_map_.end()) {
- next_handle_++;
- if (next_handle_ == MOJO_HANDLE_INVALID)
- next_handle_++;
- }
-
- MojoHandle new_handle = next_handle_;
- handle_to_entry_map_[new_handle] = Entry(dispatcher);
-
- next_handle_++;
- if (next_handle_ == MOJO_HANDLE_INVALID)
- next_handle_++;
-
- return new_handle;
-}
-
-void HandleTable::RemoveBusyHandles(const MojoHandle* handles,
- uint32_t num_handles) {
- DCHECK(handles);
- DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles);
-
- for (uint32_t i = 0; i < num_handles; i++) {
- HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]);
- DCHECK(it != handle_to_entry_map_.end());
- DCHECK(it->second.busy);
- it->second.busy = false; // For the sake of a |DCHECK()|.
- handle_to_entry_map_.erase(it);
- }
-}
-
-void HandleTable::RestoreBusyHandles(const MojoHandle* handles,
- uint32_t num_handles) {
- DCHECK(handles);
- DCHECK_LE(num_handles, GetConfiguration().max_message_num_handles);
-
- for (uint32_t i = 0; i < num_handles; i++) {
- HandleToEntryMap::iterator it = handle_to_entry_map_.find(handles[i]);
- DCHECK(it != handle_to_entry_map_.end());
- DCHECK(it->second.busy);
- it->second.busy = false;
- }
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/handle_table.h b/mojo/edk/system/handle_table.h
deleted file mode 100644
index 9385643..0000000
--- a/mojo/edk/system/handle_table.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
-#define MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
-
-#include <utility>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-class Core;
-class Dispatcher;
-class DispatcherTransport;
-
-typedef std::vector<scoped_refptr<Dispatcher>> DispatcherVector;
-
-// Test-only function (defined/used in embedder/test_embedder.cc). Declared here
-// so it can be friended.
-namespace internal {
-bool ShutdownCheckNoLeaks(Core*);
-}
-
-// This class provides the (global) handle table (owned by |Core|), which maps
-// (valid) |MojoHandle|s to |Dispatcher|s. This is abstracted so that, e.g.,
-// caching may be added.
-//
-// This class is NOT thread-safe; locking is left to |Core| (since it may need
-// to make several changes -- "atomically" or in rapid successsion, in which
-// case the extra locking/unlocking would be unnecessary overhead).
-
-class MOJO_SYSTEM_IMPL_EXPORT HandleTable {
- public:
- HandleTable();
- ~HandleTable();
-
- // Gets the dispatcher for a given handle (which should not be
- // |MOJO_HANDLE_INVALID|). Returns null if there's no dispatcher for the given
- // handle.
- // WARNING: For efficiency, this returns a dumb pointer. If you're going to
- // use the result outside |Core|'s lock, you MUST take a reference (e.g., by
- // storing the result inside a |scoped_refptr|).
- Dispatcher* GetDispatcher(MojoHandle handle);
-
- // On success, gets the dispatcher for a given handle (which should not be
- // |MOJO_HANDLE_INVALID|) and removes it. (On failure, returns an appropriate
- // result (and leaves |dispatcher| alone), namely
- // |MOJO_RESULT_INVALID_ARGUMENT| if there's no dispatcher for the given
- // handle or |MOJO_RESULT_BUSY| if the handle is marked as busy.)
- MojoResult GetAndRemoveDispatcher(MojoHandle handle,
- scoped_refptr<Dispatcher>* dispatcher);
-
- // Adds a dispatcher (which must be valid), returning the handle for it.
- // Returns |MOJO_HANDLE_INVALID| on failure (if the handle table is full).
- MojoHandle AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher);
-
- // Adds a pair of dispatchers (which must be valid), return a pair of handles
- // for them. On failure (if the handle table is full), the first (and second)
- // handles will be |MOJO_HANDLE_INVALID|, and neither dispatcher will be
- // added.
- std::pair<MojoHandle, MojoHandle> AddDispatcherPair(
- const scoped_refptr<Dispatcher>& dispatcher0,
- const scoped_refptr<Dispatcher>& dispatcher1);
-
- // Adds the given vector of dispatchers (of size at most
- // |kMaxMessageNumHandles|). |handles| must point to an array of size at least
- // |dispatchers.size()|. Unlike the other |AddDispatcher...()| functions, some
- // of the dispatchers may be invalid (null). Returns true on success and false
- // on failure (if the handle table is full), in which case it leaves
- // |handles[...]| untouched (and all dispatchers unadded).
- bool AddDispatcherVector(const DispatcherVector& dispatchers,
- MojoHandle* handles);
-
- // Tries to mark the given handles as busy and start transport on them (i.e.,
- // take their dispatcher locks); |transports| must be sized to contain
- // |num_handles| elements. On failure, returns them to their original
- // (non-busy, unlocked state).
- MojoResult MarkBusyAndStartTransport(
- MojoHandle disallowed_handle,
- const MojoHandle* handles,
- uint32_t num_handles,
- std::vector<DispatcherTransport>* transports);
-
- // Remove the given handles, which must all be present and which should have
- // previously been marked busy by |MarkBusyAndStartTransport()|.
- void RemoveBusyHandles(const MojoHandle* handles, uint32_t num_handles);
-
- // Restores the given handles, which must all be present and which should have
- // previously been marked busy by |MarkBusyAndStartTransport()|, to a non-busy
- // state.
- void RestoreBusyHandles(const MojoHandle* handles, uint32_t num_handles);
-
- private:
- friend bool internal::ShutdownCheckNoLeaks(Core*);
-
- // The |busy| member is used only to deal with functions (in particular
- // |Core::WriteMessage()|) that want to hold on to a dispatcher and later
- // remove it from the handle table, without holding on to the handle table
- // lock.
- //
- // For example, if |Core::WriteMessage()| is called with a handle to be sent,
- // (under the handle table lock) it must first check that that handle is not
- // busy (if it is busy, then it fails with |MOJO_RESULT_BUSY|) and then marks
- // it as busy. To avoid deadlock, it should also try to acquire the locks for
- // all the dispatchers for the handles that it is sending (and fail with
- // |MOJO_RESULT_BUSY| if the attempt fails). At this point, it can release the
- // handle table lock.
- //
- // If |Core::Close()| is simultaneously called on that handle, it too checks
- // if the handle is marked busy. If it is, it fails (with |MOJO_RESULT_BUSY|).
- // This prevents |Core::WriteMessage()| from sending a handle that has been
- // closed (or learning about this too late).
- struct Entry {
- Entry();
- explicit Entry(const scoped_refptr<Dispatcher>& dispatcher);
- ~Entry();
-
- scoped_refptr<Dispatcher> dispatcher;
- bool busy;
- };
- typedef base::hash_map<MojoHandle, Entry> HandleToEntryMap;
-
- // Adds the given dispatcher to the handle table, not doing any size checks.
- MojoHandle AddDispatcherNoSizeCheck(
- const scoped_refptr<Dispatcher>& dispatcher);
-
- HandleToEntryMap handle_to_entry_map_;
- MojoHandle next_handle_; // Invariant: never |MOJO_HANDLE_INVALID|.
-
- DISALLOW_COPY_AND_ASSIGN(HandleTable);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
diff --git a/mojo/edk/system/incoming_endpoint.cc b/mojo/edk/system/incoming_endpoint.cc
deleted file mode 100644
index 14f1a71..0000000
--- a/mojo/edk/system/incoming_endpoint.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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/incoming_endpoint.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/message_pipe.h"
-
-namespace mojo {
-namespace system {
-
-IncomingEndpoint::IncomingEndpoint() {
-}
-
-scoped_refptr<ChannelEndpoint> IncomingEndpoint::Init() {
- endpoint_ = new ChannelEndpoint(this, 0);
- return endpoint_;
-}
-
-scoped_refptr<MessagePipe> IncomingEndpoint::ConvertToMessagePipe() {
- base::AutoLock locker(lock_);
- scoped_refptr<MessagePipe> message_pipe(
- MessagePipe::CreateLocalProxyFromExisting(&message_queue_,
- endpoint_.get()));
- DCHECK(message_queue_.IsEmpty());
- endpoint_ = nullptr;
- return message_pipe;
-}
-
-void IncomingEndpoint::Close() {
- base::AutoLock locker(lock_);
- if (endpoint_) {
- endpoint_->DetachFromClient();
- endpoint_ = nullptr;
- }
-}
-
-bool IncomingEndpoint::OnReadMessage(unsigned /*port*/,
- MessageInTransit* message) {
- base::AutoLock locker(lock_);
- if (!endpoint_)
- return false;
-
- message_queue_.AddMessage(make_scoped_ptr(message));
- return true;
-}
-
-void IncomingEndpoint::OnDetachFromChannel(unsigned /*port*/) {
- Close();
-}
-
-IncomingEndpoint::~IncomingEndpoint() {
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/incoming_endpoint.h b/mojo/edk/system/incoming_endpoint.h
deleted file mode 100644
index 4db7d5a..0000000
--- a/mojo/edk/system/incoming_endpoint.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_
-#define MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/channel_endpoint_client.h"
-#include "mojo/edk/system/message_in_transit_queue.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class ChannelEndpoint;
-class MessagePipe;
-
-// This is a simple |ChannelEndpointClient| that only receives messages. It's
-// used for endpoints that are "received" by |Channel|, but not yet turned into
-// |MessagePipe|s.
-class MOJO_SYSTEM_IMPL_EXPORT IncomingEndpoint : public ChannelEndpointClient {
- public:
- IncomingEndpoint();
-
- // Must be called before any other method.
- scoped_refptr<ChannelEndpoint> Init();
-
- scoped_refptr<MessagePipe> ConvertToMessagePipe();
-
- // Must be called before destroying this object if |ConvertToMessagePipe()|
- // wasn't called (but |Init()| was).
- void Close();
-
- // |ChannelEndpointClient| methods:
- bool OnReadMessage(unsigned port, MessageInTransit* message) override;
- void OnDetachFromChannel(unsigned port) override;
-
- private:
- ~IncomingEndpoint() override;
-
- base::Lock lock_; // Protects the following members.
- scoped_refptr<ChannelEndpoint> endpoint_;
- MessageInTransitQueue message_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(IncomingEndpoint);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_INCOMING_ENDPOINT_H_
diff --git a/mojo/edk/system/local_data_pipe.cc b/mojo/edk/system/local_data_pipe.cc
deleted file mode 100644
index 8b9f673..0000000
--- a/mojo/edk/system/local_data_pipe.cc
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2013 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.
-
-// TODO(vtl): I currently potentially overflow in doing index calculations.
-// E.g., |start_index_| and |current_num_bytes_| fit into a |uint32_t|, but
-// their sum may not. This is bad and poses a security risk. (We're currently
-// saved by the limit on capacity -- the maximum size of the buffer, checked in
-// |DataPipe::ValidateOptions()|, is currently sufficiently small.)
-
-#include "mojo/edk/system/local_data_pipe.h"
-
-#include <string.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "mojo/edk/system/configuration.h"
-
-namespace mojo {
-namespace system {
-
-LocalDataPipe::LocalDataPipe(const MojoCreateDataPipeOptions& options)
- : DataPipe(true, true, options), start_index_(0), current_num_bytes_(0) {
- // Note: |buffer_| is lazily allocated, since a common case will be that one
- // of the handles is immediately passed off to another process.
-}
-
-LocalDataPipe::~LocalDataPipe() {
-}
-
-void LocalDataPipe::ProducerCloseImplNoLock() {
- // If the consumer is still open and we still have data, we have to keep the
- // buffer around. Currently, we won't free it even if it empties later. (We
- // could do this -- requiring a check on every read -- but that seems to be
- // optimizing for the uncommon case.)
- if (!consumer_open_no_lock() || !current_num_bytes_) {
- // Note: There can only be a two-phase *read* (by the consumer) if we still
- // have data.
- DCHECK(!consumer_in_two_phase_read_no_lock());
- DestroyBufferNoLock();
- }
-}
-
-MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_write,
- uint32_t min_num_bytes_to_write) {
- DCHECK_EQ(max_num_bytes_to_write % element_num_bytes(), 0u);
- DCHECK_EQ(min_num_bytes_to_write % element_num_bytes(), 0u);
- DCHECK_GT(max_num_bytes_to_write, 0u);
- DCHECK(consumer_open_no_lock());
-
- size_t num_bytes_to_write = 0;
- if (may_discard()) {
- if (min_num_bytes_to_write > capacity_num_bytes())
- return MOJO_RESULT_OUT_OF_RANGE;
-
- num_bytes_to_write = std::min(static_cast<size_t>(max_num_bytes_to_write),
- capacity_num_bytes());
- if (num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) {
- // Discard as much as needed (discard oldest first).
- MarkDataAsConsumedNoLock(num_bytes_to_write -
- (capacity_num_bytes() - current_num_bytes_));
- // No need to wake up write waiters, since we're definitely going to leave
- // the buffer full.
- }
- } else {
- if (min_num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) {
- // Don't return "should wait" since you can't wait for a specified amount
- // of data.
- return MOJO_RESULT_OUT_OF_RANGE;
- }
-
- num_bytes_to_write = std::min(static_cast<size_t>(max_num_bytes_to_write),
- capacity_num_bytes() - current_num_bytes_);
- }
- if (num_bytes_to_write == 0)
- return MOJO_RESULT_SHOULD_WAIT;
-
- // The amount we can write in our first |memcpy()|.
- size_t num_bytes_to_write_first =
- std::min(num_bytes_to_write, GetMaxNumBytesToWriteNoLock());
- // Do the first (and possibly only) |memcpy()|.
- size_t first_write_index =
- (start_index_ + current_num_bytes_) % capacity_num_bytes();
- EnsureBufferNoLock();
- elements.GetArray(buffer_.get() + first_write_index,
- num_bytes_to_write_first);
-
- if (num_bytes_to_write_first < num_bytes_to_write) {
- // The "second write index" is zero.
- elements.At(num_bytes_to_write_first)
- .GetArray(buffer_.get(), num_bytes_to_write - num_bytes_to_write_first);
- }
-
- current_num_bytes_ += num_bytes_to_write;
- DCHECK_LE(current_num_bytes_, capacity_num_bytes());
- num_bytes.Put(static_cast<uint32_t>(num_bytes_to_write));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_write) {
- DCHECK(consumer_open_no_lock());
-
- // The index we need to start writing at.
- size_t write_index =
- (start_index_ + current_num_bytes_) % capacity_num_bytes();
-
- size_t max_num_bytes_to_write = GetMaxNumBytesToWriteNoLock();
- if (min_num_bytes_to_write > max_num_bytes_to_write) {
- // In "may discard" mode, we can always write from the write index to the
- // end of the buffer.
- if (may_discard() &&
- min_num_bytes_to_write <= capacity_num_bytes() - write_index) {
- // To do so, we need to discard an appropriate amount of data.
- // We should only reach here if the start index is after the write index!
- DCHECK_GE(start_index_, write_index);
- DCHECK_GT(min_num_bytes_to_write - max_num_bytes_to_write, 0u);
- MarkDataAsConsumedNoLock(min_num_bytes_to_write - max_num_bytes_to_write);
- max_num_bytes_to_write = min_num_bytes_to_write;
- } else {
- // Don't return "should wait" since you can't wait for a specified amount
- // of data.
- return MOJO_RESULT_OUT_OF_RANGE;
- }
- }
-
- // Don't go into a two-phase write if there's no room.
- if (max_num_bytes_to_write == 0)
- return MOJO_RESULT_SHOULD_WAIT;
-
- EnsureBufferNoLock();
- buffer.Put(buffer_.get() + write_index);
- buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_write));
- set_producer_two_phase_max_num_bytes_written_no_lock(
- static_cast<uint32_t>(max_num_bytes_to_write));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) {
- DCHECK_LE(num_bytes_written,
- producer_two_phase_max_num_bytes_written_no_lock());
- current_num_bytes_ += num_bytes_written;
- DCHECK_LE(current_num_bytes_, capacity_num_bytes());
- set_producer_two_phase_max_num_bytes_written_no_lock(0);
- return MOJO_RESULT_OK;
-}
-
-HandleSignalsState LocalDataPipe::ProducerGetHandleSignalsStateImplNoLock()
- const {
- HandleSignalsState rv;
- if (consumer_open_no_lock()) {
- if ((may_discard() || current_num_bytes_ < capacity_num_bytes()) &&
- !producer_in_two_phase_write_no_lock())
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
- } else {
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- }
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- return rv;
-}
-
-void LocalDataPipe::ConsumerCloseImplNoLock() {
- // If the producer is around and in a two-phase write, we have to keep the
- // buffer around. (We then don't free it until the producer is closed. This
- // could be rectified, but again seems like optimizing for the uncommon case.)
- if (!producer_open_no_lock() || !producer_in_two_phase_write_no_lock())
- DestroyBufferNoLock();
- current_num_bytes_ = 0;
-}
-
-MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(
- UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) {
- DCHECK_EQ(max_num_bytes_to_read % element_num_bytes(), 0u);
- DCHECK_EQ(min_num_bytes_to_read % element_num_bytes(), 0u);
- DCHECK_GT(max_num_bytes_to_read, 0u);
-
- if (min_num_bytes_to_read > current_num_bytes_) {
- // Don't return "should wait" since you can't wait for a specified amount of
- // data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- size_t num_bytes_to_read =
- std::min(static_cast<size_t>(max_num_bytes_to_read), current_num_bytes_);
- if (num_bytes_to_read == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- // The amount we can read in our first |memcpy()|.
- size_t num_bytes_to_read_first =
- std::min(num_bytes_to_read, GetMaxNumBytesToReadNoLock());
- elements.PutArray(buffer_.get() + start_index_, num_bytes_to_read_first);
-
- if (num_bytes_to_read_first < num_bytes_to_read) {
- // The "second read index" is zero.
- elements.At(num_bytes_to_read_first)
- .PutArray(buffer_.get(), num_bytes_to_read - num_bytes_to_read_first);
- }
-
- if (!peek)
- MarkDataAsConsumedNoLock(num_bytes_to_read);
- num_bytes.Put(static_cast<uint32_t>(num_bytes_to_read));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ConsumerDiscardDataImplNoLock(
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_discard,
- uint32_t min_num_bytes_to_discard) {
- DCHECK_EQ(max_num_bytes_to_discard % element_num_bytes(), 0u);
- DCHECK_EQ(min_num_bytes_to_discard % element_num_bytes(), 0u);
- DCHECK_GT(max_num_bytes_to_discard, 0u);
-
- if (min_num_bytes_to_discard > current_num_bytes_) {
- // Don't return "should wait" since you can't wait for a specified amount of
- // data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- // Be consistent with other operations; error if no data available.
- if (current_num_bytes_ == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- size_t num_bytes_to_discard = std::min(
- static_cast<size_t>(max_num_bytes_to_discard), current_num_bytes_);
- MarkDataAsConsumedNoLock(num_bytes_to_discard);
- num_bytes.Put(static_cast<uint32_t>(num_bytes_to_discard));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ConsumerQueryDataImplNoLock(
- UserPointer<uint32_t> num_bytes) {
- // Note: This cast is safe, since the capacity fits into a |uint32_t|.
- num_bytes.Put(static_cast<uint32_t>(current_num_bytes_));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ConsumerBeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_read) {
- size_t max_num_bytes_to_read = GetMaxNumBytesToReadNoLock();
- if (min_num_bytes_to_read > max_num_bytes_to_read) {
- // Don't return "should wait" since you can't wait for a specified amount of
- // data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- // Don't go into a two-phase read if there's no data.
- if (max_num_bytes_to_read == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- buffer.Put(buffer_.get() + start_index_);
- buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_read));
- set_consumer_two_phase_max_num_bytes_read_no_lock(
- static_cast<uint32_t>(max_num_bytes_to_read));
- return MOJO_RESULT_OK;
-}
-
-MojoResult LocalDataPipe::ConsumerEndReadDataImplNoLock(
- uint32_t num_bytes_read) {
- DCHECK_LE(num_bytes_read, consumer_two_phase_max_num_bytes_read_no_lock());
- DCHECK_LE(start_index_ + num_bytes_read, capacity_num_bytes());
- MarkDataAsConsumedNoLock(num_bytes_read);
- set_consumer_two_phase_max_num_bytes_read_no_lock(0);
- return MOJO_RESULT_OK;
-}
-
-HandleSignalsState LocalDataPipe::ConsumerGetHandleSignalsStateImplNoLock()
- const {
- HandleSignalsState rv;
- if (current_num_bytes_ > 0) {
- if (!consumer_in_two_phase_read_no_lock())
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- } else if (producer_open_no_lock()) {
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- }
- if (!producer_open_no_lock())
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- return rv;
-}
-
-void LocalDataPipe::EnsureBufferNoLock() {
- DCHECK(producer_open_no_lock());
- if (buffer_)
- return;
- buffer_.reset(static_cast<char*>(
- base::AlignedAlloc(capacity_num_bytes(),
- GetConfiguration().data_pipe_buffer_alignment_bytes)));
-}
-
-void LocalDataPipe::DestroyBufferNoLock() {
-#ifndef NDEBUG
- // Scribble on the buffer to help detect use-after-frees. (This also helps the
- // unit test detect certain bugs without needing ASAN or similar.)
- if (buffer_)
- memset(buffer_.get(), 0xcd, capacity_num_bytes());
-#endif
- buffer_.reset();
-}
-
-size_t LocalDataPipe::GetMaxNumBytesToWriteNoLock() {
- size_t next_index = start_index_ + current_num_bytes_;
- if (next_index >= capacity_num_bytes()) {
- next_index %= capacity_num_bytes();
- DCHECK_GE(start_index_, next_index);
- DCHECK_EQ(start_index_ - next_index,
- capacity_num_bytes() - current_num_bytes_);
- return start_index_ - next_index;
- }
- return capacity_num_bytes() - next_index;
-}
-
-size_t LocalDataPipe::GetMaxNumBytesToReadNoLock() {
- if (start_index_ + current_num_bytes_ > capacity_num_bytes())
- return capacity_num_bytes() - start_index_;
- return current_num_bytes_;
-}
-
-void LocalDataPipe::MarkDataAsConsumedNoLock(size_t num_bytes) {
- DCHECK_LE(num_bytes, current_num_bytes_);
- start_index_ += num_bytes;
- start_index_ %= capacity_num_bytes();
- current_num_bytes_ -= num_bytes;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/local_data_pipe.h b/mojo/edk/system/local_data_pipe.h
deleted file mode 100644
index abe3a46..0000000
--- a/mojo/edk/system/local_data_pipe.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_LOCAL_DATA_PIPE_H_
-#define MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_H_
-
-#include "base/macros.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// |LocalDataPipe| is a subclass that "implements" |DataPipe| for data pipes
-// whose producer and consumer are both local. This class is thread-safe (with
-// protection provided by |DataPipe|'s |lock_|.
-class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipe : public DataPipe {
- public:
- // |validated_options| should be the output of |DataPipe::ValidateOptions()|.
- // In particular: |struct_size| is ignored (so |validated_options| must be the
- // current version of the struct) and |capacity_num_bytes| must be nonzero.
- explicit LocalDataPipe(const MojoCreateDataPipeOptions& validated_options);
-
- private:
- friend class base::RefCountedThreadSafe<LocalDataPipe>;
- ~LocalDataPipe() override;
-
- // |DataPipe| implementation:
- void ProducerCloseImplNoLock() override;
- MojoResult ProducerWriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_write,
- uint32_t min_num_bytes_to_write) override;
- MojoResult ProducerBeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_write) override;
- MojoResult ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) override;
- HandleSignalsState ProducerGetHandleSignalsStateImplNoLock() const override;
- void ConsumerCloseImplNoLock() override;
- MojoResult ConsumerReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) override;
- MojoResult ConsumerDiscardDataImplNoLock(
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_discard,
- uint32_t min_num_bytes_to_discard) override;
- MojoResult ConsumerQueryDataImplNoLock(
- UserPointer<uint32_t> num_bytes) override;
- MojoResult ConsumerBeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_read) override;
- MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) override;
- HandleSignalsState ConsumerGetHandleSignalsStateImplNoLock() const override;
-
- void EnsureBufferNoLock();
- void DestroyBufferNoLock();
-
- // Get the maximum (single) write/read size right now (in number of elements);
- // result fits in a |uint32_t|.
- size_t GetMaxNumBytesToWriteNoLock();
- size_t GetMaxNumBytesToReadNoLock();
-
- // Marks the given number of bytes as consumed/discarded. |num_bytes| must be
- // greater than |current_num_bytes_|.
- void MarkDataAsConsumedNoLock(size_t num_bytes);
-
- // The members below are protected by |DataPipe|'s |lock_|:
- scoped_ptr<char, base::AlignedFreeDeleter> buffer_;
- // Circular buffer.
- size_t start_index_;
- size_t current_num_bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalDataPipe);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_H_
diff --git a/mojo/edk/system/local_data_pipe_unittest.cc b/mojo/edk/system/local_data_pipe_unittest.cc
deleted file mode 100644
index 1223a2ba..0000000
--- a/mojo/edk/system/local_data_pipe_unittest.cc
+++ /dev/null
@@ -1,2071 +0,0 @@
-// Copyright 2013 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/local_data_pipe.h"
-
-#include <string.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/waiter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const uint32_t kSizeOfOptions =
- static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions));
-
-// Validate options.
-TEST(LocalDataPipeTest, Creation) {
- // Create using default options.
- {
- // Get default options.
- MojoCreateDataPipeOptions default_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- NullUserPointer(), &default_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(default_options));
- dp->ProducerClose();
- dp->ConsumerClose();
- }
-
- // Create using non-default options.
- {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1, // |element_num_bytes|.
- 1000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- dp->ProducerClose();
- dp->ConsumerClose();
- }
- {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 4, // |element_num_bytes|.
- 4000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- dp->ProducerClose();
- dp->ConsumerClose();
- }
- {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- 7, // |element_num_bytes|.
- 7000000 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- dp->ProducerClose();
- dp->ConsumerClose();
- }
- // Default capacity.
- {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- 100, // |element_num_bytes|.
- 0 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK,
- DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
- &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- dp->ProducerClose();
- dp->ConsumerClose();
- }
-}
-
-TEST(LocalDataPipeTest, SimpleReadWrite) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- int32_t elements[10] = {0};
- uint32_t num_bytes = 0;
-
- // Try reading; nothing there yet.
- num_bytes = static_cast<uint32_t>(arraysize(elements) * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), false, false));
-
- // Query; nothing there yet.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Discard; nothing there yet.
- num_bytes = static_cast<uint32_t>(5u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false));
-
- // Read with invalid |num_bytes|.
- num_bytes = sizeof(elements[0]) + 1;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), false, false));
-
- // Write two elements.
- elements[0] = 123;
- elements[1] = 456;
- num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), false));
- // It should have written everything (even without "all or none").
- EXPECT_EQ(2u * sizeof(elements[0]), num_bytes);
-
- // Query.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(2 * sizeof(elements[0]), num_bytes);
-
- // Read one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(1u * sizeof(elements[0]), num_bytes);
- EXPECT_EQ(123, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Query.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1 * sizeof(elements[0]), num_bytes);
-
- // Peek one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), false, true));
- EXPECT_EQ(1u * sizeof(elements[0]), num_bytes);
- EXPECT_EQ(456, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Query. Still has 1 element remaining.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1 * sizeof(elements[0]), num_bytes);
-
- // Try to read two elements, with "all or none".
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(-1, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Try to read two elements, without "all or none".
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(456, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Query.
- num_bytes = 0;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-// Note: The "basic" waiting tests test that the "wait states" are correct in
-// various situations; they don't test that waiters are properly awoken on state
-// changes. (For that, we need to use multiple threads.)
-TEST(LocalDataPipeTest, BasicProducerWaiting) {
- // Note: We take advantage of the fact that for |LocalDataPipe|, capacities
- // are strict maximums. This is not guaranteed by the API.
-
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 2 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- Waiter waiter;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Never readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Already writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, &hss));
-
- // Write two elements.
- int32_t elements[2] = {123, 456};
- uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes);
-
- // Adding a waiter should now succeed.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56,
- nullptr));
- // And it shouldn't be writable yet.
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Peek one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, true));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(123, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Add a waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56,
- nullptr));
- // And it still shouldn't be writable yet.
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Do it again.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78,
- nullptr));
-
- // Read one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(123, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Waiting should now succeed.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
- EXPECT_EQ(78u, context);
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Try writing, using a two-phase write.
- void* buffer = nullptr;
- num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(buffer);
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
-
- static_cast<int32_t*>(buffer)[0] = 789;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(static_cast<uint32_t>(
- 1u * sizeof(elements[0]))));
-
- // Add a waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90,
- nullptr));
-
- // Read one element, using a two-phase read.
- const void* read_buffer = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer);
- // Since we only read one element (after having written three in all), the
- // two-phase read should only allow us to read one. This checks an
- // implementation detail!
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- dp->ConsumerEndReadData(static_cast<uint32_t>(1u * sizeof(elements[0]))));
-
- // Waiting should succeed.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
- EXPECT_EQ(90u, context);
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Write one element.
- elements[0] = 123;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
-
- // Add a waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12,
- nullptr));
-
- // Close the consumer.
- dp->ConsumerClose();
-
- // It should now be never-writable.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
- EXPECT_EQ(12u, context);
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- dp->ProducerClose();
-}
-
-TEST(LocalDataPipeTest, PeerClosedWaiting) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 2 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- Waiter waiter;
- HandleSignalsState hss;
-
- // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on producer.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- // Add a waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- 12, nullptr));
-
- // Close the consumer.
- dp->ConsumerClose();
-
- // It should be signaled.
- uint32_t context = 0;
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
- EXPECT_EQ(12u, context);
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- dp->ProducerClose();
- }
-
- // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on consumer.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- // Add a waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- 12, nullptr));
-
- // Close the producer.
- dp->ProducerClose();
-
- // It should be signaled.
- uint32_t context = 0;
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
- EXPECT_EQ(12u, context);
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- dp->ConsumerClose();
- }
-}
-
-TEST(LocalDataPipeTest, BasicConsumerWaiting) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- Waiter waiter;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Never writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12,
- &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Not yet readable.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Write two elements.
- int32_t elements[2] = {123, 456};
- uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), true));
-
- // Should already be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Discard one element.
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
-
- // Should still be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Peek one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, true));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(456, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Should still be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(456, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Adding a waiter should now succeed.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90,
- nullptr));
-
- // Write one element.
- elements[0] = 789;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), true));
-
- // Waiting should now succeed.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
- EXPECT_EQ(90u, context);
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Close the producer.
- dp->ProducerClose();
-
- // Should still be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read one element.
- elements[0] = -1;
- elements[1] = -1;
- num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(elements),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- EXPECT_EQ(789, elements[0]);
- EXPECT_EQ(-1, elements[1]);
-
- // Should be never-readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- dp->ConsumerClose();
- }
-
- // Test with two-phase APIs and closing the producer with an active consumer
- // waiter.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- Waiter waiter;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Write two elements.
- int32_t* elements = nullptr;
- void* buffer = nullptr;
- // Request room for three (but we'll only write two).
- uint32_t num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_TRUE(buffer);
- EXPECT_GE(num_bytes, static_cast<uint32_t>(3u * sizeof(elements[0])));
- elements = static_cast<int32_t*>(buffer);
- elements[0] = 123;
- elements[1] = 456;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(static_cast<uint32_t>(
- 2u * sizeof(elements[0]))));
-
- // Should already be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read one element.
- // Request two in all-or-none mode, but only read one.
- const void* read_buffer = nullptr;
- num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_TRUE(read_buffer);
- EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes);
- const int32_t* read_elements = static_cast<const int32_t*>(read_buffer);
- EXPECT_EQ(123, read_elements[0]);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(static_cast<uint32_t>(
- 1u * sizeof(elements[0]))));
-
- // Should still be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34,
- &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read one element.
- // Request three, but not in all-or-none mode.
- read_buffer = nullptr;
- num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer);
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
- read_elements = static_cast<const int32_t*>(read_buffer);
- EXPECT_EQ(456, read_elements[0]);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(static_cast<uint32_t>(
- 1u * sizeof(elements[0]))));
-
- // Adding a waiter should now succeed.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56,
- nullptr));
-
- // Close the producer.
- dp->ProducerClose();
-
- // Should be never-readable.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
- EXPECT_EQ(56u, context);
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- dp->ConsumerClose();
- }
-}
-
-// Tests that data pipes aren't writable/readable during two-phase writes/reads.
-TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- Waiter waiter;
- HandleSignalsState hss;
-
- // It should be writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
- void* write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_ptr);
- EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t)));
-
- // At this point, it shouldn't be writable.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ProducerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // It shouldn't be readable yet either.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- static_cast<int32_t*>(write_ptr)[0] = 123;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(
- static_cast<uint32_t>(1u * sizeof(int32_t))));
-
- // It should be writable again.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // And readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Start another two-phase write and check that it's readable even in the
- // middle of it.
- num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_ptr);
- EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t)));
-
- // It should be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // End the two-phase write without writing anything.
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u));
-
- // Start a two-phase read.
- num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
- const void* read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_ptr);
- EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(int32_t)), num_bytes);
-
- // At this point, it should still be writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // But not readable.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // End the two-phase read without reading anything.
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u));
-
- // It should be readable again.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-// Test that a "may discard" data pipe is writable even when it's full.
-TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
- Waiter waiter;
- HandleSignalsState hss;
-
- // Writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Not readable.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t));
- int32_t element = 123;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(&element),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
-
- // Still writable (even though it's full).
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Now readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Overwrite that element.
- num_bytes = static_cast<uint32_t>(sizeof(int32_t));
- element = 456;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(&element),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
-
- // Still writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // And still readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read that element.
- num_bytes = static_cast<uint32_t>(sizeof(int32_t));
- element = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(&element),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes);
- EXPECT_EQ(456, element);
-
- // Still writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // No longer readable.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- dp->ConsumerRemoveAwakable(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-void Seq(int32_t start, size_t count, int32_t* out) {
- for (size_t i = 0; i < count; i++)
- out[i] = start + static_cast<int32_t>(i);
-}
-
-TEST(LocalDataPipeTest, MayDiscard) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- int32_t buffer[100] = {0};
- uint32_t num_bytes = 0;
-
- num_bytes = 20u * sizeof(int32_t);
- Seq(0, arraysize(buffer), buffer);
- // Try writing more than capacity. (This test relies on the implementation
- // enforcing the capacity strictly.)
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
-
- // Read half of what we wrote.
- num_bytes = 5u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- int32_t expected_buffer[100];
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- Seq(0, 5u, expected_buffer);
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
- // Internally, a circular buffer would now look like:
- // -, -, -, -, -, 5, 6, 7, 8, 9
-
- // Write a bit more than the space that's available.
- num_bytes = 8u * sizeof(int32_t);
- Seq(100, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(8u * sizeof(int32_t), num_bytes);
- // Internally, a circular buffer would now look like:
- // 100, 101, 102, 103, 104, 105, 106, 107, 8, 9
-
- // Read half of what's available.
- num_bytes = 5u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- expected_buffer[0] = 8;
- expected_buffer[1] = 9;
- expected_buffer[2] = 100;
- expected_buffer[3] = 101;
- expected_buffer[4] = 102;
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
- // Internally, a circular buffer would now look like:
- // -, -, -, 103, 104, 105, 106, 107, -, -
-
- // Write one integer.
- num_bytes = 1u * sizeof(int32_t);
- Seq(200, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
- // Internally, a circular buffer would now look like:
- // -, -, -, 103, 104, 105, 106, 107, 200, -
-
- // Write five more.
- num_bytes = 5u * sizeof(int32_t);
- Seq(300, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- // Internally, a circular buffer would now look like:
- // 301, 302, 303, 304, 104, 105, 106, 107, 200, 300
-
- // Read it all.
- num_bytes = sizeof(buffer);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- expected_buffer[0] = 104;
- expected_buffer[1] = 105;
- expected_buffer[2] = 106;
- expected_buffer[3] = 107;
- expected_buffer[4] = 200;
- expected_buffer[5] = 300;
- expected_buffer[6] = 301;
- expected_buffer[7] = 302;
- expected_buffer[8] = 303;
- expected_buffer[9] = 304;
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Test two-phase writes, including in all-or-none mode.
- // Note: Again, the following depends on an implementation detail -- namely
- // that the write pointer will point at the 5th element of the buffer (and the
- // buffer has exactly the capacity requested).
-
- num_bytes = 0u;
- void* write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_ptr);
- EXPECT_EQ(6u * sizeof(int32_t), num_bytes);
- Seq(400, 6, static_cast<int32_t*>(write_ptr));
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(6u * sizeof(int32_t)));
- // Internally, a circular buffer would now look like:
- // -, -, -, -, 400, 401, 402, 403, 404, 405
-
- // |ProducerBeginWriteData()| ignores |*num_bytes| except in "all-or-none"
- // mode.
- num_bytes = 6u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(4u * sizeof(int32_t), num_bytes);
- static_cast<int32_t*>(write_ptr)[0] = 500;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(1u * sizeof(int32_t)));
- // Internally, a circular buffer would now look like:
- // 500, -, -, -, 400, 401, 402, 403, 404, 405
-
- // Requesting a 10-element buffer in all-or-none mode fails at this point.
- num_bytes = 10u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // But requesting, say, a 5-element (up to 9, really) buffer should be okay.
- // It will discard two elements.
- num_bytes = 5u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- // Only write 4 elements though.
- Seq(600, 4, static_cast<int32_t*>(write_ptr));
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(4u * sizeof(int32_t)));
- // Internally, a circular buffer would now look like:
- // 500, 600, 601, 602, 603, -, 402, 403, 404, 405
-
- // Do this again. Make sure we can get a buffer all the way out to the end of
- // the internal buffer.
- num_bytes = 5u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- // Only write 3 elements though.
- Seq(700, 3, static_cast<int32_t*>(write_ptr));
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(3u * sizeof(int32_t)));
- // Internally, a circular buffer would now look like:
- // 500, 600, 601, 602, 603, 700, 701, 702, -, -
-
- // Read everything.
- num_bytes = sizeof(buffer);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(8u * sizeof(int32_t), num_bytes);
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- expected_buffer[0] = 500;
- expected_buffer[1] = 600;
- expected_buffer[2] = 601;
- expected_buffer[3] = 602;
- expected_buffer[4] = 603;
- expected_buffer[5] = 700;
- expected_buffer[6] = 701;
- expected_buffer[7] = 702;
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-TEST(LocalDataPipeTest, AllOrNone) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Try writing way too much.
- uint32_t num_bytes = 20u * sizeof(int32_t);
- int32_t buffer[100];
- Seq(0, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
-
- // Should still be empty.
- num_bytes = ~0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Write some data.
- num_bytes = 5u * sizeof(int32_t);
- Seq(100, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
-
- // Half full.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
-
- // Too much.
- num_bytes = 6u * sizeof(int32_t);
- Seq(200, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
-
- // Try reading too much.
- num_bytes = 11u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- int32_t expected_buffer[100];
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try discarding too much.
- num_bytes = 11u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
-
- // Just a little.
- num_bytes = 2u * sizeof(int32_t);
- Seq(300, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
-
- // Just right.
- num_bytes = 3u * sizeof(int32_t);
- Seq(400, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(3u * sizeof(int32_t), num_bytes);
-
- // Exactly full.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
-
- // Read half.
- num_bytes = 5u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- Seq(100, 5, expected_buffer);
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try reading too much again.
- num_bytes = 6u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try discarding too much again.
- num_bytes = 6u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
-
- // Discard a little.
- num_bytes = 2u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
-
- // Three left.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(3u * sizeof(int32_t), num_bytes);
-
- // Close the producer, then test producer-closed cases.
- dp->ProducerClose();
-
- // Try reading too much; "failed precondition" since the producer is closed.
- num_bytes = 4u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try discarding too much; "failed precondition" again.
- num_bytes = 4u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
-
- // Read a little.
- num_bytes = 2u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(2u * sizeof(int32_t), num_bytes);
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- Seq(400, 2, expected_buffer);
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Discard the remaining element.
- num_bytes = 1u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
-
- // Empty again.
- num_bytes = ~0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- dp->ConsumerClose();
-}
-
-TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Try writing way too much.
- uint32_t num_bytes = 20u * sizeof(int32_t);
- int32_t buffer[100];
- Seq(0, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
-
- // Write some stuff.
- num_bytes = 5u * sizeof(int32_t);
- Seq(100, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
-
- // Write lots of stuff (discarding all but "104").
- num_bytes = 9u * sizeof(int32_t);
- Seq(200, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(9u * sizeof(int32_t), num_bytes);
-
- // Read one.
- num_bytes = 1u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
- int32_t expected_buffer[100];
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- expected_buffer[0] = 104;
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try reading too many.
- num_bytes = 10u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Try discarding too many.
- num_bytes = 10u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
-
- // Discard a bunch.
- num_bytes = 4u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true));
-
- // Half full.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(5u * sizeof(int32_t), num_bytes);
-
- // Write as much as possible.
- num_bytes = 10u * sizeof(int32_t);
- Seq(300, arraysize(buffer), buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
-
- // Read everything.
- num_bytes = 10u * sizeof(int32_t);
- memset(buffer, 0xab, sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), true, false));
- memset(expected_buffer, 0xab, sizeof(expected_buffer));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
- Seq(300, 10, expected_buffer);
- EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
-
- // Note: All-or-none two-phase writes on a "may discard" data pipe are tested
- // in LocalDataPipeTest.MayDiscard.
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Try writing way too much (two-phase).
- uint32_t num_bytes = 20u * sizeof(int32_t);
- void* write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Try writing an amount which isn't a multiple of the element size
- // (two-phase).
- static_assert(sizeof(int32_t) > 1u, "Wow! int32_t's have size 1");
- num_bytes = 1u;
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Try reading way too much (two-phase).
- num_bytes = 20u * sizeof(int32_t);
- const void* read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Write half (two-phase).
- num_bytes = 5u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
- // May provide more space than requested.
- EXPECT_GE(num_bytes, 5u * sizeof(int32_t));
- EXPECT_TRUE(write_ptr);
- Seq(0, 5, static_cast<int32_t*>(write_ptr));
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(5u * sizeof(int32_t)));
-
- // Try reading an amount which isn't a multiple of the element size
- // (two-phase).
- num_bytes = 1u;
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Read one (two-phase).
- num_bytes = 1u * sizeof(int32_t);
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
- EXPECT_GE(num_bytes, 1u * sizeof(int32_t));
- EXPECT_EQ(0, static_cast<const int32_t*>(read_ptr)[0]);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(1u * sizeof(int32_t)));
-
- // We should have four left, leaving room for six.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(4u * sizeof(int32_t), num_bytes);
-
- // Assuming a tight circular buffer of the specified capacity, we can't do a
- // two-phase write of six now.
- num_bytes = 6u * sizeof(int32_t);
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Write six elements (simple), filling the buffer.
- num_bytes = 6u * sizeof(int32_t);
- int32_t buffer[100];
- Seq(100, 6, buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(buffer),
- MakeUserPointer(&num_bytes), true));
- EXPECT_EQ(6u * sizeof(int32_t), num_bytes);
-
- // We have ten.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
-
- // But a two-phase read of ten should fail.
- num_bytes = 10u * sizeof(int32_t);
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
-
- // Close the producer.
- dp->ProducerClose();
-
- // A two-phase read of nine should work.
- num_bytes = 9u * sizeof(int32_t);
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
- EXPECT_GE(num_bytes, 9u * sizeof(int32_t));
- EXPECT_EQ(1, static_cast<const int32_t*>(read_ptr)[0]);
- EXPECT_EQ(2, static_cast<const int32_t*>(read_ptr)[1]);
- EXPECT_EQ(3, static_cast<const int32_t*>(read_ptr)[2]);
- EXPECT_EQ(4, static_cast<const int32_t*>(read_ptr)[3]);
- EXPECT_EQ(100, static_cast<const int32_t*>(read_ptr)[4]);
- EXPECT_EQ(101, static_cast<const int32_t*>(read_ptr)[5]);
- EXPECT_EQ(102, static_cast<const int32_t*>(read_ptr)[6]);
- EXPECT_EQ(103, static_cast<const int32_t*>(read_ptr)[7]);
- EXPECT_EQ(104, static_cast<const int32_t*>(read_ptr)[8]);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(9u * sizeof(int32_t)));
-
- // A two-phase read of two should fail, with "failed precondition".
- num_bytes = 2u * sizeof(int32_t);
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), true));
-
- dp->ConsumerClose();
-}
-
-// Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads,
-// respectively, as much as possible, even if it has to "wrap around" the
-// internal circular buffer. (Note that the two-phase write and read do not do
-// this.)
-TEST(LocalDataPipeTest, WrapAround) {
- unsigned char test_data[1000];
- for (size_t i = 0; i < arraysize(test_data); i++)
- test_data[i] = static_cast<unsigned char>(i);
-
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 100u // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
- // This test won't be valid if |ValidateCreateOptions()| decides to give the
- // pipe more space.
- ASSERT_EQ(100u, validated_options.capacity_num_bytes);
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Write 20 bytes.
- uint32_t num_bytes = 20u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(&test_data[0]),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(20u, num_bytes);
-
- // Read 10 bytes.
- unsigned char read_buffer[1000] = {0};
- num_bytes = 10u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(read_buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(10u, num_bytes);
- EXPECT_EQ(0, memcmp(read_buffer, &test_data[0], 10u));
-
- // Check that a two-phase write can now only write (at most) 80 bytes. (This
- // checks an implementation detail; this behavior is not guaranteed, but we
- // need it for this test.)
- void* write_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_buffer_ptr);
- EXPECT_EQ(80u, num_bytes);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u));
-
- // Write as much data as we can (using |ProducerWriteData()|). We should write
- // 90 bytes.
- num_bytes = 200u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(&test_data[20]),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(90u, num_bytes);
-
- // Check that a two-phase read can now only read (at most) 90 bytes. (This
- // checks an implementation detail; this behavior is not guaranteed, but we
- // need it for this test.)
- const void* read_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer_ptr);
- EXPECT_EQ(90u, num_bytes);
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u));
-
- // Read as much as possible (using |ConsumerReadData()|). We should read 100
- // bytes.
- num_bytes =
- static_cast<uint32_t>(arraysize(read_buffer) * sizeof(read_buffer[0]));
- memset(read_buffer, 0, num_bytes);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(read_buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(100u, num_bytes);
- EXPECT_EQ(0, memcmp(read_buffer, &test_data[10], 100u));
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-// Tests the behavior of closing the producer or consumer with respect to
-// writes and reads (simple and two-phase).
-TEST(LocalDataPipeTest, CloseWriteRead) {
- const char kTestData[] = "hello world";
- const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
-
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- // Close producer first, then consumer.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Write some data, so we'll have something to read.
- uint32_t num_bytes = kTestDataSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(kTestData),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Write it again, so we'll have something left over.
- num_bytes = kTestDataSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(kTestData),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Start two-phase write.
- void* write_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_buffer_ptr);
- EXPECT_GT(num_bytes, 0u);
-
- // Start two-phase read.
- const void* read_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer_ptr);
- EXPECT_EQ(2u * kTestDataSize, num_bytes);
-
- // Close the producer.
- dp->ProducerClose();
-
- // The consumer can finish its two-phase read.
- EXPECT_EQ(0, memcmp(read_buffer_ptr, kTestData, kTestDataSize));
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(kTestDataSize));
-
- // And start another.
- read_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer_ptr);
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Close the consumer, which cancels the two-phase read.
- dp->ConsumerClose();
- }
-
- // Close consumer first, then producer.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Write some data, so we'll have something to read.
- uint32_t num_bytes = kTestDataSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(kTestData),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Start two-phase write.
- void* write_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_buffer_ptr);
- ASSERT_GT(num_bytes, kTestDataSize);
-
- // Start two-phase read.
- const void* read_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(read_buffer_ptr);
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Close the consumer.
- dp->ConsumerClose();
-
- // Actually write some data. (Note: Premature freeing of the buffer would
- // probably only be detected under ASAN or similar.)
- memcpy(write_buffer_ptr, kTestData, kTestDataSize);
- // Note: Even though the consumer has been closed, ending the two-phase
- // write will report success.
- EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(kTestDataSize));
-
- // But trying to write should result in failure.
- num_bytes = kTestDataSize;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ProducerWriteData(UserPointer<const void>(kTestData),
- MakeUserPointer(&num_bytes), false));
-
- // As will trying to start another two-phase write.
- write_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
-
- dp->ProducerClose();
- }
-
- // Test closing the consumer first, then the producer, with an active
- // two-phase write.
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Start two-phase write.
- void* write_buffer_ptr = nullptr;
- uint32_t num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_TRUE(write_buffer_ptr);
- ASSERT_GT(num_bytes, kTestDataSize);
-
- dp->ConsumerClose();
- dp->ProducerClose();
- }
-
- // Test closing the producer and then trying to read (with no data).
- {
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Write some data, so we'll have something to read.
- uint32_t num_bytes = kTestDataSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(kTestData),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(kTestDataSize, num_bytes);
-
- // Close the producer.
- dp->ProducerClose();
-
- // Peek that data.
- char buffer[1000];
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, true));
- EXPECT_EQ(kTestDataSize, num_bytes);
- EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize));
-
- // Read that data.
- memset(buffer, 0, 1000);
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
- EXPECT_EQ(kTestDataSize, num_bytes);
- EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize));
-
- // A second read should fail.
- num_bytes = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerReadData(UserPointer<void>(buffer),
- MakeUserPointer(&num_bytes), false, false));
-
- // A two-phase read should also fail.
- const void* read_buffer_ptr = nullptr;
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr),
- MakeUserPointer(&num_bytes), false));
-
- // Ditto for discard.
- num_bytes = 10u;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false));
-
- dp->ConsumerClose();
- }
-}
-
-TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // No data.
- uint32_t num_bytes = 1000u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Try "ending" a two-phase write when one isn't active.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ProducerEndWriteData(1u * sizeof(int32_t)));
-
- // Still no data.
- num_bytes = 1000u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Try ending a two-phase write with an invalid amount (too much).
- num_bytes = 0u;
- void* write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dp->ProducerEndWriteData(num_bytes +
- static_cast<uint32_t>(sizeof(int32_t))));
-
- // But the two-phase write still ended.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, dp->ProducerEndWriteData(0u));
-
- // Still no data.
- num_bytes = 1000u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Try ending a two-phase write with an invalid amount (not a multiple of the
- // element size).
- num_bytes = 0u;
- write_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_GE(num_bytes, 1u);
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ProducerEndWriteData(1u));
-
- // But the two-phase write still ended.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, dp->ProducerEndWriteData(0u));
-
- // Still no data.
- num_bytes = 1000u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(0u, num_bytes);
-
- // Now write some data, so we'll be able to try reading.
- int32_t element = 123;
- num_bytes = 1u * sizeof(int32_t);
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(&element),
- MakeUserPointer(&num_bytes), false));
-
- // One element available.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
-
- // Try "ending" a two-phase read when one isn't active.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- dp->ConsumerEndReadData(1u * sizeof(int32_t)));
-
- // Still one element available.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
-
- // Try ending a two-phase read with an invalid amount (too much).
- num_bytes = 0u;
- const void* read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dp->ConsumerEndReadData(num_bytes +
- static_cast<uint32_t>(sizeof(int32_t))));
-
- // Still one element available.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
-
- // Try ending a two-phase read with an invalid amount (not a multiple of the
- // element size).
- num_bytes = 0u;
- read_ptr = nullptr;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
- EXPECT_EQ(123, static_cast<const int32_t*>(read_ptr)[0]);
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ConsumerEndReadData(1u));
-
- // Still one element available.
- num_bytes = 0u;
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes)));
- EXPECT_EQ(1u * sizeof(int32_t), num_bytes);
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-// Tests that even with "may discard", the data won't change under a two-phase
-// read.
-// TODO(vtl): crbug.com/348644: We currently don't pass this. (There are two
-// related issues: First, we don't recognize that the data given to
-// |ConsumerBeginReadData()| isn't discardable until |ConsumerEndReadData()|,
-// and thus we erroneously allow |ProducerWriteData()| to succeed. Second, the
-// |ProducerWriteData()| then changes the data underneath the two-phase read.)
-TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
- 1, // |element_num_bytes|.
- 2 // |capacity_num_bytes|.
- };
- MojoCreateDataPipeOptions validated_options = {0};
- EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options));
-
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
-
- // Write some elements.
- char elements[2] = {'a', 'b'};
- uint32_t num_bytes = 2u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(2u, num_bytes);
-
- // Begin reading.
- const void* read_ptr = nullptr;
- num_bytes = 2u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(2u, num_bytes);
- EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]);
- EXPECT_EQ('b', static_cast<const char*>(read_ptr)[1]);
-
- // Try to write some more. But nothing should be discardable right now.
- elements[0] = 'x';
- elements[1] = 'y';
- num_bytes = 2u;
- // TODO(vtl): This should be:
- // EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- // dp->ProducerWriteData(elements, &num_bytes, false));
- // but we incorrectly think that the bytes being read are discardable. Letting
- // this through reveals the significant consequence.
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), false));
-
- // Check that our read buffer hasn't changed underneath us.
- EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]);
- EXPECT_EQ('b', static_cast<const char*>(read_ptr)[1]);
-
- // End reading.
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(2u));
-
- // Now writing should succeed.
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ProducerWriteData(UserPointer<const void>(elements),
- MakeUserPointer(&num_bytes), false));
-
- // And if we read, we should get the new values.
- read_ptr = nullptr;
- num_bytes = 2u;
- EXPECT_EQ(MOJO_RESULT_OK,
- dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr),
- MakeUserPointer(&num_bytes), false));
- EXPECT_EQ(2u, num_bytes);
- EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]);
- EXPECT_EQ('y', static_cast<const char*>(read_ptr)[1]);
-
- // End reading.
- EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(2u));
-
- dp->ProducerClose();
- dp->ConsumerClose();
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc
deleted file mode 100644
index 1800aa4..0000000
--- a/mojo/edk/system/local_message_pipe_endpoint.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2013 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/local_message_pipe_endpoint.h"
-
-#include <string.h>
-
-#include "base/logging.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/message_in_transit.h"
-
-namespace mojo {
-namespace system {
-
-LocalMessagePipeEndpoint::LocalMessagePipeEndpoint(
- MessageInTransitQueue* message_queue)
- : is_open_(true), is_peer_open_(true) {
- if (message_queue)
- message_queue_.Swap(message_queue);
-}
-
-LocalMessagePipeEndpoint::~LocalMessagePipeEndpoint() {
- DCHECK(!is_open_);
- DCHECK(message_queue_.IsEmpty()); // Should be implied by not being open.
-}
-
-MessagePipeEndpoint::Type LocalMessagePipeEndpoint::GetType() const {
- return kTypeLocal;
-}
-
-bool LocalMessagePipeEndpoint::OnPeerClose() {
- DCHECK(is_open_);
- DCHECK(is_peer_open_);
-
- HandleSignalsState old_state = GetHandleSignalsState();
- is_peer_open_ = false;
- HandleSignalsState new_state = GetHandleSignalsState();
-
- if (!new_state.equals(old_state))
- awakable_list_.AwakeForStateChange(new_state);
-
- return true;
-}
-
-void LocalMessagePipeEndpoint::EnqueueMessage(
- scoped_ptr<MessageInTransit> message) {
- DCHECK(is_open_);
- DCHECK(is_peer_open_);
-
- bool was_empty = message_queue_.IsEmpty();
- message_queue_.AddMessage(message.Pass());
- if (was_empty)
- awakable_list_.AwakeForStateChange(GetHandleSignalsState());
-}
-
-void LocalMessagePipeEndpoint::Close() {
- DCHECK(is_open_);
- is_open_ = false;
- message_queue_.Clear();
-}
-
-void LocalMessagePipeEndpoint::CancelAllAwakables() {
- DCHECK(is_open_);
- awakable_list_.CancelAll();
-}
-
-MojoResult LocalMessagePipeEndpoint::ReadMessage(
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) {
- DCHECK(is_open_);
- DCHECK(!dispatchers || dispatchers->empty());
-
- const uint32_t max_bytes = num_bytes.IsNull() ? 0 : num_bytes.Get();
- const uint32_t max_num_dispatchers = num_dispatchers ? *num_dispatchers : 0;
-
- if (message_queue_.IsEmpty()) {
- return is_peer_open_ ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- // TODO(vtl): If |flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD|, we could pop
- // and release the lock immediately.
- bool enough_space = true;
- MessageInTransit* message = message_queue_.PeekMessage();
- if (!num_bytes.IsNull())
- num_bytes.Put(message->num_bytes());
- if (message->num_bytes() <= max_bytes)
- bytes.PutArray(message->bytes(), message->num_bytes());
- else
- enough_space = false;
-
- if (DispatcherVector* queued_dispatchers = message->dispatchers()) {
- if (num_dispatchers)
- *num_dispatchers = static_cast<uint32_t>(queued_dispatchers->size());
- if (enough_space) {
- if (queued_dispatchers->empty()) {
- // Nothing to do.
- } else if (queued_dispatchers->size() <= max_num_dispatchers) {
- DCHECK(dispatchers);
- dispatchers->swap(*queued_dispatchers);
- } else {
- enough_space = false;
- }
- }
- } else {
- if (num_dispatchers)
- *num_dispatchers = 0;
- }
-
- message = nullptr;
-
- if (enough_space || (flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)) {
- message_queue_.DiscardMessage();
-
- // Now it's empty, thus no longer readable.
- if (message_queue_.IsEmpty()) {
- // It's currently not possible to wait for non-readability, but we should
- // do the state change anyway.
- awakable_list_.AwakeForStateChange(GetHandleSignalsState());
- }
- }
-
- if (!enough_space)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- return MOJO_RESULT_OK;
-}
-
-HandleSignalsState LocalMessagePipeEndpoint::GetHandleSignalsState() const {
- HandleSignalsState rv;
- if (!message_queue_.IsEmpty()) {
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- }
- if (is_peer_open_) {
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
- rv.satisfiable_signals |=
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE;
- } else {
- rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- }
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
- return rv;
-}
-
-MojoResult LocalMessagePipeEndpoint::AddAwakable(
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- DCHECK(is_open_);
-
- HandleSignalsState state = GetHandleSignalsState();
- if (state.satisfies(signals)) {
- if (signals_state)
- *signals_state = state;
- return MOJO_RESULT_ALREADY_EXISTS;
- }
- if (!state.can_satisfy(signals)) {
- if (signals_state)
- *signals_state = state;
- return MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- awakable_list_.Add(awakable, signals, context);
- return MOJO_RESULT_OK;
-}
-
-void LocalMessagePipeEndpoint::RemoveAwakable(
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- DCHECK(is_open_);
- awakable_list_.Remove(awakable);
- if (signals_state)
- *signals_state = GetHandleSignalsState();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/local_message_pipe_endpoint.h b/mojo/edk/system/local_message_pipe_endpoint.h
deleted file mode 100644
index f792d90..0000000
--- a/mojo/edk/system/local_message_pipe_endpoint.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_
-#define MOJO_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "mojo/edk/system/awakable_list.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/message_in_transit_queue.h"
-#include "mojo/edk/system/message_pipe_endpoint.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint
- : public MessagePipeEndpoint {
- public:
- // If |message_queue| is non-null, its contents will be taken as the queue of
- // (already-received) messages.
- explicit LocalMessagePipeEndpoint(
- MessageInTransitQueue* message_queue = nullptr);
- ~LocalMessagePipeEndpoint() override;
-
- // |MessagePipeEndpoint| implementation:
- Type GetType() const override;
- bool OnPeerClose() override;
- void EnqueueMessage(scoped_ptr<MessageInTransit> message) override;
-
- // There's a dispatcher for |LocalMessagePipeEndpoint|s, so we have to
- // implement/override these:
- void Close() override;
- void CancelAllAwakables() override;
- MojoResult ReadMessage(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) override;
- HandleSignalsState GetHandleSignalsState() const override;
- MojoResult AddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) override;
- void RemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state) override;
-
- // This is only to be used by |MessagePipe|:
- MessageInTransitQueue* message_queue() { return &message_queue_; }
-
- private:
- bool is_open_;
- bool is_peer_open_;
-
- // Queue of incoming messages.
- MessageInTransitQueue message_queue_;
- AwakableList awakable_list_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalMessagePipeEndpoint);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_LOCAL_MESSAGE_PIPE_ENDPOINT_H_
diff --git a/mojo/edk/system/mapping_table.cc b/mojo/edk/system/mapping_table.cc
deleted file mode 100644
index 693e8d7..0000000
--- a/mojo/edk/system/mapping_table.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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/mapping_table.h"
-
-#include "base/logging.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/configuration.h"
-
-namespace mojo {
-namespace system {
-
-MappingTable::MappingTable() {
-}
-
-MappingTable::~MappingTable() {
- // This should usually not be reached (the only instance should be owned by
- // the singleton |Core|, which lives forever), except in tests.
-}
-
-MojoResult MappingTable::AddMapping(
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping) {
- DCHECK(mapping);
-
- if (address_to_mapping_map_.size() >=
- GetConfiguration().max_mapping_table_sze)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- uintptr_t address = reinterpret_cast<uintptr_t>(mapping->GetBase());
- DCHECK(address_to_mapping_map_.find(address) ==
- address_to_mapping_map_.end());
- address_to_mapping_map_[address] = mapping.release();
- return MOJO_RESULT_OK;
-}
-
-MojoResult MappingTable::RemoveMapping(uintptr_t address) {
- AddressToMappingMap::iterator it = address_to_mapping_map_.find(address);
- if (it == address_to_mapping_map_.end())
- return MOJO_RESULT_INVALID_ARGUMENT;
- embedder::PlatformSharedBufferMapping* mapping_to_delete = it->second;
- address_to_mapping_map_.erase(it);
- delete mapping_to_delete;
- return MOJO_RESULT_OK;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/mapping_table.h b/mojo/edk/system/mapping_table.h
deleted file mode 100644
index d2812d8..0000000
--- a/mojo/edk/system/mapping_table.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
-#define MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformSharedBufferMapping;
-}
-
-namespace system {
-
-class Core;
-
-// Test-only function (defined/used in embedder/test_embedder.cc). Declared here
-// so it can be friended.
-namespace internal {
-bool ShutdownCheckNoLeaks(Core*);
-}
-
-// This class provides the (global) table of memory mappings (owned by |Core|),
-// which maps mapping base addresses to |PlatformSharedBufferMapping|s.
-//
-// This class is NOT thread-safe; locking is left to |Core|.
-class MOJO_SYSTEM_IMPL_EXPORT MappingTable {
- public:
- MappingTable();
- ~MappingTable();
-
- // Tries to add a mapping. (Takes ownership of the mapping in all cases; on
- // failure, it will be destroyed.)
- MojoResult AddMapping(
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping);
- MojoResult RemoveMapping(uintptr_t address);
-
- private:
- friend bool internal::ShutdownCheckNoLeaks(Core*);
-
- typedef base::hash_map<uintptr_t, embedder::PlatformSharedBufferMapping*>
- AddressToMappingMap;
- AddressToMappingMap address_to_mapping_map_;
-
- DISALLOW_COPY_AND_ASSIGN(MappingTable);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
diff --git a/mojo/edk/system/memory.cc b/mojo/edk/system/memory.cc
deleted file mode 100644
index 0e3d9a9..0000000
--- a/mojo/edk/system/memory.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 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/memory.h"
-
-#include <limits>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-namespace mojo {
-namespace system {
-namespace internal {
-
-template <size_t alignment>
-bool IsAligned(const void* pointer) {
- return reinterpret_cast<uintptr_t>(pointer) % alignment == 0;
-}
-
-// MSVS (2010, 2013) sometimes (on the stack) aligns, e.g., |int64_t|s (for
-// which |__alignof(int64_t)| is 8) to 4-byte boundaries. http://goo.gl/Y2n56T
-#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
-template <>
-bool IsAligned<8>(const void* pointer) {
- return reinterpret_cast<uintptr_t>(pointer) % 4 == 0;
-}
-#endif
-
-template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) {
- CHECK(pointer && IsAligned<alignment>(pointer));
-}
-
-// Explicitly instantiate the sizes we need. Add instantiations as needed.
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(const void*);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(const void*);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 4>(const void*);
-template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(const void*);
-
-template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount(const void* pointer, size_t count) {
- CHECK_LE(count, std::numeric_limits<size_t>::max() / size);
- CHECK(count == 0 || (pointer && IsAligned<alignment>(pointer)));
-}
-
-// Explicitly instantiate the sizes we need. Add instantiations as needed.
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount<1, 1>(const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount<4, 4>(const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount<8, 4>(const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount<8, 8>(const void*, size_t);
-
-template <size_t alignment>
-void CheckUserPointerWithSize(const void* pointer, size_t size) {
- // TODO(vtl): If running in kernel mode, do a full verification. For now, just
- // check that it's non-null and aligned. (A faster user mode implementation is
- // also possible if this check is skipped.)
- CHECK(size == 0 || (!!pointer && internal::IsAligned<alignment>(pointer)));
-}
-
-// Explicitly instantiate the sizes we need. Add instantiations as needed.
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithSize<1>(const void*, size_t);
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithSize<4>(const void*, size_t);
-// Whereas the other |Check...()| functions are usually used with integral typs
-// or arrays of integral types, this one is used with Options structs for which
-// alignment has been explicitly been specified (using |MOJO_ALIGNAS()|), which
-// MSVS *does* respect.
-#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
-template <>
-void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithSize<8>(const void* pointer, size_t size) {
- CHECK(size == 0 ||
- (!!pointer && reinterpret_cast<uintptr_t>(pointer) % 8 == 0));
-}
-#else
-template void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithSize<8>(const void*, size_t);
-#endif
-
-} // namespace internal
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/memory.h b/mojo/edk/system/memory.h
deleted file mode 100644
index 96cf219..0000000
--- a/mojo/edk/system/memory.h
+++ /dev/null
@@ -1,377 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_MEMORY_H_
-#define MOJO_EDK_SYSTEM_MEMORY_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h> // For |memcpy()|.
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/macros.h"
-
-namespace mojo {
-namespace system {
-
-namespace internal {
-
-// Removes |const| from |T| (available as |remove_const<T>::type|):
-// TODO(vtl): Remove these once we have the C++11 |remove_const|.
-template <typename T>
-struct remove_const {
- typedef T type;
-};
-template <typename T>
-struct remove_const<const T> {
- typedef T type;
-};
-
-// Yields |(const) char| if |T| is |(const) void|, else |T|:
-template <typename T>
-struct VoidToChar {
- typedef T type;
-};
-template <>
-struct VoidToChar<void> {
- typedef char type;
-};
-template <>
-struct VoidToChar<const void> {
- typedef const char type;
-};
-
-// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
-// a buffer of the given size and alignment (both in bytes).
-template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer);
-
-// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
-// a buffer of |count| elements of the given size and alignment (both in bytes).
-template <size_t size, size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithCount(const void* pointer, size_t count);
-
-// Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
-// a buffer of the given size and alignment (both in bytes).
-template <size_t alignment>
-void MOJO_SYSTEM_IMPL_EXPORT
-CheckUserPointerWithSize(const void* pointer, size_t size);
-
-} // namespace internal
-
-// Forward declarations so that they can be friended.
-template <typename Type>
-class UserPointerReader;
-template <typename Type>
-class UserPointerWriter;
-template <typename Type>
-class UserPointerReaderWriter;
-template <class Options>
-class UserOptionsReader;
-
-// Provides a convenient way to implicitly get null |UserPointer<Type>|s.
-struct NullUserPointer {};
-
-// Represents a user pointer to a single |Type| (which must be POD), for Mojo
-// primitive parameters.
-//
-// Use a const |Type| for in parameters, and non-const |Type|s for out and
-// in-out parameters (in which case the |Put()| method is available).
-template <typename Type>
-class UserPointer {
- private:
- typedef typename internal::VoidToChar<Type>::type NonVoidType;
-
- public:
- // Instead of explicitly using these constructors, you can often use
- // |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common
- // exception is when you have, e.g., a |char*| and want to get a
- // |UserPointer<void>|.)
- UserPointer() : pointer_(nullptr) {}
- explicit UserPointer(Type* pointer) : pointer_(pointer) {}
- // Allow implicit conversion from the "null user pointer".
- UserPointer(NullUserPointer) : pointer_(nullptr) {}
- ~UserPointer() {}
-
- // Allow assignment from the "null user pointer".
- UserPointer<Type>& operator=(NullUserPointer) {
- pointer_ = nullptr;
- return *this;
- }
-
- // Allow conversion to a "non-const" |UserPointer|.
- operator UserPointer<const Type>() const {
- return UserPointer<const Type>(pointer_);
- }
-
- bool IsNull() const { return !pointer_; }
-
- // "Reinterpret casts" to a |UserPointer<ToType>|.
- template <typename ToType>
- UserPointer<ToType> ReinterpretCast() const {
- return UserPointer<ToType>(reinterpret_cast<ToType*>(pointer_));
- }
-
- // Checks that this pointer points to a valid |Type| in the same way as
- // |Get()| and |Put()|.
- // TODO(vtl): Logically, there should be separate read checks and write
- // checks.
- void Check() const {
- internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(
- pointer_);
- }
-
- // Checks that this pointer points to a valid array (of type |Type|, or just a
- // buffer if |Type| is |void| or |const void|) of |count| elements (or bytes
- // if |Type| is |void| or |const void|) in the same way as |GetArray()| and
- // |PutArray()|.
- // TODO(vtl): Logically, there should be separate read checks and write
- // checks.
- // TODO(vtl): Switch more things to use this.
- void CheckArray(size_t count) const {
- internal::CheckUserPointerWithCount<sizeof(NonVoidType),
- MOJO_ALIGNOF(NonVoidType)>(pointer_,
- count);
- }
-
- // Gets the value (of type |Type|, or a |char| if |Type| is |void|) pointed to
- // by this user pointer. Use this when you'd use the rvalue |*user_pointer|,
- // but be aware that this may be costly -- so if the value will be used
- // multiple times, you should save it.
- //
- // (We want to force a copy here, so return |Type| not |const Type&|.)
- NonVoidType Get() const {
- Check();
- internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(
- pointer_);
- return *pointer_;
- }
-
- // Gets an array (of type |Type|, or just a buffer if |Type| is |void| or
- // |const void|) of |count| elements (or bytes if |Type| is |void| or |const
- // void|) from the location pointed to by this user pointer. Use this when
- // you'd do something like |memcpy(destination, user_pointer, count *
- // sizeof(Type)|.
- void GetArray(typename internal::remove_const<Type>::type* destination,
- size_t count) const {
- CheckArray(count);
- memcpy(destination, pointer_, count * sizeof(NonVoidType));
- }
-
- // Puts a value (of type |Type|, or of type |char| if |Type| is |void|) to the
- // location pointed to by this user pointer. Use this when you'd use the
- // lvalue |*user_pointer|. Since this may be costly, you should avoid using
- // this (for the same user pointer) more than once.
- //
- // Note: This |Put()| method is not valid when |T| is const, e.g., |const
- // uint32_t|, but it's okay to include them so long as this template is only
- // implicitly instantiated (see 14.7.1 of the C++11 standard) and not
- // explicitly instantiated. (On implicit instantiation, only the declarations
- // need be valid, not the definitions.)
- //
- // In C++11, we could do something like:
- // template <typename _Type = Type>
- // typename enable_if<!is_const<_Type>::value &&
- // !is_void<_Type>::value>::type Put(
- // const _Type& value) { ... }
- // (which obviously be correct), but C++03 doesn't allow default function
- // template arguments.
- void Put(const NonVoidType& value) {
- Check();
- *pointer_ = value;
- }
-
- // Puts an array (of type |Type|, or just a buffer if |Type| is |void|) with
- // |count| elements (or bytes |Type| is |void|) to the location pointed to by
- // this user pointer. Use this when you'd do something like
- // |memcpy(user_pointer, source, count * sizeof(Type))|.
- //
- // Note: The same comments about the validity of |Put()| (except for the part
- // about |void|) apply here.
- void PutArray(const Type* source, size_t count) {
- CheckArray(count);
- memcpy(pointer_, source, count * sizeof(NonVoidType));
- }
-
- // Gets a |UserPointer| at offset |i| (in |Type|s) relative to this.
- UserPointer At(size_t i) const {
- return UserPointer(
- static_cast<Type*>(static_cast<NonVoidType*>(pointer_) + i));
- }
-
- // Gets the value of the |UserPointer| as a |uintptr_t|. This should not be
- // casted back to a pointer (and dereferenced), but may be used as a key for
- // lookup or passed back to the user.
- uintptr_t GetPointerValue() const {
- return reinterpret_cast<uintptr_t>(pointer_);
- }
-
- // These provides safe (read-only/write-only/read-and-write) access to a
- // |UserPointer<Type>| (probably pointing to an array) using just an ordinary
- // pointer (obtained via |GetPointer()|).
- //
- // The memory returned by |GetPointer()| may be a copy of the original user
- // memory, but should be modified only if the user is intended to eventually
- // see the change.) If any changes are made, |Commit()| should be called to
- // guarantee that the changes are written back to user memory (it may be
- // called multiple times).
- //
- // Note: These classes are designed to allow fast, unsafe implementations (in
- // which |GetPointer()| just returns the user pointer) if desired. Thus if
- // |Commit()| is *not* called, changes may or may not be made visible to the
- // user.
- //
- // Use these classes in the following way:
- //
- // MojoResult Core::PutFoos(UserPointer<const uint32_t> foos,
- // uint32_t num_foos) {
- // UserPointer<const uint32_t>::Reader foos_reader(foos, num_foos);
- // return PutFoosImpl(foos_reader.GetPointer(), num_foos);
- // }
- //
- // MojoResult Core::GetFoos(UserPointer<uint32_t> foos,
- // uint32_t num_foos) {
- // UserPointer<uint32_t>::Writer foos_writer(foos, num_foos);
- // MojoResult rv = GetFoosImpl(foos.GetPointer(), num_foos);
- // foos_writer.Commit();
- // return rv;
- // }
- //
- // TODO(vtl): Possibly, since we're not really being safe, we should just not
- // copy for Release builds.
- typedef UserPointerReader<Type> Reader;
- typedef UserPointerWriter<Type> Writer;
- typedef UserPointerReaderWriter<Type> ReaderWriter;
-
- private:
- friend class UserPointerReader<Type>;
- friend class UserPointerReader<const Type>;
- friend class UserPointerWriter<Type>;
- friend class UserPointerReaderWriter<Type>;
- template <class Options>
- friend class UserOptionsReader;
-
- Type* pointer_;
- // Allow copy and assignment.
-};
-
-// Provides a convenient way to make a |UserPointer<Type>|.
-template <typename Type>
-inline UserPointer<Type> MakeUserPointer(Type* pointer) {
- return UserPointer<Type>(pointer);
-}
-
-// Implementation of |UserPointer<Type>::Reader|.
-template <typename Type>
-class UserPointerReader {
- private:
- typedef typename internal::remove_const<Type>::type TypeNoConst;
-
- public:
- // Note: If |count| is zero, |GetPointer()| will always return null.
- UserPointerReader(UserPointer<const Type> user_pointer, size_t count) {
- Init(user_pointer.pointer_, count, true);
- }
- UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) {
- Init(user_pointer.pointer_, count, true);
- }
-
- const Type* GetPointer() const { return buffer_.get(); }
-
- private:
- template <class Options>
- friend class UserOptionsReader;
-
- struct NoCheck {};
- UserPointerReader(NoCheck,
- UserPointer<const Type> user_pointer,
- size_t count) {
- Init(user_pointer.pointer_, count, false);
- }
-
- void Init(const Type* user_pointer, size_t count, bool check) {
- if (count == 0)
- return;
-
- if (check) {
- internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
- user_pointer, count);
- }
- buffer_.reset(new TypeNoConst[count]);
- memcpy(buffer_.get(), user_pointer, count * sizeof(Type));
- }
-
- scoped_ptr<TypeNoConst[]> buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(UserPointerReader);
-};
-
-// Implementation of |UserPointer<Type>::Writer|.
-template <typename Type>
-class UserPointerWriter {
- public:
- // Note: If |count| is zero, |GetPointer()| will always return null.
- UserPointerWriter(UserPointer<Type> user_pointer, size_t count)
- : user_pointer_(user_pointer), count_(count) {
- if (count_ > 0) {
- buffer_.reset(new Type[count_]);
- memset(buffer_.get(), 0, count_ * sizeof(Type));
- }
- }
-
- Type* GetPointer() const { return buffer_.get(); }
-
- void Commit() {
- internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
- user_pointer_.pointer_, count_);
- memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
- }
-
- private:
- UserPointer<Type> user_pointer_;
- size_t count_;
- scoped_ptr<Type[]> buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(UserPointerWriter);
-};
-
-// Implementation of |UserPointer<Type>::ReaderWriter|.
-template <typename Type>
-class UserPointerReaderWriter {
- public:
- // Note: If |count| is zero, |GetPointer()| will always return null.
- UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count)
- : user_pointer_(user_pointer), count_(count) {
- if (count_ > 0) {
- internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
- user_pointer_.pointer_, count_);
- buffer_.reset(new Type[count]);
- memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type));
- }
- }
-
- Type* GetPointer() const { return buffer_.get(); }
- size_t GetCount() const { return count_; }
-
- void Commit() {
- internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
- user_pointer_.pointer_, count_);
- memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
- }
-
- private:
- UserPointer<Type> user_pointer_;
- size_t count_;
- scoped_ptr<Type[]> buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MEMORY_H_
diff --git a/mojo/edk/system/memory_unittest.cc b/mojo/edk/system/memory_unittest.cc
deleted file mode 100644
index 46515c0..0000000
--- a/mojo/edk/system/memory_unittest.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-// 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/memory.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "mojo/public/c/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-TEST(MemoryTest, Valid) {
- char my_char;
- int32_t my_int32;
- int64_t my_int64_array[5] = {}; // Zero initialize.
-
- UserPointer<char> my_char_ptr(&my_char);
- UserPointer<int32_t> my_int32_ptr(&my_int32);
- UserPointer<int64_t> my_int64_array_ptr(my_int64_array);
-
- // |UserPointer<>::IsNull()|:
- EXPECT_FALSE(my_char_ptr.IsNull());
- EXPECT_FALSE(my_int32_ptr.IsNull());
- EXPECT_FALSE(my_int64_array_ptr.IsNull());
-
- // |UserPointer<>::Put()| and |UserPointer<>::Get()|:
- my_char_ptr.Put('x');
- EXPECT_EQ('x', my_char);
- EXPECT_EQ('x', my_char_ptr.Get());
- my_int32_ptr.Put(123);
- EXPECT_EQ(123, my_int32);
- EXPECT_EQ(123, my_int32_ptr.Get());
- my_int64_array_ptr.Put(456);
- EXPECT_EQ(456, my_int64_array[0]);
- EXPECT_EQ(456, my_int64_array_ptr.Get());
-
- // |UserPointer<>::At()|, etc.:
- my_int64_array_ptr.At(3).Put(789);
- EXPECT_EQ(789, my_int64_array[3]);
- {
- // Copy construction:
- UserPointer<int64_t> other(my_int64_array_ptr.At(3));
- EXPECT_FALSE(other.IsNull());
- EXPECT_EQ(789, other.Get());
-
- // Assignment:
- other = my_int64_array_ptr;
- EXPECT_FALSE(other.IsNull());
- EXPECT_EQ(456, other.Get());
-
- // Assignment to |NullUserPointer()|:
- other = NullUserPointer();
- EXPECT_TRUE(other.IsNull());
-
- // |MakeUserPointer()|:
- other = MakeUserPointer(&my_int64_array[1]);
- other.Put(-123);
- EXPECT_EQ(-123, my_int64_array_ptr.At(1).Get());
- }
-
- // "const" |UserPointer<>|:
- {
- // Explicit constructor from |NullUserPointer()|:
- UserPointer<const char> other((NullUserPointer()));
- EXPECT_TRUE(other.IsNull());
-
- // Conversion to "const":
- other = my_char_ptr;
- EXPECT_EQ('x', other.Get());
- }
-
- // Default constructor:
- {
- UserPointer<int32_t> other;
- EXPECT_TRUE(other.IsNull());
-
- other = my_int32_ptr;
- other.Put(-456);
- EXPECT_EQ(-456, my_int32_ptr.Get());
- }
-
- // |UserPointer<>::CheckArray()|:
- my_int64_array_ptr.CheckArray(5);
-
- // |UserPointer<>::GetArray()|:
- {
- // From a "const" |UserPointer<>| (why not?):
- UserPointer<const int64_t> other(my_int64_array_ptr);
- int64_t array[3] = {1, 2, 3};
- other.At(1).GetArray(array, 3);
- EXPECT_EQ(-123, array[0]);
- EXPECT_EQ(0, array[1]);
- EXPECT_EQ(789, array[2]);
- }
-
- // |UserPointer<>::PutArray()|:
- {
- const int64_t array[2] = {654, 321};
- my_int64_array_ptr.At(3).PutArray(array, 2);
- EXPECT_EQ(0, my_int64_array[2]);
- EXPECT_EQ(654, my_int64_array[3]);
- EXPECT_EQ(321, my_int64_array[4]);
- }
-
- // |UserPointer<>::Reader|:
- {
- UserPointer<int64_t>::Reader reader(my_int64_array_ptr, 5);
- EXPECT_EQ(456, reader.GetPointer()[0]);
- EXPECT_EQ(321, reader.GetPointer()[4]);
- }
-
- // Non-const to const:
- {
- UserPointer<const int64_t>::Reader reader(my_int64_array_ptr.At(3), 1);
- const int64_t* ptr = reader.GetPointer();
- EXPECT_EQ(654, *ptr);
- }
-
- // |UserPointer<>::Writer|:
- {
- UserPointer<int64_t>::Writer writer(my_int64_array_ptr.At(2), 1);
- int64_t* ptr = writer.GetPointer();
- *ptr = 1234567890123LL;
- writer.Commit();
- EXPECT_EQ(1234567890123LL, my_int64_array[2]);
- }
-
- // |UserPointer<>::ReaderWriter|:
- {
- UserPointer<int32_t>::ReaderWriter reader_writer(my_int32_ptr, 1);
- int32_t* ptr = reader_writer.GetPointer();
- EXPECT_EQ(-456, *ptr);
- *ptr = 42;
- reader_writer.Commit();
- EXPECT_EQ(42, my_int32);
- }
-
- // |UserPointer<>::ReinterpretCast<>|:
- // (This assumes little-endian, etc.)
- {
- UserPointer<const char> other(my_int32_ptr.ReinterpretCast<char>());
- EXPECT_EQ(42, other.Get());
- EXPECT_EQ(0, other.At(1).Get());
- EXPECT_EQ(0, other.At(2).Get());
- EXPECT_EQ(0, other.At(3).Get());
- }
-
- // |UserPointer<>::GetPointerValue()|:
- {
- UserPointer<int32_t> other;
- EXPECT_EQ(0u, other.GetPointerValue());
- other = my_int32_ptr;
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&my_int32), other.GetPointerValue());
- }
-}
-
-TEST(MemoryTest, InvalidDeath) {
- const char kMemoryCheckFailedRegex[] = "Check failed";
-
- // Note: |Check...()| are defined to be "best effort" checks (and may always
- // return true). Thus these tests of invalid cases only reflect the current
- // implementation.
-
- // These tests depend on |int32_t| and |int64_t| having nontrivial alignment.
- static_assert(MOJO_ALIGNOF(int32_t) != 1,
- "int32_t does not require nontrivial alignment");
- static_assert(MOJO_ALIGNOF(int64_t) != 1,
- "int64_t does not require nontrivial alignment");
-
- // Null:
- {
- UserPointer<char> ptr(nullptr);
- char array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Put('x'), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
- }
- {
- UserPointer<int32_t> ptr(nullptr);
- int32_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
- }
- {
- UserPointer<int64_t> ptr(nullptr);
- int64_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
- }
- // Also check a const pointer:
- {
- UserPointer<const int32_t> ptr(nullptr);
- int32_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- }
-
- // Unaligned:
- {
- int32_t x[10];
- UserPointer<int32_t> ptr(
- reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(x) + 1));
- int32_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
- }
- {
- int64_t x[10];
- UserPointer<int64_t> ptr(
- reinterpret_cast<int64_t*>(reinterpret_cast<uintptr_t>(x) + 1));
- int64_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
- }
- // Also check a const pointer:
- {
- int32_t x[10];
- UserPointer<const int32_t> ptr(
- reinterpret_cast<const int32_t*>(reinterpret_cast<uintptr_t>(x) + 1));
- int32_t array[5] = {};
- EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
- }
-
- // Count too big:
- {
- const size_t kTooBig =
- std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1;
- int32_t x = 0;
- UserPointer<int32_t> ptr(&x);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
- kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig),
- kMemoryCheckFailedRegex);
- }
- {
- const size_t kTooBig =
- std::numeric_limits<size_t>::max() / sizeof(int64_t) + 1;
- int64_t x = 0;
- UserPointer<int64_t> ptr(&x);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
- kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig),
- kMemoryCheckFailedRegex);
- }
- // Also check a const pointer:
- {
- const size_t kTooBig =
- std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1;
- int32_t x = 0;
- UserPointer<const int32_t> ptr(&x);
- EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
- EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
- kMemoryCheckFailedRegex);
- }
-
- // TODO(vtl): Tests for |UserPointer{Reader,Writer,ReaderWriter}|.
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc
deleted file mode 100644
index 68919f2..0000000
--- a/mojo/edk/system/message_in_transit.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2013 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/message_in_transit.h"
-
-#include <string.h>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/transport_data.h"
-
-namespace mojo {
-namespace system {
-
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
- MessageInTransit::kTypeEndpoint;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
- MessageInTransit::kTypeChannel;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
- MessageInTransit::kTypeRawChannel;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
- MessageInTransit::kSubtypeEndpointData;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
- MessageInTransit::kSubtypeChannelAttachAndRunEndpoint;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
- MessageInTransit::kSubtypeChannelRemoveEndpoint;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
- MessageInTransit::kSubtypeChannelRemoveEndpointAck;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
- MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles;
-STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
-
-struct MessageInTransit::PrivateStructForCompileAsserts {
- // The size of |Header| must be a multiple of the alignment.
- static_assert(sizeof(Header) % kMessageAlignment == 0,
- "sizeof(MessageInTransit::Header) invalid");
-};
-
-MessageInTransit::View::View(size_t message_size, const void* buffer)
- : buffer_(buffer) {
- size_t next_message_size = 0;
- DCHECK(MessageInTransit::GetNextMessageSize(buffer_, message_size,
- &next_message_size));
- DCHECK_EQ(message_size, next_message_size);
- // This should be equivalent.
- DCHECK_EQ(message_size, total_size());
-}
-
-bool MessageInTransit::View::IsValid(size_t serialized_platform_handle_size,
- const char** error_message) const {
- size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes;
- // Avoid dangerous situations, but making sure that the size of the "header" +
- // the size of the data fits into a 31-bit number.
- DCHECK_LE(static_cast<uint64_t>(sizeof(Header)) + max_message_num_bytes,
- 0x7fffffffULL)
- << "GetConfiguration().max_message_num_bytes too big";
-
- // We assume (to avoid extra rounding code) that the maximum message (data)
- // size is a multiple of the alignment.
- DCHECK_EQ(max_message_num_bytes % kMessageAlignment, 0U)
- << "GetConfiguration().max_message_num_bytes not a multiple of alignment";
-
- // Note: This also implies a check on the |main_buffer_size()|, which is just
- // |RoundUpMessageAlignment(sizeof(Header) + num_bytes())|.
- if (num_bytes() > max_message_num_bytes) {
- *error_message = "Message data payload too large";
- return false;
- }
-
- if (transport_data_buffer_size() > 0) {
- const char* e = TransportData::ValidateBuffer(
- serialized_platform_handle_size, transport_data_buffer(),
- transport_data_buffer_size());
- if (e) {
- *error_message = e;
- return false;
- }
- }
-
- return true;
-}
-
-MessageInTransit::MessageInTransit(Type type,
- Subtype subtype,
- uint32_t num_bytes,
- const void* bytes)
- : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
- main_buffer_(static_cast<char*>(
- base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
- ConstructorHelper(type, subtype, num_bytes);
- if (bytes) {
- memcpy(MessageInTransit::bytes(), bytes, num_bytes);
- memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0,
- main_buffer_size_ - sizeof(Header) - num_bytes);
- } else {
- memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header));
- }
-}
-
-MessageInTransit::MessageInTransit(Type type,
- Subtype subtype,
- uint32_t num_bytes,
- UserPointer<const void> bytes)
- : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
- main_buffer_(static_cast<char*>(
- base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
- ConstructorHelper(type, subtype, num_bytes);
- bytes.GetArray(MessageInTransit::bytes(), num_bytes);
- memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0,
- main_buffer_size_ - sizeof(Header) - num_bytes);
-}
-
-MessageInTransit::MessageInTransit(const View& message_view)
- : main_buffer_size_(message_view.main_buffer_size()),
- main_buffer_(static_cast<char*>(
- base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
- DCHECK_GE(main_buffer_size_, sizeof(Header));
- DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
-
- memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_);
- DCHECK_EQ(main_buffer_size_,
- RoundUpMessageAlignment(sizeof(Header) + num_bytes()));
-}
-
-MessageInTransit::~MessageInTransit() {
- if (dispatchers_) {
- for (size_t i = 0; i < dispatchers_->size(); i++) {
- if (!(*dispatchers_)[i])
- continue;
-
- DCHECK((*dispatchers_)[i]->HasOneRef());
- (*dispatchers_)[i]->Close();
- }
- }
-}
-
-// static
-bool MessageInTransit::GetNextMessageSize(const void* buffer,
- size_t buffer_size,
- size_t* next_message_size) {
- DCHECK(next_message_size);
- if (!buffer_size)
- return false;
- DCHECK(buffer);
- DCHECK_EQ(
- reinterpret_cast<uintptr_t>(buffer) % MessageInTransit::kMessageAlignment,
- 0u);
-
- if (buffer_size < sizeof(Header))
- return false;
-
- const Header* header = static_cast<const Header*>(buffer);
- *next_message_size = header->total_size;
- DCHECK_EQ(*next_message_size % kMessageAlignment, 0u);
- return true;
-}
-
-void MessageInTransit::SetDispatchers(
- scoped_ptr<DispatcherVector> dispatchers) {
- DCHECK(dispatchers);
- DCHECK(!dispatchers_);
- DCHECK(!transport_data_);
-
- dispatchers_ = dispatchers.Pass();
-#ifndef NDEBUG
- for (size_t i = 0; i < dispatchers_->size(); i++)
- DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef());
-#endif
-}
-
-void MessageInTransit::SetTransportData(
- scoped_ptr<TransportData> transport_data) {
- DCHECK(transport_data);
- DCHECK(!transport_data_);
- DCHECK(!dispatchers_);
-
- transport_data_ = transport_data.Pass();
- UpdateTotalSize();
-}
-
-void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
- DCHECK(channel);
- DCHECK(!transport_data_);
-
- if (!dispatchers_ || !dispatchers_->size())
- return;
-
- transport_data_.reset(new TransportData(dispatchers_.Pass(), channel));
-
- // Update the sizes in the message header.
- UpdateTotalSize();
-}
-
-void MessageInTransit::ConstructorHelper(Type type,
- Subtype subtype,
- uint32_t num_bytes) {
- DCHECK_LE(num_bytes, GetConfiguration().max_message_num_bytes);
-
- // |total_size| is updated below, from the other values.
- header()->type = type;
- header()->subtype = subtype;
- header()->source_id = ChannelEndpointId();
- header()->destination_id = ChannelEndpointId();
- header()->num_bytes = num_bytes;
- header()->unused = 0;
- // Note: If dispatchers are subsequently attached, then |total_size| will have
- // to be adjusted.
- UpdateTotalSize();
-}
-
-void MessageInTransit::UpdateTotalSize() {
- DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
- header()->total_size = static_cast<uint32_t>(main_buffer_size_);
- if (transport_data_) {
- header()->total_size +=
- static_cast<uint32_t>(transport_data_->buffer_size());
- }
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h
deleted file mode 100644
index 023362a..0000000
--- a/mojo/edk/system/message_in_transit.h
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class Channel;
-class TransportData;
-
-// This class is used to represent data in transit. It is thread-unsafe.
-//
-// |MessageInTransit| buffers:
-//
-// A |MessageInTransit| can be serialized by writing the main buffer and then,
-// if it has one, the transport data buffer. Both buffers are
-// |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
-// in size.
-//
-// The main buffer consists of the header (of type |Header|, which is an
-// internal detail of this class) followed immediately by the message data
-// (accessed by |bytes()| and of size |num_bytes()|, and also
-// |kMessageAlignment|-byte aligned), and then any padding needed to make the
-// main buffer a multiple of |kMessageAlignment| bytes in size.
-//
-// See |TransportData| for a description of the (serialized) transport data
-// buffer.
-class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
- public:
- typedef uint16_t Type;
- // Messages that are forwarded to endpoints.
- static const Type kTypeEndpoint = 0;
- // Messages that are consumed by the |Channel|.
- static const Type kTypeChannel = 1;
- // Messages that are consumed by the |RawChannel| (implementation).
- static const Type kTypeRawChannel = 2;
-
- typedef uint16_t Subtype;
- // Subtypes for type |kTypeEndpoint|:
- static const Subtype kSubtypeEndpointData = 0;
- // Subtypes for type |kTypeChannel|:
- static const Subtype kSubtypeChannelAttachAndRunEndpoint = 0;
- static const Subtype kSubtypeChannelRemoveEndpoint = 1;
- static const Subtype kSubtypeChannelRemoveEndpointAck = 2;
-
- // Subtypes for type |kTypeRawChannel|:
- static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0;
-
- // Messages (the header and data) must always be aligned to a multiple of this
- // quantity (which must be a power of 2).
- static const size_t kMessageAlignment = 8;
-
- // Forward-declare |Header| so that |View| can use it:
- private:
- struct Header;
-
- public:
- // This represents a view of serialized message data in a raw buffer.
- class MOJO_SYSTEM_IMPL_EXPORT View {
- public:
- // Constructs a view from the given buffer of the given size. (The size must
- // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
- // must remain alive/unmodified through the lifetime of this object.
- // |buffer| should be |kMessageAlignment|-byte aligned.
- View(size_t message_size, const void* buffer);
-
- // Checks that the given |View| appears to be for a valid message, within
- // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
- // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
- // transport data -- see |TransportData::ValidateBuffer()|).
- //
- // It returns true (and leaves |error_message| alone) if this object appears
- // to be a valid message (according to the above) and false, pointing
- // |*error_message| to a suitable error message, if not.
- bool IsValid(size_t serialized_platform_handle_size,
- const char** error_message) const;
-
- // API parallel to that for |MessageInTransit| itself (mostly getters for
- // header data).
- const void* main_buffer() const { return buffer_; }
- size_t main_buffer_size() const {
- return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
- }
- const void* transport_data_buffer() const {
- return (total_size() > main_buffer_size())
- ? static_cast<const char*>(buffer_) + main_buffer_size()
- : nullptr;
- }
- size_t transport_data_buffer_size() const {
- return total_size() - main_buffer_size();
- }
- size_t total_size() const { return header()->total_size; }
- uint32_t num_bytes() const { return header()->num_bytes; }
- const void* bytes() const {
- return static_cast<const char*>(buffer_) + sizeof(Header);
- }
- Type type() const { return header()->type; }
- Subtype subtype() const { return header()->subtype; }
- ChannelEndpointId source_id() const { return header()->source_id; }
- ChannelEndpointId destination_id() const {
- return header()->destination_id;
- }
-
- private:
- const Header* header() const { return static_cast<const Header*>(buffer_); }
-
- const void* const buffer_;
-
- // Though this struct is trivial, disallow copy and assign, since it doesn't
- // own its data. (If you're copying/assigning this, you're probably doing
- // something wrong.)
- DISALLOW_COPY_AND_ASSIGN(View);
- };
-
- // |bytes| is optional; if null, the message data will be zero-initialized.
- MessageInTransit(Type type,
- Subtype subtype,
- uint32_t num_bytes,
- const void* bytes);
- // |bytes| should be valid (and non-null), unless |num_bytes| is zero.
- MessageInTransit(Type type,
- Subtype subtype,
- uint32_t num_bytes,
- UserPointer<const void> bytes);
- // Constructs a |MessageInTransit| from a |View|.
- explicit MessageInTransit(const View& message_view);
-
- ~MessageInTransit();
-
- // Gets the size of the next message from |buffer|, which has |buffer_size|
- // bytes currently available, returning true and setting |*next_message_size|
- // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
- // (and on success, |*next_message_size| will be a multiple of
- // |kMessageAlignment|).
- // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently
- // satisified on a faith-based basis.
- static bool GetNextMessageSize(const void* buffer,
- size_t buffer_size,
- size_t* next_message_size);
-
- // Makes this message "own" the given set of dispatchers. The dispatchers must
- // not be referenced from anywhere else (in particular, not from the handle
- // table), i.e., each dispatcher must have a reference count of 1. This
- // message must not already have dispatchers.
- void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers);
-
- // Sets the |TransportData| for this message. This should only be done when
- // there are no dispatchers and no existing |TransportData|.
- void SetTransportData(scoped_ptr<TransportData> transport_data);
-
- // Serializes any dispatchers to the secondary buffer. This message must not
- // already have a secondary buffer (so this must only be called once). The
- // caller must ensure (e.g., by holding on to a reference) that |channel|
- // stays alive through the call.
- void SerializeAndCloseDispatchers(Channel* channel);
-
- // Gets the main buffer and its size (in number of bytes), respectively.
- const void* main_buffer() const { return main_buffer_.get(); }
- size_t main_buffer_size() const { return main_buffer_size_; }
-
- // Gets the transport data buffer (if any).
- const TransportData* transport_data() const { return transport_data_.get(); }
- TransportData* transport_data() { return transport_data_.get(); }
-
- // Gets the total size of the message (see comment in |Header|, below).
- size_t total_size() const { return header()->total_size; }
-
- // Gets the size of the message data.
- uint32_t num_bytes() const { return header()->num_bytes; }
-
- // Gets the message data (of size |num_bytes()| bytes).
- const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
- void* bytes() { return main_buffer_.get() + sizeof(Header); }
-
- Type type() const { return header()->type; }
- Subtype subtype() const { return header()->subtype; }
- ChannelEndpointId source_id() const { return header()->source_id; }
- ChannelEndpointId destination_id() const { return header()->destination_id; }
-
- void set_source_id(ChannelEndpointId source_id) {
- header()->source_id = source_id;
- }
- void set_destination_id(ChannelEndpointId destination_id) {
- header()->destination_id = destination_id;
- }
-
- // Gets the dispatchers attached to this message; this may return null if
- // there are none. Note that the caller may mutate the set of dispatchers
- // (e.g., take ownership of all the dispatchers, leaving the vector empty).
- DispatcherVector* dispatchers() { return dispatchers_.get(); }
-
- // Returns true if this message has dispatchers attached.
- bool has_dispatchers() const {
- return dispatchers_ && !dispatchers_->empty();
- }
-
- // Rounds |n| up to a multiple of |kMessageAlignment|.
- static inline size_t RoundUpMessageAlignment(size_t n) {
- return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1);
- }
-
- private:
- // To allow us to make compile-assertions about |Header| in the .cc file.
- struct PrivateStructForCompileAsserts;
-
- // Header for the data (main buffer). Must be a multiple of
- // |kMessageAlignment| bytes in size. Must be POD.
- struct Header {
- // Total size of the message, including the header, the message data
- // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
- // bytes), and serialized handle information. Note that this may not be the
- // correct value if dispatchers are attached but
- // |SerializeAndCloseDispatchers()| has not been called.
- uint32_t total_size;
- Type type; // 2 bytes.
- Subtype subtype; // 2 bytes.
- ChannelEndpointId source_id; // 4 bytes.
- ChannelEndpointId destination_id; // 4 bytes.
- // Size of actual message data.
- uint32_t num_bytes;
- uint32_t unused;
- };
-
- const Header* header() const {
- return reinterpret_cast<const Header*>(main_buffer_.get());
- }
- Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
-
- void ConstructorHelper(Type type, Subtype subtype, uint32_t num_bytes);
- void UpdateTotalSize();
-
- const size_t main_buffer_size_;
- const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_; // Never null.
-
- scoped_ptr<TransportData> transport_data_; // May be null.
-
- // Any dispatchers that may be attached to this message. These dispatchers
- // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
- // allow a dispatcher entry to be null, in case it couldn't be duplicated for
- // some reason.)
- scoped_ptr<DispatcherVector> dispatchers_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_H_
diff --git a/mojo/edk/system/message_in_transit_queue.cc b/mojo/edk/system/message_in_transit_queue.cc
deleted file mode 100644
index ab5195e..0000000
--- a/mojo/edk/system/message_in_transit_queue.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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/message_in_transit_queue.h"
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-
-namespace mojo {
-namespace system {
-
-MessageInTransitQueue::MessageInTransitQueue() {
-}
-
-MessageInTransitQueue::~MessageInTransitQueue() {
- if (!IsEmpty()) {
- LOG(WARNING) << "Destroying nonempty message queue";
- Clear();
- }
-}
-
-void MessageInTransitQueue::Clear() {
- STLDeleteElements(&queue_);
-}
-
-void MessageInTransitQueue::Swap(MessageInTransitQueue* other) {
- queue_.swap(other->queue_);
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_in_transit_queue.h b/mojo/edk/system/message_in_transit_queue.h
deleted file mode 100644
index d81bd2b..0000000
--- a/mojo/edk/system/message_in_transit_queue.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_
-
-#include <deque>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// A simple queue for |MessageInTransit|s (that owns its messages).
-// This class is not thread-safe.
-// TODO(vtl): Write tests.
-class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue {
- public:
- MessageInTransitQueue();
- ~MessageInTransitQueue();
-
- bool IsEmpty() const { return queue_.empty(); }
-
- void AddMessage(scoped_ptr<MessageInTransit> message) {
- queue_.push_back(message.release());
- }
-
- scoped_ptr<MessageInTransit> GetMessage() {
- MessageInTransit* rv = queue_.front();
- queue_.pop_front();
- return make_scoped_ptr(rv);
- }
-
- MessageInTransit* PeekMessage() { return queue_.front(); }
-
- void DiscardMessage() {
- delete queue_.front();
- queue_.pop_front();
- }
-
- void Clear();
-
- // Efficiently swaps contents with |*other|.
- void Swap(MessageInTransitQueue* other);
-
- private:
- // TODO(vtl): When C++11 is available, switch this to a deque of
- // |scoped_ptr|/|unique_ptr|s.
- std::deque<MessageInTransit*> queue_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageInTransitQueue);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_
diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc
deleted file mode 100644
index 554401e..0000000
--- a/mojo/edk/system/message_pipe.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright 2013 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/message_pipe.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/incoming_endpoint.h"
-#include "mojo/edk/system/local_message_pipe_endpoint.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/message_pipe_endpoint.h"
-#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
-
-namespace mojo {
-namespace system {
-
-// static
-MessagePipe* MessagePipe::CreateLocalLocal() {
- MessagePipe* message_pipe = new MessagePipe();
- message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint());
- message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint());
- return message_pipe;
-}
-
-// static
-MessagePipe* MessagePipe::CreateLocalProxy(
- scoped_refptr<ChannelEndpoint>* channel_endpoint) {
- DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely.
- MessagePipe* message_pipe = new MessagePipe();
- message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint());
- *channel_endpoint = new ChannelEndpoint(message_pipe, 1);
- message_pipe->endpoints_[1].reset(
- new ProxyMessagePipeEndpoint(channel_endpoint->get()));
- return message_pipe;
-}
-
-// static
-MessagePipe* MessagePipe::CreateLocalProxyFromExisting(
- MessageInTransitQueue* message_queue,
- ChannelEndpoint* channel_endpoint) {
- DCHECK(message_queue);
- MessagePipe* message_pipe = new MessagePipe();
- message_pipe->endpoints_[0].reset(
- new LocalMessagePipeEndpoint(message_queue));
- if (channel_endpoint) {
- bool attached_to_channel = channel_endpoint->ReplaceClient(message_pipe, 1);
- message_pipe->endpoints_[1].reset(
- new ProxyMessagePipeEndpoint(channel_endpoint));
- if (!attached_to_channel)
- message_pipe->OnDetachFromChannel(1);
- } else {
- // This means that the proxy side was already closed; we only need to inform
- // the local side of this.
- // TODO(vtl): This is safe to do without locking (but perhaps slightly
- // dubious), since no other thread has access to |message_pipe| yet.
- message_pipe->endpoints_[0]->OnPeerClose();
- }
- return message_pipe;
-}
-
-// static
-MessagePipe* MessagePipe::CreateProxyLocal(
- scoped_refptr<ChannelEndpoint>* channel_endpoint) {
- DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely.
- MessagePipe* message_pipe = new MessagePipe();
- *channel_endpoint = new ChannelEndpoint(message_pipe, 0);
- message_pipe->endpoints_[0].reset(
- new ProxyMessagePipeEndpoint(channel_endpoint->get()));
- message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint());
- return message_pipe;
-}
-
-// static
-unsigned MessagePipe::GetPeerPort(unsigned port) {
- DCHECK(port == 0 || port == 1);
- return port ^ 1;
-}
-
-// static
-bool MessagePipe::Deserialize(Channel* channel,
- const void* source,
- size_t size,
- scoped_refptr<MessagePipe>* message_pipe,
- unsigned* port) {
- DCHECK(!*message_pipe); // Not technically wrong, but unlikely.
-
- if (size != channel->GetSerializedEndpointSize()) {
- LOG(ERROR) << "Invalid serialized message pipe";
- return false;
- }
-
- scoped_refptr<IncomingEndpoint> incoming_endpoint =
- channel->DeserializeEndpoint(source);
- if (!incoming_endpoint)
- return false;
-
- *message_pipe = incoming_endpoint->ConvertToMessagePipe();
- DCHECK(*message_pipe);
- *port = 0;
- return true;
-}
-
-MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) {
- DCHECK(port == 0 || port == 1);
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
-
- return endpoints_[port]->GetType();
-}
-
-void MessagePipe::CancelAllAwakables(unsigned port) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
- endpoints_[port]->CancelAllAwakables();
-}
-
-void MessagePipe::Close(unsigned port) {
- DCHECK(port == 0 || port == 1);
-
- unsigned peer_port = GetPeerPort(port);
-
- base::AutoLock locker(lock_);
- // The endpoint's |OnPeerClose()| may have been called first and returned
- // false, which would have resulted in its destruction.
- if (!endpoints_[port])
- return;
-
- endpoints_[port]->Close();
- if (endpoints_[peer_port]) {
- if (!endpoints_[peer_port]->OnPeerClose())
- endpoints_[peer_port].reset();
- }
- endpoints_[port].reset();
-}
-
-// TODO(vtl): Handle flags.
-MojoResult MessagePipe::WriteMessage(
- unsigned port,
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- return EnqueueMessageNoLock(
- GetPeerPort(port),
- make_scoped_ptr(new MessageInTransit(
- MessageInTransit::kTypeEndpoint,
- MessageInTransit::kSubtypeEndpointData, num_bytes, bytes)),
- transports);
-}
-
-MojoResult MessagePipe::ReadMessage(unsigned port,
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
-
- return endpoints_[port]->ReadMessage(bytes, num_bytes, dispatchers,
- num_dispatchers, flags);
-}
-
-HandleSignalsState MessagePipe::GetHandleSignalsState(unsigned port) const {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(const_cast<base::Lock&>(lock_));
- DCHECK(endpoints_[port]);
-
- return endpoints_[port]->GetHandleSignalsState();
-}
-
-MojoResult MessagePipe::AddAwakable(unsigned port,
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
-
- return endpoints_[port]->AddAwakable(awakable, signals, context,
- signals_state);
-}
-
-void MessagePipe::RemoveAwakable(unsigned port,
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
-
- endpoints_[port]->RemoveAwakable(awakable, signals_state);
-}
-
-void MessagePipe::StartSerialize(unsigned /*port*/,
- Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) {
- *max_size = channel->GetSerializedEndpointSize();
- *max_platform_handles = 0;
-}
-
-bool MessagePipe::EndSerialize(
- unsigned port,
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* /*platform_handles*/) {
- DCHECK(port == 0 || port == 1);
-
- base::AutoLock locker(lock_);
- DCHECK(endpoints_[port]);
-
- // The port being serialized must be local.
- DCHECK_EQ(endpoints_[port]->GetType(), MessagePipeEndpoint::kTypeLocal);
-
- unsigned peer_port = GetPeerPort(port);
- MessageInTransitQueue* message_queue =
- static_cast<LocalMessagePipeEndpoint*>(endpoints_[port].get())
- ->message_queue();
- // The replacement for |endpoints_[port]|, if any.
- MessagePipeEndpoint* replacement_endpoint = nullptr;
-
- // The three cases below correspond to the ones described above
- // |Channel::SerializeEndpoint...()| (in channel.h).
- if (!endpoints_[peer_port]) {
- // Case 1: (known-)closed peer port. There's no reason for us to continue to
- // exist afterwards.
- channel->SerializeEndpointWithClosedPeer(destination, message_queue);
- } else if (endpoints_[peer_port]->GetType() ==
- MessagePipeEndpoint::kTypeLocal) {
- // Case 2: local peer port. We replace |port|'s |LocalMessagePipeEndpoint|
- // with a |ProxyMessagePipeEndpoint| hooked up to the |ChannelEndpoint| that
- // the |Channel| returns to us.
- scoped_refptr<ChannelEndpoint> channel_endpoint =
- channel->SerializeEndpointWithLocalPeer(destination, message_queue,
- this, port);
- replacement_endpoint = new ProxyMessagePipeEndpoint(channel_endpoint.get());
- } else {
- // Case 3: remote peer port. We get the |peer_port|'s |ChannelEndpoint| and
- // pass it to the |Channel|. There's no reason for us to continue to exist
- // afterwards.
- DCHECK_EQ(endpoints_[peer_port]->GetType(),
- MessagePipeEndpoint::kTypeProxy);
- ProxyMessagePipeEndpoint* peer_endpoint =
- static_cast<ProxyMessagePipeEndpoint*>(endpoints_[peer_port].get());
- scoped_refptr<ChannelEndpoint> peer_channel_endpoint =
- peer_endpoint->ReleaseChannelEndpoint();
- channel->SerializeEndpointWithRemotePeer(destination, message_queue,
- peer_channel_endpoint);
- // No need to call |Close()| after |ReleaseChannelEndpoint()|.
- endpoints_[peer_port].reset();
- }
-
- endpoints_[port]->Close();
- endpoints_[port].reset(replacement_endpoint);
-
- *actual_size = channel->GetSerializedEndpointSize();
- return true;
-}
-
-bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) {
- base::AutoLock locker(lock_);
-
- if (!endpoints_[port]) {
- // This will happen only on the rare occasion that the call to
- // |OnReadMessage()| is racing with us calling
- // |ChannelEndpoint::ReplaceClient()|, in which case we reject the message,
- // and the |ChannelEndpoint| can retry (calling the new client's
- // |OnReadMessage()|).
- return false;
- }
-
- // This is called when the |ChannelEndpoint| for the
- // |ProxyMessagePipeEndpoint| |port| receives a message (from the |Channel|).
- // We need to pass this message on to its peer port (typically a
- // |LocalMessagePipeEndpoint|).
- MojoResult result = EnqueueMessageNoLock(GetPeerPort(port),
- make_scoped_ptr(message), nullptr);
- DLOG_IF(WARNING, result != MOJO_RESULT_OK)
- << "EnqueueMessageNoLock() failed (result = " << result << ")";
- return true;
-}
-
-void MessagePipe::OnDetachFromChannel(unsigned port) {
- Close(port);
-}
-
-MessagePipe::MessagePipe() {
-}
-
-MessagePipe::~MessagePipe() {
- // Owned by the dispatchers. The owning dispatchers should only release us via
- // their |Close()| method, which should inform us of being closed via our
- // |Close()|. Thus these should already be null.
- DCHECK(!endpoints_[0]);
- DCHECK(!endpoints_[1]);
-}
-
-MojoResult MessagePipe::EnqueueMessageNoLock(
- unsigned port,
- scoped_ptr<MessageInTransit> message,
- std::vector<DispatcherTransport>* transports) {
- DCHECK(port == 0 || port == 1);
- DCHECK(message);
-
- DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpoint);
- DCHECK(endpoints_[GetPeerPort(port)]);
-
- // The destination port need not be open, unlike the source port.
- if (!endpoints_[port])
- return MOJO_RESULT_FAILED_PRECONDITION;
-
- if (transports) {
- MojoResult result = AttachTransportsNoLock(port, message.get(), transports);
- if (result != MOJO_RESULT_OK)
- return result;
- }
-
- // The endpoint's |EnqueueMessage()| may not report failure.
- endpoints_[port]->EnqueueMessage(message.Pass());
- return MOJO_RESULT_OK;
-}
-
-MojoResult MessagePipe::AttachTransportsNoLock(
- unsigned port,
- MessageInTransit* message,
- std::vector<DispatcherTransport>* transports) {
- DCHECK(!message->has_dispatchers());
-
- // You're not allowed to send either handle to a message pipe over the message
- // pipe, so check for this. (The case of trying to write a handle to itself is
- // taken care of by |Core|. That case kind of makes sense, but leads to
- // complications if, e.g., both sides try to do the same thing with their
- // respective handles simultaneously. The other case, of trying to write the
- // peer handle to a handle, doesn't make sense -- since no handle will be
- // available to read the message from.)
- for (size_t i = 0; i < transports->size(); i++) {
- if (!(*transports)[i].is_valid())
- continue;
- if ((*transports)[i].GetType() == Dispatcher::kTypeMessagePipe) {
- MessagePipeDispatcherTransport mp_transport((*transports)[i]);
- if (mp_transport.GetMessagePipe() == this) {
- // The other case should have been disallowed by |Core|. (Note: |port|
- // is the peer port of the handle given to |WriteMessage()|.)
- DCHECK_EQ(mp_transport.GetPort(), port);
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
- }
- }
-
- // Clone the dispatchers and attach them to the message. (This must be done as
- // a separate loop, since we want to leave the dispatchers alone on failure.)
- scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector());
- dispatchers->reserve(transports->size());
- for (size_t i = 0; i < transports->size(); i++) {
- if ((*transports)[i].is_valid()) {
- dispatchers->push_back(
- (*transports)[i].CreateEquivalentDispatcherAndClose());
- } else {
- LOG(WARNING) << "Enqueueing null dispatcher";
- dispatchers->push_back(nullptr);
- }
- }
- message->SetDispatchers(dispatchers.Pass());
- return MOJO_RESULT_OK;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe.h b/mojo/edk/system/message_pipe.h
deleted file mode 100644
index df05014..0000000
--- a/mojo/edk/system/message_pipe.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_MESSAGE_PIPE_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/system/channel_endpoint_client.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/message_pipe_endpoint.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/message_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-class Awakable;
-class Channel;
-class ChannelEndpoint;
-class MessageInTransitQueue;
-
-// |MessagePipe| is the secondary object implementing a message pipe (see the
-// explanatory comment in core.cc). It is typically owned by the dispatcher(s)
-// corresponding to the local endpoints. This class is thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient {
- public:
- // Creates a |MessagePipe| with two new |LocalMessagePipeEndpoint|s.
- static MessagePipe* CreateLocalLocal();
-
- // Creates a |MessagePipe| with a |LocalMessagePipeEndpoint| on port 0 and a
- // |ProxyMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the
- // (newly-created) |ChannelEndpoint| for the latter.
- static MessagePipe* CreateLocalProxy(
- scoped_refptr<ChannelEndpoint>* channel_endpoint);
-
- // Similar to |CreateLocalProxy()|, except that it'll do so from an existing
- // |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and take
- // |message_queue|'s contents as already-received incoming messages. If
- // |channel_endpoint| is null, this will create a "half-open" message pipe.
- static MessagePipe* CreateLocalProxyFromExisting(
- MessageInTransitQueue* message_queue,
- ChannelEndpoint* channel_endpoint);
-
- // Creates a |MessagePipe| with a |ProxyMessagePipeEndpoint| on port 0 and a
- // |LocalMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the
- // (newly-created) |ChannelEndpoint| for the former.
- // Note: This is really only needed in tests (outside of tests, this
- // configuration arises from a local message pipe having its port 0
- // "converted" using |ConvertLocalToProxy()|).
- static MessagePipe* CreateProxyLocal(
- scoped_refptr<ChannelEndpoint>* channel_endpoint);
-
- // Gets the other port number (i.e., 0 -> 1, 1 -> 0).
- static unsigned GetPeerPort(unsigned port);
-
- // Used by |MessagePipeDispatcher::Deserialize()|. Returns true on success (in
- // which case, |*message_pipe|/|*port| are set appropriately) and false on
- // failure (in which case |*message_pipe| may or may not be set to null).
- static bool Deserialize(Channel* channel,
- const void* source,
- size_t size,
- scoped_refptr<MessagePipe>* message_pipe,
- unsigned* port);
-
- // Gets the type of the endpoint (used for assertions, etc.).
- MessagePipeEndpoint::Type GetType(unsigned port);
-
- // These are called by the dispatcher to implement its methods of
- // corresponding names. In all cases, the port |port| must be open.
- void CancelAllAwakables(unsigned port);
- void Close(unsigned port);
- // Unlike |MessagePipeDispatcher::WriteMessage()|, this does not validate its
- // arguments.
- MojoResult WriteMessage(unsigned port,
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags);
- MojoResult ReadMessage(unsigned port,
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags);
- HandleSignalsState GetHandleSignalsState(unsigned port) const;
- MojoResult AddAwakable(unsigned port,
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- void RemoveAwakable(unsigned port,
- Awakable* awakable,
- HandleSignalsState* signals_state);
- void StartSerialize(unsigned port,
- Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles);
- bool EndSerialize(unsigned port,
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles);
-
- // |ChannelEndpointClient| methods:
- bool OnReadMessage(unsigned port, MessageInTransit* message) override;
- void OnDetachFromChannel(unsigned port) override;
-
- private:
- MessagePipe();
- ~MessagePipe() override;
-
- // This is used internally by |WriteMessage()| and by |OnReadMessage()|.
- // |transports| may be non-null only if it's nonempty and |message| has no
- // dispatchers attached. Must be called with |lock_| held.
- MojoResult EnqueueMessageNoLock(unsigned port,
- scoped_ptr<MessageInTransit> message,
- std::vector<DispatcherTransport>* transports);
-
- // Helper for |EnqueueMessageNoLock()|. Must be called with |lock_| held.
- MojoResult AttachTransportsNoLock(
- unsigned port,
- MessageInTransit* message,
- std::vector<DispatcherTransport>* transports);
-
- base::Lock lock_; // Protects the following members.
- scoped_ptr<MessagePipeEndpoint> endpoints_[2];
-
- DISALLOW_COPY_AND_ASSIGN(MessagePipe);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_H_
diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc
deleted file mode 100644
index a6733dbe..0000000
--- a/mojo/edk/system/message_pipe_dispatcher.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2013 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/message_pipe_dispatcher.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/local_message_pipe_endpoint.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/options_validation.h"
-#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
-
-namespace mojo {
-namespace system {
-
-const unsigned kInvalidPort = static_cast<unsigned>(-1);
-
-// MessagePipeDispatcher -------------------------------------------------------
-
-// static
-const MojoCreateMessagePipeOptions
- MessagePipeDispatcher::kDefaultCreateOptions = {
- static_cast<uint32_t>(sizeof(MojoCreateMessagePipeOptions)),
- MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE};
-
-MessagePipeDispatcher::MessagePipeDispatcher(
- const MojoCreateMessagePipeOptions& /*validated_options*/)
- : port_(kInvalidPort) {
-}
-
-// static
-MojoResult MessagePipeDispatcher::ValidateCreateOptions(
- UserPointer<const MojoCreateMessagePipeOptions> in_options,
- MojoCreateMessagePipeOptions* out_options) {
- const MojoCreateMessagePipeOptionsFlags kKnownFlags =
- MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE;
-
- *out_options = kDefaultCreateOptions;
- if (in_options.IsNull())
- return MOJO_RESULT_OK;
-
- UserOptionsReader<MojoCreateMessagePipeOptions> reader(in_options);
- if (!reader.is_valid())
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateMessagePipeOptions, 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 MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe,
- unsigned port) {
- DCHECK(message_pipe);
- DCHECK(port == 0 || port == 1);
-
- message_pipe_ = message_pipe;
- port_ = port;
-}
-
-Dispatcher::Type MessagePipeDispatcher::GetType() const {
- return kTypeMessagePipe;
-}
-
-// static
-scoped_refptr<MessagePipeDispatcher>
-MessagePipeDispatcher::CreateRemoteMessagePipe(
- scoped_refptr<ChannelEndpoint>* channel_endpoint) {
- scoped_refptr<MessagePipe> message_pipe(
- MessagePipe::CreateLocalProxy(channel_endpoint));
- scoped_refptr<MessagePipeDispatcher> dispatcher(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- dispatcher->Init(message_pipe, 0);
- return dispatcher;
-}
-
-// static
-scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize(
- Channel* channel,
- const void* source,
- size_t size) {
- unsigned port = kInvalidPort;
- scoped_refptr<MessagePipe> message_pipe;
- if (!MessagePipe::Deserialize(channel, source, size, &message_pipe, &port))
- return nullptr;
- DCHECK(message_pipe);
- DCHECK(port == 0 || port == 1);
-
- scoped_refptr<MessagePipeDispatcher> dispatcher(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- dispatcher->Init(message_pipe, port);
- return dispatcher;
-}
-
-MessagePipeDispatcher::~MessagePipeDispatcher() {
- // |Close()|/|CloseImplNoLock()| should have taken care of the pipe.
- DCHECK(!message_pipe_);
-}
-
-MessagePipe* MessagePipeDispatcher::GetMessagePipeNoLock() const {
- lock().AssertAcquired();
- return message_pipe_.get();
-}
-
-unsigned MessagePipeDispatcher::GetPortNoLock() const {
- lock().AssertAcquired();
- return port_;
-}
-
-void MessagePipeDispatcher::CancelAllAwakablesNoLock() {
- lock().AssertAcquired();
- message_pipe_->CancelAllAwakables(port_);
-}
-
-void MessagePipeDispatcher::CloseImplNoLock() {
- lock().AssertAcquired();
- message_pipe_->Close(port_);
- message_pipe_ = nullptr;
- port_ = kInvalidPort;
-}
-
-scoped_refptr<Dispatcher>
-MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
- lock().AssertAcquired();
-
- // TODO(vtl): Currently, there are no options, so we just use
- // |kDefaultCreateOptions|. Eventually, we'll have to duplicate the options
- // too.
- scoped_refptr<MessagePipeDispatcher> rv =
- new MessagePipeDispatcher(kDefaultCreateOptions);
- rv->Init(message_pipe_, port_);
- message_pipe_ = nullptr;
- port_ = kInvalidPort;
- return scoped_refptr<Dispatcher>(rv.get());
-}
-
-MojoResult MessagePipeDispatcher::WriteMessageImplNoLock(
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags) {
- DCHECK(!transports ||
- (transports->size() > 0 &&
- transports->size() <= GetConfiguration().max_message_num_handles));
-
- lock().AssertAcquired();
-
- if (num_bytes > GetConfiguration().max_message_num_bytes)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- return message_pipe_->WriteMessage(port_, bytes, num_bytes, transports,
- flags);
-}
-
-MojoResult MessagePipeDispatcher::ReadMessageImplNoLock(
- UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) {
- lock().AssertAcquired();
- return message_pipe_->ReadMessage(port_, bytes, num_bytes, dispatchers,
- num_dispatchers, flags);
-}
-
-HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateImplNoLock()
- const {
- lock().AssertAcquired();
- return message_pipe_->GetHandleSignalsState(port_);
-}
-
-MojoResult MessagePipeDispatcher::AddAwakableImplNoLock(
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- return message_pipe_->AddAwakable(port_, awakable, signals, context,
- signals_state);
-}
-
-void MessagePipeDispatcher::RemoveAwakableImplNoLock(
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- message_pipe_->RemoveAwakable(port_, awakable, signals_state);
-}
-
-void MessagePipeDispatcher::StartSerializeImplNoLock(
- Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) {
- DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
- return message_pipe_->StartSerialize(port_, channel, max_size,
- max_platform_handles);
-}
-
-bool MessagePipeDispatcher::EndSerializeAndCloseImplNoLock(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) {
- DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
-
- bool rv = message_pipe_->EndSerialize(port_, channel, destination,
- actual_size, platform_handles);
- message_pipe_ = nullptr;
- port_ = kInvalidPort;
- return rv;
-}
-
-// MessagePipeDispatcherTransport ----------------------------------------------
-
-MessagePipeDispatcherTransport::MessagePipeDispatcherTransport(
- DispatcherTransport transport)
- : DispatcherTransport(transport) {
- DCHECK_EQ(message_pipe_dispatcher()->GetType(), Dispatcher::kTypeMessagePipe);
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h
deleted file mode 100644
index fb16dd3..0000000
--- a/mojo/edk/system/message_pipe_dispatcher.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class ChannelEndpoint;
-class MessagePipe;
-class MessagePipeDispatcherTransport;
-
-// This is the |Dispatcher| implementation for message pipes (created by the
-// Mojo primitive |MojoCreateMessagePipe()|). This class is thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher : public Dispatcher {
- public:
- // The default options to use for |MojoCreateMessagePipe()|. (Real uses
- // should obtain this via |ValidateCreateOptions()| with a null |in_options|;
- // this is exposed directly for testing convenience.)
- static const MojoCreateMessagePipeOptions kDefaultCreateOptions;
-
- MessagePipeDispatcher(
- const MojoCreateMessagePipeOptions& /*validated_options*/);
-
- // Validates and/or sets default options for |MojoCreateMessagePipeOptions|.
- // If non-null, |in_options| must point to a struct of at least
- // |in_options->struct_size| bytes. |out_options| must point to a (current)
- // |MojoCreateMessagePipeOptions| and will be entirely overwritten on success
- // (it may be partly overwritten on failure).
- static MojoResult ValidateCreateOptions(
- UserPointer<const MojoCreateMessagePipeOptions> in_options,
- MojoCreateMessagePipeOptions* out_options);
-
- // Must be called before any other methods. (This method is not thread-safe.)
- void Init(scoped_refptr<MessagePipe> message_pipe, unsigned port);
-
- // |Dispatcher| public methods:
- Type GetType() const override;
-
- // Creates a |MessagePipe| with a local endpoint (at port 0) and a proxy
- // endpoint, and creates/initializes a |MessagePipeDispatcher| (attached to
- // the message pipe, port 0).
- // TODO(vtl): This currently uses |kDefaultCreateOptions|, which is okay since
- // there aren't any options, but eventually options should be plumbed through.
- static scoped_refptr<MessagePipeDispatcher> CreateRemoteMessagePipe(
- scoped_refptr<ChannelEndpoint>* channel_endpoint);
-
- // The "opposite" of |SerializeAndClose()|. (Typically this is called by
- // |Dispatcher::Deserialize()|.)
- static scoped_refptr<MessagePipeDispatcher> Deserialize(Channel* channel,
- const void* source,
- size_t size);
-
- private:
- friend class MessagePipeDispatcherTransport;
-
- ~MessagePipeDispatcher() override;
-
- // Gets a dumb pointer to |message_pipe_|. This must be called under the
- // |Dispatcher| lock (that it's a dumb pointer is okay since it's under lock).
- // This is needed when sending handles across processes, where nontrivial,
- // invasive work needs to be done.
- MessagePipe* GetMessagePipeNoLock() const;
- // Similarly for the port.
- unsigned GetPortNoLock() const;
-
- // |Dispatcher| protected methods:
- void CancelAllAwakablesNoLock() override;
- void CloseImplNoLock() override;
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
- MojoResult WriteMessageImplNoLock(
- UserPointer<const void> bytes,
- uint32_t num_bytes,
- std::vector<DispatcherTransport>* transports,
- MojoWriteMessageFlags flags) override;
- MojoResult ReadMessageImplNoLock(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags) override;
- HandleSignalsState GetHandleSignalsStateImplNoLock() const override;
- MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) override;
- void RemoveAwakableImplNoLock(Awakable* awakable,
- HandleSignalsState* signals_state) override;
- void StartSerializeImplNoLock(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) override;
- bool EndSerializeAndCloseImplNoLock(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) override;
-
- // Protected by |lock()|:
- scoped_refptr<MessagePipe> message_pipe_; // This will be null if closed.
- unsigned port_;
-
- DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);
-};
-
-class MessagePipeDispatcherTransport : public DispatcherTransport {
- public:
- explicit MessagePipeDispatcherTransport(DispatcherTransport transport);
-
- MessagePipe* GetMessagePipe() {
- return message_pipe_dispatcher()->GetMessagePipeNoLock();
- }
- unsigned GetPort() { return message_pipe_dispatcher()->GetPortNoLock(); }
-
- private:
- MessagePipeDispatcher* message_pipe_dispatcher() {
- return static_cast<MessagePipeDispatcher*>(dispatcher());
- }
-
- // Copy and assign allowed.
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc
deleted file mode 100644
index b5562b0..0000000
--- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc
+++ /dev/null
@@ -1,691 +0,0 @@
-// Copyright 2013 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.
-
-// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
-// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
-// increase tolerance and reduce observed flakiness (though doing so reduces the
-// meaningfulness of the test).
-
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-
-#include <string.h>
-
-#include <limits>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
-#include "base/rand_util.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/system/waiter_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED;
-
-TEST(MessagePipeDispatcherTest, Basic) {
- test::Stopwatch stopwatch;
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
- for (unsigned i = 0; i < 2; i++) {
- scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- EXPECT_EQ(Dispatcher::kTypeMessagePipe, d0->GetType());
- scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, i); // 0, 1.
- d1->Init(mp, i ^ 1); // 1, 0.
- }
- Waiter w;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Try adding a writable waiter when already writable.
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // Shouldn't need to remove the waiter (it was not added).
-
- // Add a readable waiter to |d0|, then make it readable (by writing to
- // |d1|), then wait.
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr));
- buffer[0] = 123456789;
- EXPECT_EQ(MOJO_RESULT_OK,
- d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(1u, context);
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- hss = HandleSignalsState();
- d0->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Try adding a readable waiter when already readable (from above).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // Shouldn't need to remove the waiter (it was not added).
-
- // Make |d0| no longer readable (by reading from it).
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- d0->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
- EXPECT_EQ(123456789, buffer[0]);
-
- // Wait for zero time for readability on |d0| (will time out).
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- hss = HandleSignalsState();
- d0->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Wait for non-zero, finite time for readability on |d0| (will time out).
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr));
- base::TimeDelta elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- hss = HandleSignalsState();
- d0->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Check the peer closed signal.
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, nullptr));
-
- // Close the peer.
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
-
- // It should be signaled.
- EXPECT_EQ(MOJO_RESULT_OK, w.Wait(1000, &context));
- EXPECT_EQ(12u, context);
- hss = HandleSignalsState();
- d0->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- }
-}
-
-TEST(MessagePipeDispatcherTest, InvalidParams) {
- char buffer[1];
-
- scoped_refptr<MessagePipeDispatcher> d0(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d1(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, 0);
- d1->Init(mp, 1);
- }
-
- // |WriteMessage|:
- // Huge buffer size.
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- d0->WriteMessage(UserPointer<const void>(buffer),
- std::numeric_limits<uint32_t>::max(), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
-}
-
-// These test invalid arguments that should cause death if we're being paranoid
-// about checking arguments (which we would want to do if, e.g., we were in a
-// true "kernel" situation, but we might not want to do otherwise for
-// performance reasons). Probably blatant errors like passing in null pointers
-// (for required pointer arguments) will still cause death, but perhaps not
-// predictably.
-TEST(MessagePipeDispatcherTest, InvalidParamsDeath) {
- const char kMemoryCheckFailedRegex[] = "Check failed";
-
- scoped_refptr<MessagePipeDispatcher> d0(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d1(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, 0);
- d1->Init(mp, 1);
- }
-
- // |WriteMessage|:
- // Null buffer with nonzero buffer size.
- EXPECT_DEATH_IF_SUPPORTED(d0->WriteMessage(NullUserPointer(), 1, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- kMemoryCheckFailedRegex);
-
- // |ReadMessage|:
- // Null buffer with nonzero buffer size.
- // First write something so that we actually have something to read.
- EXPECT_EQ(MOJO_RESULT_OK,
- d1->WriteMessage(UserPointer<const void>("x"), 1, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- uint32_t buffer_size = 1;
- EXPECT_DEATH_IF_SUPPORTED(
- d0->ReadMessage(NullUserPointer(), MakeUserPointer(&buffer_size), 0,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE),
- kMemoryCheckFailedRegex);
-
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
-}
-
-// Test what happens when one end is closed (single-threaded test).
-TEST(MessagePipeDispatcherTest, BasicClosed) {
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
- for (unsigned i = 0; i < 2; i++) {
- scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, i); // 0, 1.
- d1->Init(mp, i ^ 1); // 1, 0.
- }
- Waiter w;
- HandleSignalsState hss;
-
- // Write (twice) to |d1|.
- buffer[0] = 123456789;
- EXPECT_EQ(MOJO_RESULT_OK,
- d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- buffer[0] = 234567890;
- EXPECT_EQ(MOJO_RESULT_OK,
- d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Try waiting for readable on |d0|; should fail (already satisfied).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Try reading from |d1|; should fail (nothing to read).
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- d1->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Close |d1|.
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
-
- // Try waiting for readable on |d0|; should fail (already satisfied).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read from |d0|.
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- d0->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
- EXPECT_EQ(123456789, buffer[0]);
-
- // Try waiting for readable on |d0|; should fail (already satisfied).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read again from |d0|.
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- d0->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
- EXPECT_EQ(234567890, buffer[0]);
-
- // Try waiting for readable on |d0|; should fail (unsatisfiable).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- // Try waiting for writable on |d0|; should fail (unsatisfiable).
- w.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- // Try reading from |d0|; should fail (nothing to read and other end
- // closed).
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d0->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Try writing to |d0|; should fail (other end closed).
- buffer[0] = 345678901;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d0->WriteMessage(UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- }
-}
-
-#if defined(OS_WIN)
-// http://crbug.com/396386
-#define MAYBE_BasicThreaded DISABLED_BasicThreaded
-#else
-#define MAYBE_BasicThreaded BasicThreaded
-#endif
-TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) {
- test::Stopwatch stopwatch;
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
- base::TimeDelta elapsed;
- bool did_wait;
- MojoResult result;
- uint32_t context;
- HandleSignalsState hss;
-
- // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
- for (unsigned i = 0; i < 2; i++) {
- scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, i); // 0, 1.
- d1->Init(mp, i ^ 1); // 1, 0.
- }
-
- // Wait for readable on |d1|, which will become readable after some time.
- {
- test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- // Wake it up by writing to |d0|.
- buffer[0] = 123456789;
- EXPECT_EQ(MOJO_RESULT_OK,
- d0->WriteMessage(UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- } // Joins the thread.
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(1u, context);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Now |d1| is already readable. Try waiting for it again.
- {
- test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- } // Joins the thread.
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_FALSE(did_wait);
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Consume what we wrote to |d0|.
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- d1->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
- EXPECT_EQ(123456789, buffer[0]);
-
- // Wait for readable on |d1| and close |d0| after some time, which should
- // cancel that wait.
- {
- test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- } // Joins the thread.
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(3u, context);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
- }
-
- for (unsigned i = 0; i < 2; i++) {
- scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
- MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d0->Init(mp, i); // 0, 1.
- d1->Init(mp, i ^ 1); // 1, 0.
- }
-
- // Wait for readable on |d1| and close |d1| after some time, which should
- // cancel that wait.
- {
- test::WaiterThread thread(d1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
- } // Joins the thread.
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(4u, context);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- }
-}
-
-// Stress test -----------------------------------------------------------------
-
-const size_t kMaxMessageSize = 2000;
-
-class WriterThread : public base::SimpleThread {
- public:
- // |*messages_written| and |*bytes_written| belong to the thread while it's
- // alive.
- WriterThread(scoped_refptr<Dispatcher> write_dispatcher,
- size_t* messages_written,
- size_t* bytes_written)
- : base::SimpleThread("writer_thread"),
- write_dispatcher_(write_dispatcher),
- messages_written_(messages_written),
- bytes_written_(bytes_written) {
- *messages_written_ = 0;
- *bytes_written_ = 0;
- }
-
- ~WriterThread() override { Join(); }
-
- private:
- void Run() override {
- // Make some data to write.
- unsigned char buffer[kMaxMessageSize];
- for (size_t i = 0; i < kMaxMessageSize; i++)
- buffer[i] = static_cast<unsigned char>(i);
-
- // Number of messages to write.
- *messages_written_ = static_cast<size_t>(base::RandInt(1000, 6000));
-
- // Write messages.
- for (size_t i = 0; i < *messages_written_; i++) {
- uint32_t bytes_to_write = static_cast<uint32_t>(
- base::RandInt(1, static_cast<int>(kMaxMessageSize)));
- EXPECT_EQ(MOJO_RESULT_OK,
- write_dispatcher_->WriteMessage(UserPointer<const void>(buffer),
- bytes_to_write, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- *bytes_written_ += bytes_to_write;
- }
-
- // Write one last "quit" message.
- EXPECT_EQ(MOJO_RESULT_OK, write_dispatcher_->WriteMessage(
- UserPointer<const void>("quit"), 4, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- }
-
- const scoped_refptr<Dispatcher> write_dispatcher_;
- size_t* const messages_written_;
- size_t* const bytes_written_;
-
- DISALLOW_COPY_AND_ASSIGN(WriterThread);
-};
-
-class ReaderThread : public base::SimpleThread {
- public:
- // |*messages_read| and |*bytes_read| belong to the thread while it's alive.
- ReaderThread(scoped_refptr<Dispatcher> read_dispatcher,
- size_t* messages_read,
- size_t* bytes_read)
- : base::SimpleThread("reader_thread"),
- read_dispatcher_(read_dispatcher),
- messages_read_(messages_read),
- bytes_read_(bytes_read) {
- *messages_read_ = 0;
- *bytes_read_ = 0;
- }
-
- ~ReaderThread() override { Join(); }
-
- private:
- void Run() override {
- unsigned char buffer[kMaxMessageSize];
- Waiter w;
- HandleSignalsState hss;
- MojoResult result;
-
- // Read messages.
- for (;;) {
- // Wait for it to be readable.
- w.Init();
- hss = HandleSignalsState();
- result = read_dispatcher_->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0,
- &hss);
- EXPECT_TRUE(result == MOJO_RESULT_OK ||
- result == MOJO_RESULT_ALREADY_EXISTS)
- << "result: " << result;
- if (result == MOJO_RESULT_OK) {
- // Actually need to wait.
- EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr));
- read_dispatcher_->RemoveAwakable(&w, &hss);
- }
- // We may not actually be readable, since we're racing with other threads.
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- // Now, try to do the read.
- // Clear the buffer so that we can check the result.
- memset(buffer, 0, sizeof(buffer));
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- result = read_dispatcher_->ReadMessage(
- UserPointer<void>(buffer), MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE);
- EXPECT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT)
- << "result: " << result;
- // We're racing with others to read, so maybe we failed.
- if (result == MOJO_RESULT_SHOULD_WAIT)
- continue; // In which case, try again.
- // Check for quit.
- if (buffer_size == 4 && memcmp("quit", buffer, 4) == 0)
- return;
- EXPECT_GE(buffer_size, 1u);
- EXPECT_LE(buffer_size, kMaxMessageSize);
- EXPECT_TRUE(IsValidMessage(buffer, buffer_size));
-
- (*messages_read_)++;
- *bytes_read_ += buffer_size;
- }
- }
-
- static bool IsValidMessage(const unsigned char* buffer,
- uint32_t message_size) {
- size_t i;
- for (i = 0; i < message_size; i++) {
- if (buffer[i] != static_cast<unsigned char>(i))
- return false;
- }
- // Check that the remaining bytes weren't stomped on.
- for (; i < kMaxMessageSize; i++) {
- if (buffer[i] != 0)
- return false;
- }
- return true;
- }
-
- const scoped_refptr<Dispatcher> read_dispatcher_;
- size_t* const messages_read_;
- size_t* const bytes_read_;
-
- DISALLOW_COPY_AND_ASSIGN(ReaderThread);
-};
-
-TEST(MessagePipeDispatcherTest, Stress) {
- static const size_t kNumWriters = 30;
- static const size_t kNumReaders = kNumWriters;
-
- scoped_refptr<MessagePipeDispatcher> d_write(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipeDispatcher> d_read(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- d_write->Init(mp, 0);
- d_read->Init(mp, 1);
- }
-
- size_t messages_written[kNumWriters];
- size_t bytes_written[kNumWriters];
- size_t messages_read[kNumReaders];
- size_t bytes_read[kNumReaders];
- {
- // Make writers.
- ScopedVector<WriterThread> writers;
- for (size_t i = 0; i < kNumWriters; i++) {
- writers.push_back(
- new WriterThread(d_write, &messages_written[i], &bytes_written[i]));
- }
-
- // Make readers.
- ScopedVector<ReaderThread> readers;
- for (size_t i = 0; i < kNumReaders; i++) {
- readers.push_back(
- new ReaderThread(d_read, &messages_read[i], &bytes_read[i]));
- }
-
- // Start writers.
- for (size_t i = 0; i < kNumWriters; i++)
- writers[i]->Start();
-
- // Start readers.
- for (size_t i = 0; i < kNumReaders; i++)
- readers[i]->Start();
-
- // TODO(vtl): Maybe I should have an event that triggers all the threads to
- // start doing stuff for real (so that the first ones created/started aren't
- // advantaged).
- } // Joins all the threads.
-
- size_t total_messages_written = 0;
- size_t total_bytes_written = 0;
- for (size_t i = 0; i < kNumWriters; i++) {
- total_messages_written += messages_written[i];
- total_bytes_written += bytes_written[i];
- }
- size_t total_messages_read = 0;
- size_t total_bytes_read = 0;
- for (size_t i = 0; i < kNumReaders; i++) {
- total_messages_read += messages_read[i];
- total_bytes_read += bytes_read[i];
- // We'd have to be really unlucky to have read no messages on a thread.
- EXPECT_GT(messages_read[i], 0u) << "reader: " << i;
- EXPECT_GE(bytes_read[i], messages_read[i]) << "reader: " << i;
- }
- EXPECT_EQ(total_messages_written, total_messages_read);
- EXPECT_EQ(total_bytes_written, total_bytes_read);
-
- EXPECT_EQ(MOJO_RESULT_OK, d_write->Close());
- EXPECT_EQ(MOJO_RESULT_OK, d_read->Close());
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_endpoint.cc b/mojo/edk/system/message_pipe_endpoint.cc
deleted file mode 100644
index 4b8bc5e..0000000
--- a/mojo/edk/system/message_pipe_endpoint.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 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/message_pipe_endpoint.h"
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace system {
-
-void MessagePipeEndpoint::CancelAllAwakables() {
- NOTREACHED();
-}
-
-MojoResult MessagePipeEndpoint::ReadMessage(UserPointer<void> /*bytes*/,
- UserPointer<uint32_t> /*num_bytes*/,
- DispatcherVector* /*dispatchers*/,
- uint32_t* /*num_dispatchers*/,
- MojoReadMessageFlags /*flags*/) {
- NOTREACHED();
- return MOJO_RESULT_INTERNAL;
-}
-
-HandleSignalsState MessagePipeEndpoint::GetHandleSignalsState() const {
- NOTREACHED();
- return HandleSignalsState();
-}
-
-MojoResult MessagePipeEndpoint::AddAwakable(Awakable* /*awakable*/,
- MojoHandleSignals /*signals*/,
- uint32_t /*context*/,
- HandleSignalsState* signals_state) {
- NOTREACHED();
- if (signals_state)
- *signals_state = HandleSignalsState();
- return MOJO_RESULT_INTERNAL;
-}
-
-void MessagePipeEndpoint::RemoveAwakable(Awakable* /*awakable*/,
- HandleSignalsState* signals_state) {
- NOTREACHED();
- if (signals_state)
- *signals_state = HandleSignalsState();
-}
-
-void MessagePipeEndpoint::Attach(ChannelEndpoint* /*channel_endpoint*/) {
- NOTREACHED();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_endpoint.h b/mojo/edk/system/message_pipe_endpoint.h
deleted file mode 100644
index 0b5f12e..0000000
--- a/mojo/edk/system/message_pipe_endpoint.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/message_pipe.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-class ChannelEndpoint;
-class Awakable;
-
-// This is an interface to one of the ends of a message pipe, and is used by
-// |MessagePipe|. Its most important role is to provide a sink for messages
-// (i.e., a place where messages can be sent). It has a secondary role: When the
-// endpoint is local (i.e., in the current process), there'll be a dispatcher
-// corresponding to the endpoint. In that case, the implementation of
-// |MessagePipeEndpoint| also implements the functionality required by the
-// dispatcher, e.g., to read messages and to wait. Implementations of this class
-// are not thread-safe; instances are protected by |MesssagePipe|'s lock.
-class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint {
- public:
- virtual ~MessagePipeEndpoint() {}
-
- enum Type { kTypeLocal, kTypeProxy };
- virtual Type GetType() const = 0;
-
- // All implementations must implement these.
- // Returns false if the endpoint should be closed and destroyed, else true.
- virtual bool OnPeerClose() = 0;
- // Implements |MessagePipe::EnqueueMessage()|. The major differences are that:
- // a) Dispatchers have been vetted and cloned/attached to the message.
- // b) At this point, we cannot report failure (if, e.g., a channel is torn
- // down at this point, we should silently swallow the message).
- virtual void EnqueueMessage(scoped_ptr<MessageInTransit> message) = 0;
- virtual void Close() = 0;
-
- // Implementations must override these if they represent a local endpoint,
- // i.e., one for which there's a |MessagePipeDispatcher| (and thus a handle).
- // An implementation for a proxy endpoint (for which there's no dispatcher)
- // needs not override these methods, since they should never be called.
- //
- // These methods implement the methods of the same name in |MessagePipe|,
- // though |MessagePipe|'s implementation may have to do a little more if the
- // operation involves both endpoints.
- virtual void CancelAllAwakables();
- virtual MojoResult ReadMessage(UserPointer<void> bytes,
- UserPointer<uint32_t> num_bytes,
- DispatcherVector* dispatchers,
- uint32_t* num_dispatchers,
- MojoReadMessageFlags flags);
- virtual HandleSignalsState GetHandleSignalsState() const;
- virtual MojoResult AddAwakable(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state);
- virtual void RemoveAwakable(Awakable* awakable,
- HandleSignalsState* signals_state);
-
- // Implementations must override these if they represent a proxy endpoint. An
- // implementation for a local endpoint needs not override these methods, since
- // they should never be called.
- virtual void Attach(ChannelEndpoint* channel_endpoint);
-
- protected:
- MessagePipeEndpoint() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MessagePipeEndpoint);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_ENDPOINT_H_
diff --git a/mojo/edk/system/message_pipe_perftest.cc b/mojo/edk/system/message_pipe_perftest.cc
deleted file mode 100644
index 2387782..0000000
--- a/mojo/edk/system/message_pipe_perftest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// 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 <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/pickle.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/perf_time_logger.h"
-#include "base/time/time.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/local_message_pipe_endpoint.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/message_pipe_test_utils.h"
-#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
-#include "mojo/edk/system/raw_channel.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-class MultiprocessMessagePipePerfTest
- : public test::MultiprocessMessagePipeTestBase {
- public:
- MultiprocessMessagePipePerfTest() : message_count_(0), message_size_(0) {}
-
- void SetUpMeasurement(int message_count, size_t message_size) {
- message_count_ = message_count;
- message_size_ = message_size;
- payload_ = Pickle();
- payload_.WriteString(std::string(message_size, '*'));
- read_buffer_.resize(message_size * 2);
- }
-
- protected:
- void WriteWaitThenRead(scoped_refptr<MessagePipe> mp) {
- CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(payload_.data()),
- static_cast<uint32_t>(payload_.size()), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- HandleSignalsState hss;
- CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
- MOJO_RESULT_OK);
- uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer_.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer_[0]),
- MakeUserPointer(&read_buffer_size), nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- CHECK_EQ(read_buffer_size, static_cast<uint32_t>(payload_.size()));
- }
-
- void SendQuitMessage(scoped_refptr<MessagePipe> mp) {
- CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(""), 0, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- }
-
- void Measure(scoped_refptr<MessagePipe> mp) {
- // Have one ping-pong to ensure channel being established.
- WriteWaitThenRead(mp);
-
- std::string test_name =
- base::StringPrintf("IPC_Perf_%dx_%u", message_count_,
- static_cast<unsigned>(message_size_));
- base::PerfTimeLogger logger(test_name.c_str());
-
- for (int i = 0; i < message_count_; ++i)
- WriteWaitThenRead(mp);
-
- logger.Done();
- }
-
- private:
- int message_count_;
- size_t message_size_;
- Pickle payload_;
- std::string read_buffer_;
- scoped_ptr<base::PerfTimeLogger> perf_logger_;
-};
-
-// For each message received, sends a reply message with the same contents
-// repeated twice, until the other end is closed or it receives "quitquitquit"
-// (which it doesn't reply to). It'll return the number of messages received,
-// not including any "quitquitquit" message, modulo 100.
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient) {
- embedder::SimplePlatformSupport platform_support;
- test::ChannelThread channel_thread(&platform_support);
- embedder::ScopedPlatformHandle client_platform_handle =
- mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
- CHECK(client_platform_handle.is_valid());
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- channel_thread.Start(client_platform_handle.Pass(), ep);
-
- std::string buffer(1000000, '\0');
- int rv = 0;
- while (true) {
- // Wait for our end of the message pipe to be readable.
- HandleSignalsState hss;
- MojoResult result =
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss);
- if (result != MOJO_RESULT_OK) {
- rv = result;
- break;
- }
-
- uint32_t read_size = static_cast<uint32_t>(buffer.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&buffer[0]),
- MakeUserPointer(&read_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
-
- // Empty message indicates quitting
- if (0 == read_size)
- break;
-
- CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(&buffer[0]),
- static_cast<uint32_t>(read_size), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- }
-
- mp->Close(0);
- return rv;
-}
-
-// Repeatedly sends messages as previous one got replied by the child.
-// Waits for the child to close its end before quitting once specified
-// number of messages has been sent.
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_PingPong DISABLED_PingPong
-#else
-#define MAYBE_PingPong PingPong
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessMessagePipePerfTest, MAYBE_PingPong) {
- helper()->StartChild("PingPongClient");
-
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- Init(ep);
-
- // This values are set to align with one at ipc_pertests.cc for comparison.
- const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832};
- const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000};
-
- for (size_t i = 0; i < 5; i++) {
- SetUpMeasurement(kMessageCount[i], kMsgSize[i]);
- Measure(mp);
- }
-
- SendQuitMessage(mp);
- mp->Close(0);
- EXPECT_EQ(0, helper()->WaitForChildShutdown());
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_test_utils.cc b/mojo/edk/system/message_pipe_test_utils.cc
deleted file mode 100644
index f227543..0000000
--- a/mojo/edk/system/message_pipe_test_utils.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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/message_pipe_test_utils.h"
-
-#include "base/bind.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/waiter.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp,
- MojoHandleSignals signals,
- HandleSignalsState* signals_state) {
- Waiter waiter;
- waiter.Init();
-
- MojoResult add_result =
- mp->AddAwakable(0, &waiter, signals, 0, signals_state);
- if (add_result != MOJO_RESULT_OK) {
- return (add_result == MOJO_RESULT_ALREADY_EXISTS) ? MOJO_RESULT_OK
- : add_result;
- }
-
- MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr);
- mp->RemoveAwakable(0, &waiter, signals_state);
- return wait_result;
-}
-
-ChannelThread::ChannelThread(embedder::PlatformSupport* platform_support)
- : platform_support_(platform_support),
- test_io_thread_(base::TestIOThread::kManualStart) {
-}
-
-ChannelThread::~ChannelThread() {
- Stop();
-}
-
-void ChannelThread::Start(embedder::ScopedPlatformHandle platform_handle,
- scoped_refptr<ChannelEndpoint> channel_endpoint) {
- test_io_thread_.Start();
- test_io_thread_.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelThread::InitChannelOnIOThread, base::Unretained(this),
- base::Passed(&platform_handle), channel_endpoint));
-}
-
-void ChannelThread::Stop() {
- if (channel_) {
- // Hack to flush write buffers before quitting.
- // TODO(vtl): Remove this once |Channel| has a
- // |FlushWriteBufferAndShutdown()| (or whatever).
- while (!channel_->IsWriteBufferEmpty())
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
-
- test_io_thread_.PostTaskAndWait(
- FROM_HERE, base::Bind(&ChannelThread::ShutdownChannelOnIOThread,
- base::Unretained(this)));
- }
- test_io_thread_.Stop();
-}
-
-void ChannelThread::InitChannelOnIOThread(
- embedder::ScopedPlatformHandle platform_handle,
- scoped_refptr<ChannelEndpoint> channel_endpoint) {
- CHECK_EQ(base::MessageLoop::current(), test_io_thread_.message_loop());
- CHECK(platform_handle.is_valid());
-
- // Create and initialize |Channel|.
- channel_ = new Channel(platform_support_);
- channel_->Init(RawChannel::Create(platform_handle.Pass()));
-
- // Start the bootstrap endpoint.
- // Note: On the "server" (parent process) side, we need not attach/run the
- // endpoint immediately. However, on the "client" (child process) side, this
- // *must* be done here -- otherwise, the |Channel| may receive/process
- // messages (which it can do as soon as it's hooked up to the IO thread
- // message loop, and that message loop runs) before the endpoint is attached.
- channel_->SetBootstrapEndpoint(channel_endpoint);
-}
-
-void ChannelThread::ShutdownChannelOnIOThread() {
- CHECK(channel_);
- channel_->Shutdown();
- channel_ = nullptr;
-}
-
-#if !defined(OS_IOS)
-MultiprocessMessagePipeTestBase::MultiprocessMessagePipeTestBase()
- : channel_thread_(&platform_support_) {
-}
-
-MultiprocessMessagePipeTestBase::~MultiprocessMessagePipeTestBase() {
-}
-
-void MultiprocessMessagePipeTestBase::Init(scoped_refptr<ChannelEndpoint> ep) {
- channel_thread_.Start(helper_.server_platform_handle.Pass(), ep);
-}
-#endif
-
-} // namespace test
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_test_utils.h b/mojo/edk/system/message_pipe_test_utils.h
deleted file mode 100644
index c9d9c8b..0000000
--- a/mojo/edk/system/message_pipe_test_utils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_
-
-#include "base/test/test_io_thread.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/multiprocess_test_helper.h"
-
-namespace mojo {
-namespace system {
-
-class Channel;
-class ChannelEndpoint;
-class MessagePipe;
-
-namespace test {
-
-MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp,
- MojoHandleSignals signals,
- HandleSignalsState* signals_state);
-
-class ChannelThread {
- public:
- explicit ChannelThread(embedder::PlatformSupport* platform_support);
- ~ChannelThread();
-
- void Start(embedder::ScopedPlatformHandle platform_handle,
- scoped_refptr<ChannelEndpoint> channel_endpoint);
- void Stop();
-
- private:
- void InitChannelOnIOThread(embedder::ScopedPlatformHandle platform_handle,
- scoped_refptr<ChannelEndpoint> channel_endpoint);
- void ShutdownChannelOnIOThread();
-
- embedder::PlatformSupport* const platform_support_;
- base::TestIOThread test_io_thread_;
- scoped_refptr<Channel> channel_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelThread);
-};
-
-#if !defined(OS_IOS)
-class MultiprocessMessagePipeTestBase : public testing::Test {
- public:
- MultiprocessMessagePipeTestBase();
- ~MultiprocessMessagePipeTestBase() override;
-
- protected:
- void Init(scoped_refptr<ChannelEndpoint> ep);
-
- embedder::PlatformSupport* platform_support() { return &platform_support_; }
- mojo::test::MultiprocessTestHelper* helper() { return &helper_; }
-
- private:
- embedder::SimplePlatformSupport platform_support_;
- ChannelThread channel_thread_;
- mojo::test::MultiprocessTestHelper helper_;
-
- DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipeTestBase);
-};
-#endif
-
-} // namespace test
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_
diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc
deleted file mode 100644
index a30b636..0000000
--- a/mojo/edk/system/message_pipe_unittest.cc
+++ /dev/null
@@ -1,574 +0,0 @@
-// Copyright 2013 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/message_pipe.h"
-
-#include "base/memory/ref_counted.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/time/time.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/system/waiter_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED;
-
-// Tests:
-// - only default flags
-// - reading messages from a port
-// - when there are no/one/two messages available for that port
-// - with buffer size 0 (and null buffer) -- should get size
-// - with too-small buffer -- should get size
-// - also verify that buffers aren't modified when/where they shouldn't be
-// - writing messages to a port
-// - in the obvious scenarios (as above)
-// - to a port that's been closed
-// - writing a message to a port, closing the other (would be the source) port,
-// and reading it
-TEST(MessagePipeTest, Basic) {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
-
- int32_t buffer[2];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Nothing to read yet on port 0.
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
- EXPECT_EQ(123, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Ditto for port 1.
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Write from port 1 (to port 0).
- buffer[0] = 789012345;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read from port 0.
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(789012345, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read again from port 0 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Write two messages from port 0 (to port 1).
- buffer[0] = 123456789;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- buffer[0] = 234567890;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read from port 1 with buffer size 0 (should get the size of next message).
- // Also test that giving a null buffer is okay when the buffer size is 0.
- buffer_size = 0;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(1, NullUserPointer(), MakeUserPointer(&buffer_size),
- 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
-
- // Read from port 1 with buffer size 1 (too small; should get the size of next
- // message).
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = 1;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(123, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read from port 1.
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(123456789, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read again from port 1.
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(234567890, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read again from port 1 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Write from port 0 (to port 1).
- buffer[0] = 345678901;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Close port 0.
- mp->Close(0);
-
- // Try to write from port 1 (to port 0).
- buffer[0] = 456789012;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read from port 1; should still get message (even though port 0 was closed).
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(345678901, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read again from port 1 -- it should be empty (and port 0 is closed).
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- mp->Close(1);
-}
-
-TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
-
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Write some messages from port 1 (to port 0).
- for (int32_t i = 0; i < 5; i++) {
- buffer[0] = i;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- }
-
- // Port 0 shouldn't be empty.
- buffer_size = 0;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size),
- 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(kBufferSize, buffer_size);
-
- // Close port 0 first, which should have outstanding (incoming) messages.
- mp->Close(0);
- mp->Close(1);
-}
-
-TEST(MessagePipeTest, DiscardMode) {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
-
- int32_t buffer[2];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Write from port 1 (to port 0).
- buffer[0] = 789012345;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read/discard from port 0 (no buffer); get size.
- buffer_size = 0;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size),
- 0, nullptr, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
-
- // Read again from port 0 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- // Write from port 1 (to port 0).
- buffer[0] = 890123456;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read from port 0 (buffer big enough).
- buffer[0] = 123;
- buffer[1] = 456;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
- EXPECT_EQ(890123456, buffer[0]);
- EXPECT_EQ(456, buffer[1]);
-
- // Read again from port 0 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- // Write from port 1 (to port 0).
- buffer[0] = 901234567;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Read/discard from port 0 (buffer too small); get size.
- buffer_size = 1;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
- EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
-
- // Read again from port 0 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- // Write from port 1 (to port 0).
- buffer[0] = 123456789;
- buffer[1] = 0;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(1, UserPointer<const void>(buffer),
- static_cast<uint32_t>(sizeof(buffer[0])), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Discard from port 0.
- buffer_size = 1;
- EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
- mp->ReadMessage(0, NullUserPointer(), NullUserPointer(), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- // Read again from port 0 -- it should be empty.
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
-
- mp->Close(0);
- mp->Close(1);
-}
-
-TEST(MessagePipeTest, BasicWaiting) {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- Waiter waiter;
- HandleSignalsState hss;
-
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
- uint32_t buffer_size;
-
- // Always writable (until the other port is closed).
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE,
- 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Not yet readable.
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- mp->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // The peer is not closed.
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
- hss = HandleSignalsState();
- mp->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Write from port 0 (to port 1), to make port 1 readable.
- buffer[0] = 123456789;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Port 1 should already be readable now.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE,
- 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // ... and still writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Close port 0.
- mp->Close(0);
-
- // Port 1 should be signaled with peer closed.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 5, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Port 1 should not be writable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // But it should still be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Read from port 1.
- buffer[0] = 0;
- buffer_size = kBufferSize;
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(123456789, buffer[0]);
-
- // Now port 1 should no longer be readable.
- waiter.Init();
- hss = HandleSignalsState();
- EXPECT_EQ(
- MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- mp->Close(1);
-}
-
-TEST(MessagePipeTest, ThreadedWaiting) {
- int32_t buffer[1];
- const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
-
- MojoResult result;
- uint32_t context;
-
- // Write to wake up waiter waiting for read.
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- test::SimpleWaiterThread thread(&result, &context);
-
- thread.waiter()->Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE,
- 1, nullptr));
- thread.Start();
-
- buffer[0] = 123456789;
- // Write from port 0 (to port 1), which should wake up the waiter.
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize,
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- HandleSignalsState hss;
- mp->RemoveAwakable(1, thread.waiter(), &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- mp->Close(0);
- mp->Close(1);
- } // Joins |thread|.
- // The waiter should have woken up successfully.
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(1u, context);
-
- // Close to cancel waiter.
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- test::SimpleWaiterThread thread(&result, &context);
-
- thread.waiter()->Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE,
- 2, nullptr));
- thread.Start();
-
- // Close port 1 first -- this should result in the waiter being cancelled.
- mp->CancelAllAwakables(1);
- mp->Close(1);
-
- // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into
- // the |MessagePipe| to remove any waiter.
-
- mp->Close(0);
- } // Joins |thread|.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(2u, context);
-
- // Close to cancel waiter using peer closed signal.
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- test::SimpleWaiterThread thread(&result, &context);
-
- thread.waiter()->Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddAwakable(1, thread.waiter(),
- MOJO_HANDLE_SIGNAL_PEER_CLOSED, 3, nullptr));
- thread.Start();
-
- // Close port 1 first -- this should result in the waiter being cancelled.
- mp->CancelAllAwakables(1);
- mp->Close(1);
-
- // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into
- // the |MessagePipe| to remove any waiter.
-
- mp->Close(0);
- } // Joins |thread|.
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(3u, context);
-
- // Close to make waiter un-wake-up-able.
- {
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
- test::SimpleWaiterThread thread(&result, &context);
-
- thread.waiter()->Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE,
- 4, nullptr));
- thread.Start();
-
- // Close port 0 first -- this should wake the waiter up, since port 1 will
- // never be readable.
- mp->CancelAllAwakables(0);
- mp->Close(0);
-
- HandleSignalsState hss;
- mp->RemoveAwakable(1, thread.waiter(), &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->CancelAllAwakables(1);
- mp->Close(1);
- } // Joins |thread|.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(4u, context);
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
deleted file mode 100644
index af3b3bb..0000000
--- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2013 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 <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "build/build_config.h" // TODO(vtl): Remove this.
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/message_pipe_test_utils.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/raw_channel.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-class MultiprocessMessagePipeTest
- : public test::MultiprocessMessagePipeTestBase {};
-
-// For each message received, sends a reply message with the same contents
-// repeated twice, until the other end is closed or it receives "quitquitquit"
-// (which it doesn't reply to). It'll return the number of messages received,
-// not including any "quitquitquit" message, modulo 100.
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) {
- embedder::SimplePlatformSupport platform_support;
- test::ChannelThread channel_thread(&platform_support);
- embedder::ScopedPlatformHandle client_platform_handle =
- mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
- CHECK(client_platform_handle.is_valid());
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- channel_thread.Start(client_platform_handle.Pass(), ep);
-
- const std::string quitquitquit("quitquitquit");
- int rv = 0;
- for (;; rv = (rv + 1) % 100) {
- // Wait for our end of the message pipe to be readable.
- HandleSignalsState hss;
- MojoResult result =
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss);
- if (result != MOJO_RESULT_OK) {
- // It was closed, probably.
- CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
- CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
- CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
- break;
- } else {
- CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
- }
-
- std::string read_buffer(1000, '\0');
- uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&read_buffer_size), nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- read_buffer.resize(read_buffer_size);
- VLOG(2) << "Child got: " << read_buffer;
-
- if (read_buffer == quitquitquit) {
- VLOG(2) << "Child quitting.";
- break;
- }
-
- std::string write_buffer = read_buffer + read_buffer;
- CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(write_buffer.data()),
- static_cast<uint32_t>(write_buffer.size()),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- }
-
- mp->Close(0);
- return rv;
-}
-
-// Sends "hello" to child, and expects "hellohello" back.
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_Basic DISABLED_Basic
-#else
-#define MAYBE_Basic Basic
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) {
- helper()->StartChild("EchoEcho");
-
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- Init(ep);
-
- std::string hello("hello");
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(hello.data()),
- static_cast<uint32_t>(hello.size()), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_OK,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- // The child may or may not have closed its end of the message pipe and died
- // (and we may or may not know it yet), so our end may or may not appear as
- // writable.
- EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- std::string read_buffer(1000, '\0');
- uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&read_buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- read_buffer.resize(read_buffer_size);
- VLOG(2) << "Parent got: " << read_buffer;
- EXPECT_EQ(hello + hello, read_buffer);
-
- mp->Close(0);
-
- // We sent one message.
- EXPECT_EQ(1 % 100, helper()->WaitForChildShutdown());
-}
-
-// Sends a bunch of messages to the child. Expects them "repeated" back. Waits
-// for the child to close its end before quitting.
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_QueueMessages DISABLED_QueueMessages
-#else
-#define MAYBE_QueueMessages QueueMessages
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessMessagePipeTest, DISABLED_QueueMessages) {
- helper()->StartChild("EchoEcho");
-
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- Init(ep);
-
- static const size_t kNumMessages = 1001;
- for (size_t i = 0; i < kNumMessages; i++) {
- std::string write_buffer(i, 'A' + (i % 26));
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(write_buffer.data()),
- static_cast<uint32_t>(write_buffer.size()),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- }
-
- const std::string quitquitquit("quitquitquit");
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(quitquitquit.data()),
- static_cast<uint32_t>(quitquitquit.size()),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- for (size_t i = 0; i < kNumMessages; i++) {
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_OK,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- // The child may or may not have closed its end of the message pipe and died
- // (and we may or may not know it yet), so our end may or may not appear as
- // writable.
- EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- std::string read_buffer(kNumMessages * 2, '\0');
- uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&read_buffer_size), nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- read_buffer.resize(read_buffer_size);
-
- EXPECT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer);
- }
-
- // Wait for it to become readable, which should fail (since we sent
- // "quitquitquit").
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->Close(0);
-
- EXPECT_EQ(static_cast<int>(kNumMessages % 100),
- helper()->WaitForChildShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
- embedder::SimplePlatformSupport platform_support;
- test::ChannelThread channel_thread(&platform_support);
- embedder::ScopedPlatformHandle client_platform_handle =
- mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
- CHECK(client_platform_handle.is_valid());
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- channel_thread.Start(client_platform_handle.Pass(), ep);
-
- // Wait for the first message from our parent.
- HandleSignalsState hss;
- CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
- MOJO_RESULT_OK);
- // In this test, the parent definitely doesn't close its end of the message
- // pipe before we do.
- CHECK_EQ(hss.satisfied_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED);
-
- // It should have a shared buffer.
- std::string read_buffer(100, '\0');
- uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
- DispatcherVector dispatchers;
- uint32_t num_dispatchers = 10; // Maximum number to receive.
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&num_bytes), &dispatchers,
- &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- read_buffer.resize(num_bytes);
- CHECK_EQ(read_buffer, std::string("go 1"));
- CHECK_EQ(num_dispatchers, 1u);
-
- CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypeSharedBuffer);
-
- scoped_refptr<SharedBufferDispatcher> dispatcher(
- static_cast<SharedBufferDispatcher*>(dispatchers[0].get()));
-
- // Make a mapping.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
- CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping),
- MOJO_RESULT_OK);
- CHECK(mapping);
- CHECK(mapping->GetBase());
- CHECK_EQ(mapping->GetLength(), 100u);
-
- // Write some stuff to the shared buffer.
- static const char kHello[] = "hello";
- memcpy(mapping->GetBase(), kHello, sizeof(kHello));
-
- // We should be able to close the dispatcher now.
- dispatcher->Close();
-
- // And send a message to signal that we've written stuff.
- const std::string go2("go 2");
- CHECK_EQ(mp->WriteMessage(0, UserPointer<const void>(&go2[0]),
- static_cast<uint32_t>(go2.size()), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
-
- // Now wait for our parent to send us a message.
- hss = HandleSignalsState();
- CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
- MOJO_RESULT_OK);
- CHECK_EQ(hss.satisfied_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED);
-
- read_buffer = std::string(100, '\0');
- num_bytes = static_cast<uint32_t>(read_buffer.size());
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&num_bytes), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- read_buffer.resize(num_bytes);
- CHECK_EQ(read_buffer, std::string("go 3"));
-
- // It should have written something to the shared buffer.
- static const char kWorld[] = "world!!!";
- CHECK_EQ(memcmp(mapping->GetBase(), kWorld, sizeof(kWorld)), 0);
-
- // And we're done.
- mp->Close(0);
-
- return 0;
-}
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
-#define MAYBE_SharedBufferPassing SharedBufferPassing
-#else
-// Not yet implemented (on Windows).
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing
-#endif
-TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
- helper()->StartChild("CheckSharedBuffer");
-
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- Init(ep);
-
- // Make a shared buffer.
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher));
- ASSERT_TRUE(dispatcher);
-
- // Make a mapping.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
- EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- ASSERT_TRUE(mapping);
- ASSERT_TRUE(mapping->GetBase());
- ASSERT_EQ(100u, mapping->GetLength());
-
- // Send the shared buffer.
- const std::string go1("go 1");
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- ASSERT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(&go1[0]),
- static_cast<uint32_t>(go1.size()), &transports,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
-
- // Wait for a message from the child.
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_OK,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- std::string read_buffer(100, '\0');
- uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&num_bytes), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- read_buffer.resize(num_bytes);
- EXPECT_EQ(std::string("go 2"), read_buffer);
-
- // After we get it, the child should have written something to the shared
- // buffer.
- static const char kHello[] = "hello";
- EXPECT_EQ(0, memcmp(mapping->GetBase(), kHello, sizeof(kHello)));
-
- // Now we'll write some stuff to the shared buffer.
- static const char kWorld[] = "world!!!";
- memcpy(mapping->GetBase(), kWorld, sizeof(kWorld));
-
- // And send a message to signal that we've written stuff.
- const std::string go3("go 3");
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(&go3[0]),
- static_cast<uint32_t>(go3.size()), nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait for |mp| to become readable, which should fail.
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->Close(0);
-
- EXPECT_EQ(0, helper()->WaitForChildShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) {
- embedder::SimplePlatformSupport platform_support;
- test::ChannelThread channel_thread(&platform_support);
- embedder::ScopedPlatformHandle client_platform_handle =
- mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
- CHECK(client_platform_handle.is_valid());
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- channel_thread.Start(client_platform_handle.Pass(), ep);
-
- HandleSignalsState hss;
- CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
- MOJO_RESULT_OK);
- CHECK_EQ(hss.satisfied_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED);
-
- std::string read_buffer(100, '\0');
- uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
- DispatcherVector dispatchers;
- uint32_t num_dispatchers = 30; // Maximum number to receive.
- CHECK_EQ(mp->ReadMessage(0, UserPointer<void>(&read_buffer[0]),
- MakeUserPointer(&num_bytes), &dispatchers,
- &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE),
- MOJO_RESULT_OK);
- mp->Close(0);
-
- read_buffer.resize(num_bytes);
- char hello[32];
- int num_handles = 0;
- sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles);
- CHECK_EQ(std::string("hello"), std::string(hello));
- CHECK_GT(num_handles, 0);
-
- for (int i = 0; i < num_handles; ++i) {
- CHECK_EQ(dispatchers[i]->GetType(), Dispatcher::kTypePlatformHandle);
-
- scoped_refptr<PlatformHandleDispatcher> dispatcher(
- static_cast<PlatformHandleDispatcher*>(dispatchers[i].get()));
- embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle().Pass();
- CHECK(h.is_valid());
- dispatcher->Close();
-
- base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h.Pass(), "r"));
- CHECK(fp);
- std::string fread_buffer(100, '\0');
- size_t bytes_read =
- fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get());
- fread_buffer.resize(bytes_read);
- CHECK_EQ(fread_buffer, "world");
- }
-
- return 0;
-}
-
-class MultiprocessMessagePipeTestWithPipeCount
- : public test::MultiprocessMessagePipeTestBase,
- public testing::WithParamInterface<size_t> {};
-
-TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- helper()->StartChild("CheckPlatformHandleFile");
-
- scoped_refptr<ChannelEndpoint> ep;
- scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
- Init(ep);
-
- std::vector<scoped_refptr<PlatformHandleDispatcher>> dispatchers;
- std::vector<DispatcherTransport> transports;
-
- size_t pipe_count = GetParam();
- for (size_t i = 0; i < pipe_count; ++i) {
- base::FilePath unused;
- base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- const std::string world("world");
- CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size());
- fflush(fp.get());
- rewind(fp.get());
-
- scoped_refptr<PlatformHandleDispatcher> dispatcher(
- new PlatformHandleDispatcher(embedder::ScopedPlatformHandle(
- mojo::test::PlatformHandleFromFILE(fp.Pass()))));
- dispatchers.push_back(dispatcher);
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- ASSERT_TRUE(transport.is_valid());
- transports.push_back(transport);
- }
-
- char message[128];
- sprintf(message, "hello %d", static_cast<int>(pipe_count));
- EXPECT_EQ(MOJO_RESULT_OK,
- mp->WriteMessage(0, UserPointer<const void>(message),
- static_cast<uint32_t>(strlen(message)),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- for (size_t i = 0; i < pipe_count; ++i) {
- transports[i].End();
- EXPECT_TRUE(dispatchers[i]->HasOneRef());
- }
-
- dispatchers.clear();
-
- // Wait for it to become readable, which should fail.
- HandleSignalsState hss;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- mp->Close(0);
-
- EXPECT_EQ(0, helper()->WaitForChildShutdown());
-}
-
-// Not yet implemented (on Windows).
-// Android multi-process tests are not executing the new process. This is flaky.
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
-INSTANTIATE_TEST_CASE_P(PipeCount,
- MultiprocessMessagePipeTestWithPipeCount,
- testing::Values(1u, 10u, 25u));
-#endif
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/options_validation.h b/mojo/edk/system/options_validation.h
deleted file mode 100644
index 9724e38..0000000
--- a/mojo/edk/system/options_validation.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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.
-
-// Functions to help with verifying various |Mojo...Options| structs from the
-// (public, C) API. These are "extensible" structs, which all have |struct_size|
-// as their first member. All fields (other than |struct_size|) are optional,
-// but any |flags| specified must be known to the system (otherwise, an error of
-// |MOJO_RESULT_UNIMPLEMENTED| should be returned).
-
-#ifndef MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
-#define MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-template <class Options>
-class UserOptionsReader {
- public:
- // Constructor from a |UserPointer<const Options>| (which it checks -- this
- // constructor has side effects!).
- // Note: We initialize |options_reader_| without checking, since we do a check
- // in |GetSizeForReader()|.
- explicit UserOptionsReader(UserPointer<const Options> options)
- : options_reader_(UserPointer<const char>::Reader::NoCheck(),
- options.template ReinterpretCast<const char>(),
- GetSizeForReader(options)) {
- static_assert(offsetof(Options, struct_size) == 0,
- "struct_size not first member of Options");
- // TODO(vtl): Enable when MSVC supports this (C++11 extended sizeof):
- // static_assert(sizeof(Options::struct_size) == sizeof(uint32_t),
- // "Options::struct_size not a uint32_t");
- // (Or maybe assert that its type is uint32_t?)
- }
-
- bool is_valid() const { return !!options_reader_.GetPointer(); }
-
- const Options& options() const {
- DCHECK(is_valid());
- return *reinterpret_cast<const Options*>(options_reader_.GetPointer());
- }
-
- // Checks that the given (variable-size) |options| passed to the constructor
- // (plausibly) has a member at the given offset with the given size. You
- // probably want to use |OPTIONS_STRUCT_HAS_MEMBER()| instead.
- bool HasMember(size_t offset, size_t size) const {
- DCHECK(is_valid());
- // We assume that |offset| and |size| are reasonable, since they should come
- // from |offsetof(Options, some_member)| and |sizeof(Options::some_member)|,
- // respectively.
- return options().struct_size >= offset + size;
- }
-
- private:
- static inline size_t GetSizeForReader(UserPointer<const Options> options) {
- uint32_t struct_size =
- options.template ReinterpretCast<const uint32_t>().Get();
- if (struct_size < sizeof(uint32_t))
- return 0;
-
- // Check the full requested size.
- // Note: Use |MOJO_ALIGNOF()| here to match the exact macro used in the
- // declaration of Options structs.
- internal::CheckUserPointerWithSize<MOJO_ALIGNOF(Options)>(options.pointer_,
- struct_size);
- options.template ReinterpretCast<const char>().CheckArray(struct_size);
- // But we'll never look at more than |sizeof(Options)| bytes.
- return std::min(static_cast<size_t>(struct_size), sizeof(Options));
- }
-
- UserPointer<const char>::Reader options_reader_;
-
- DISALLOW_COPY_AND_ASSIGN(UserOptionsReader);
-};
-
-// Macro to invoke |UserOptionsReader<Options>::HasMember()| parametrized by
-// member name instead of offset and size.
-//
-// (We can't just give |HasMember()| a member pointer template argument instead,
-// since there's no good/strictly-correct way to get an offset from that.)
-//
-// TODO(vtl): With C++11, use |sizeof(Options::member)| instead of (the
-// contortion below). We might also be able to pull out the type |Options| from
-// |reader| (using |decltype|) instead of requiring a parameter.
-#define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \
- reader.HasMember(offsetof(Options, member), sizeof(reader.options().member))
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
diff --git a/mojo/edk/system/options_validation_unittest.cc b/mojo/edk/system/options_validation_unittest.cc
deleted file mode 100644
index 89c4e60..0000000
--- a/mojo/edk/system/options_validation_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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/options_validation.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "mojo/public/c/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-// Declare a test options struct just as we do in actual public headers.
-
-typedef uint32_t TestOptionsFlags;
-
-static_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment");
-struct MOJO_ALIGNAS(8) TestOptions {
- uint32_t struct_size;
- TestOptionsFlags flags;
- uint32_t member1;
- uint32_t member2;
-};
-static_assert(sizeof(TestOptions) == 16, "TestOptions has wrong size");
-
-const uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions));
-
-TEST(OptionsValidationTest, Valid) {
- {
- const TestOptions kOptions = {kSizeOfTestOptions};
- UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
- EXPECT_TRUE(reader.is_valid());
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
- }
- {
- const TestOptions kOptions = {static_cast<uint32_t>(
- offsetof(TestOptions, struct_size) + sizeof(uint32_t))};
- UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
- EXPECT_TRUE(reader.is_valid());
- EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
- EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
- EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
- }
-
- {
- const TestOptions kOptions = {
- static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))};
- UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions));
- EXPECT_TRUE(reader.is_valid());
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
- EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
- EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
- }
- {
- MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
- TestOptions* options = reinterpret_cast<TestOptions*>(buf);
- options->struct_size = kSizeOfTestOptions + 1;
- UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
- EXPECT_TRUE(reader.is_valid());
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
- }
- {
- MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
- TestOptions* options = reinterpret_cast<TestOptions*>(buf);
- options->struct_size = kSizeOfTestOptions + 4;
- UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
- EXPECT_TRUE(reader.is_valid());
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
- EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
- }
-}
-
-TEST(OptionsValidationTest, Invalid) {
- // Size too small:
- for (size_t i = 0; i < sizeof(uint32_t); i++) {
- TestOptions options = {static_cast<uint32_t>(i)};
- UserOptionsReader<TestOptions> reader(MakeUserPointer(&options));
- EXPECT_FALSE(reader.is_valid()) << i;
- }
-}
-
-// These test invalid arguments that should cause death if we're being paranoid
-// about checking arguments (which we would want to do if, e.g., we were in a
-// true "kernel" situation, but we might not want to do otherwise for
-// performance reasons). Probably blatant errors like passing in null pointers
-// (for required pointer arguments) will still cause death, but perhaps not
-// predictably.
-TEST(OptionsValidationTest, InvalidDeath) {
- const char kMemoryCheckFailedRegex[] = "Check failed";
-
- // Null:
- EXPECT_DEATH_IF_SUPPORTED(
- { UserOptionsReader<TestOptions> reader((NullUserPointer())); },
- kMemoryCheckFailedRegex);
-
- // Unaligned:
- EXPECT_DEATH_IF_SUPPORTED(
- {
- UserOptionsReader<TestOptions> reader(
- MakeUserPointer(reinterpret_cast<const TestOptions*>(1)));
- },
- kMemoryCheckFailedRegex);
- // Note: The current implementation checks the size only after checking the
- // alignment versus that required for the |uint32_t| size, so it won't die in
- // the expected way if you pass, e.g., 4. So we have to manufacture a valid
- // pointer at an offset of alignment 4.
- EXPECT_DEATH_IF_SUPPORTED(
- {
- uint32_t buffer[100] = {};
- TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 8 == 0)
- ? reinterpret_cast<TestOptions*>(&buffer[1])
- : reinterpret_cast<TestOptions*>(&buffer[0]);
- options->struct_size = static_cast<uint32_t>(sizeof(TestOptions));
- UserOptionsReader<TestOptions> reader(MakeUserPointer(options));
- },
- kMemoryCheckFailedRegex);
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/platform_handle_dispatcher.cc b/mojo/edk/system/platform_handle_dispatcher.cc
deleted file mode 100644
index f064c67..0000000
--- a/mojo/edk/system/platform_handle_dispatcher.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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 "base/logging.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-const size_t kInvalidPlatformHandleIndex = static_cast<size_t>(-1);
-
-struct SerializedPlatformHandleDispatcher {
- size_t platform_handle_index; // (Or |kInvalidPlatformHandleIndex|.)
-};
-
-} // namespace
-
-PlatformHandleDispatcher::PlatformHandleDispatcher(
- embedder::ScopedPlatformHandle platform_handle)
- : platform_handle_(platform_handle.Pass()) {
-}
-
-embedder::ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() {
- base::AutoLock locker(lock());
- return platform_handle_.Pass();
-}
-
-Dispatcher::Type PlatformHandleDispatcher::GetType() const {
- return kTypePlatformHandle;
-}
-
-// static
-scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
- Channel* channel,
- const void* source,
- size_t size,
- embedder::PlatformHandleVector* 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.
- embedder::PlatformHandle 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 scoped_refptr<PlatformHandleDispatcher>(new PlatformHandleDispatcher(
- embedder::ScopedPlatformHandle(platform_handle)));
-}
-
-PlatformHandleDispatcher::~PlatformHandleDispatcher() {
-}
-
-void PlatformHandleDispatcher::CloseImplNoLock() {
- lock().AssertAcquired();
- platform_handle_.reset();
-}
-
-scoped_refptr<Dispatcher>
-PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
- lock().AssertAcquired();
- return scoped_refptr<Dispatcher>(
- new PlatformHandleDispatcher(platform_handle_.Pass()));
-}
-
-void PlatformHandleDispatcher::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(SerializedPlatformHandleDispatcher);
- *max_platform_handles = 1;
-}
-
-bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock(
- Channel* /*channel*/,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) {
- DCHECK(HasOneRef()); // 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(platform_handle_.release());
- } else {
- serialization->platform_handle_index = kInvalidPlatformHandleIndex;
- }
-
- *actual_size = sizeof(SerializedPlatformHandleDispatcher);
- return true;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/platform_handle_dispatcher.h b/mojo/edk/system/platform_handle_dispatcher.h
deleted file mode 100644
index 6eb56b7..0000000
--- a/mojo/edk/system/platform_handle_dispatcher.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/simple_dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// A dispatcher that simply wraps/transports a |PlatformHandle| (only for use by
-// the embedder).
-class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher
- : public SimpleDispatcher {
- public:
- explicit PlatformHandleDispatcher(
- embedder::ScopedPlatformHandle platform_handle);
-
- embedder::ScopedPlatformHandle PassPlatformHandle();
-
- // |Dispatcher| public methods:
- Type GetType() const override;
-
- // The "opposite" of |SerializeAndClose()|. (Typically this is called by
- // |Dispatcher::Deserialize()|.)
- static scoped_refptr<PlatformHandleDispatcher> Deserialize(
- Channel* channel,
- const void* source,
- size_t size,
- embedder::PlatformHandleVector* platform_handles);
-
- private:
- ~PlatformHandleDispatcher() override;
-
- // |Dispatcher| protected methods:
- void CloseImplNoLock() override;
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
- void StartSerializeImplNoLock(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) override;
- bool EndSerializeAndCloseImplNoLock(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) override;
-
- embedder::ScopedPlatformHandle platform_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformHandleDispatcher);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc
deleted file mode 100644
index dae53b4..0000000
--- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 <stdio.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-TEST(PlatformHandleDispatcherTest, Basic) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHelloWorld[] = "hello world";
-
- base::FilePath unused;
- base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- ASSERT_TRUE(fp);
- EXPECT_EQ(sizeof(kHelloWorld),
- fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get()));
-
- embedder::ScopedPlatformHandle h(
- mojo::test::PlatformHandleFromFILE(fp.Pass()));
- EXPECT_FALSE(fp);
- ASSERT_TRUE(h.is_valid());
-
- scoped_refptr<PlatformHandleDispatcher> dispatcher(
- new PlatformHandleDispatcher(h.Pass()));
- EXPECT_FALSE(h.is_valid());
- EXPECT_EQ(Dispatcher::kTypePlatformHandle, dispatcher->GetType());
-
- h = dispatcher->PassPlatformHandle().Pass();
- EXPECT_TRUE(h.is_valid());
-
- fp = mojo::test::FILEFromPlatformHandle(h.Pass(), "rb").Pass();
- EXPECT_FALSE(h.is_valid());
- EXPECT_TRUE(fp);
-
- rewind(fp.get());
- char read_buffer[1000] = {};
- EXPECT_EQ(sizeof(kHelloWorld),
- fread(read_buffer, 1, sizeof(read_buffer), fp.get()));
- EXPECT_STREQ(kHelloWorld, read_buffer);
-
- // Try getting the handle again. (It should fail cleanly.)
- h = dispatcher->PassPlatformHandle().Pass();
- EXPECT_FALSE(h.is_valid());
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-}
-
-TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kFooBar[] = "foo bar";
-
- base::FilePath unused;
- base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get()));
-
- scoped_refptr<PlatformHandleDispatcher> dispatcher(
- new PlatformHandleDispatcher(
- mojo::test::PlatformHandleFromFILE(fp.Pass())));
-
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
- EXPECT_EQ(Dispatcher::kTypePlatformHandle, transport.GetType());
- EXPECT_FALSE(transport.IsBusy());
-
- scoped_refptr<Dispatcher> generic_dispatcher =
- transport.CreateEquivalentDispatcherAndClose();
- ASSERT_TRUE(generic_dispatcher);
-
- transport.End();
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
-
- ASSERT_EQ(Dispatcher::kTypePlatformHandle, generic_dispatcher->GetType());
- dispatcher = static_cast<PlatformHandleDispatcher*>(generic_dispatcher.get());
-
- fp = mojo::test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(),
- "rb").Pass();
- EXPECT_TRUE(fp);
-
- rewind(fp.get());
- char read_buffer[1000] = {};
- EXPECT_EQ(sizeof(kFooBar),
- fread(read_buffer, 1, sizeof(read_buffer), fp.get()));
- EXPECT_STREQ(kFooBar, read_buffer);
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.cc b/mojo/edk/system/proxy_message_pipe_endpoint.cc
deleted file mode 100644
index 5f0f2e9..0000000
--- a/mojo/edk/system/proxy_message_pipe_endpoint.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 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/proxy_message_pipe_endpoint.h"
-
-#include <string.h>
-
-#include "base/logging.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/local_message_pipe_endpoint.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-
-namespace mojo {
-namespace system {
-
-ProxyMessagePipeEndpoint::ProxyMessagePipeEndpoint(
- ChannelEndpoint* channel_endpoint)
- : channel_endpoint_(channel_endpoint) {
-}
-
-ProxyMessagePipeEndpoint::~ProxyMessagePipeEndpoint() {
- DCHECK(!channel_endpoint_);
-}
-
-scoped_refptr<ChannelEndpoint>
-ProxyMessagePipeEndpoint::ReleaseChannelEndpoint() {
- DCHECK(channel_endpoint_);
- scoped_refptr<ChannelEndpoint> rv;
- rv.swap(channel_endpoint_);
- return rv;
-}
-
-MessagePipeEndpoint::Type ProxyMessagePipeEndpoint::GetType() const {
- return kTypeProxy;
-}
-
-bool ProxyMessagePipeEndpoint::OnPeerClose() {
- DetachIfNecessary();
- return false;
-}
-
-// Note: We may have to enqueue messages even when our (local) peer isn't open
-// -- it may have been written to and closed immediately, before we were ready.
-// This case is handled in |Run()| (which will call us).
-void ProxyMessagePipeEndpoint::EnqueueMessage(
- scoped_ptr<MessageInTransit> message) {
- DCHECK(channel_endpoint_);
- LOG_IF(WARNING, !channel_endpoint_->EnqueueMessage(message.Pass()))
- << "Failed to write enqueue message to channel";
-}
-
-void ProxyMessagePipeEndpoint::Close() {
- DetachIfNecessary();
-}
-
-void ProxyMessagePipeEndpoint::DetachIfNecessary() {
- if (channel_endpoint_) {
- channel_endpoint_->DetachFromClient();
- channel_endpoint_ = nullptr;
- }
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.h b/mojo/edk/system/proxy_message_pipe_endpoint.h
deleted file mode 100644
index 6e10699..0000000
--- a/mojo/edk/system/proxy_message_pipe_endpoint.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_
-#define MOJO_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/message_pipe_endpoint.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class ChannelEndpoint;
-class LocalMessagePipeEndpoint;
-class MessagePipe;
-
-// A |ProxyMessagePipeEndpoint| is an endpoint which delegates everything to a
-// |ChannelEndpoint|, which may be co-owned by a |Channel|. Like any
-// |MessagePipeEndpoint|, a |ProxyMessagePipeEndpoint| is owned by a
-// |MessagePipe|.
-//
-// For example, a |MessagePipe| with one endpoint local and the other endpoint
-// remote consists of a |LocalMessagePipeEndpoint| and a
-// |ProxyMessagePipeEndpoint|, with only the local endpoint being accessible via
-// a |MessagePipeDispatcher|.
-class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint
- : public MessagePipeEndpoint {
- public:
- explicit ProxyMessagePipeEndpoint(ChannelEndpoint* channel_endpoint);
- ~ProxyMessagePipeEndpoint() override;
-
- // Returns |channel_endpoint_| and resets |channel_endpoint_| to null. This
- // may be called at most once, after which |Close()| need not be called.
- //
- // Note: The returned |ChannelEndpoint| must have its client changed while
- // still under |MessagePipe|'s lock (which this must have also been called
- // under).
- scoped_refptr<ChannelEndpoint> ReleaseChannelEndpoint();
-
- // |MessagePipeEndpoint| implementation:
- Type GetType() const override;
- bool OnPeerClose() override;
- void EnqueueMessage(scoped_ptr<MessageInTransit> message) override;
- void Close() override;
-
- private:
- void DetachIfNecessary();
-
- scoped_refptr<ChannelEndpoint> channel_endpoint_;
-
- DISALLOW_COPY_AND_ASSIGN(ProxyMessagePipeEndpoint);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_PROXY_MESSAGE_PIPE_ENDPOINT_H_
diff --git a/mojo/edk/system/raw_channel.cc b/mojo/edk/system/raw_channel.cc
deleted file mode 100644
index aff1110..0000000
--- a/mojo/edk/system/raw_channel.cc
+++ /dev/null
@@ -1,514 +0,0 @@
-// 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/raw_channel.h"
-
-#include <string.h>
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/transport_data.h"
-
-namespace mojo {
-namespace system {
-
-const size_t kReadSize = 4096;
-
-// RawChannel::ReadBuffer ------------------------------------------------------
-
-RawChannel::ReadBuffer::ReadBuffer() : buffer_(kReadSize), num_valid_bytes_(0) {
-}
-
-RawChannel::ReadBuffer::~ReadBuffer() {
-}
-
-void RawChannel::ReadBuffer::GetBuffer(char** addr, size_t* size) {
- DCHECK_GE(buffer_.size(), num_valid_bytes_ + kReadSize);
- *addr = &buffer_[0] + num_valid_bytes_;
- *size = kReadSize;
-}
-
-// RawChannel::WriteBuffer -----------------------------------------------------
-
-RawChannel::WriteBuffer::WriteBuffer(size_t serialized_platform_handle_size)
- : serialized_platform_handle_size_(serialized_platform_handle_size),
- platform_handles_offset_(0),
- data_offset_(0) {
-}
-
-RawChannel::WriteBuffer::~WriteBuffer() {
- STLDeleteElements(&message_queue_);
-}
-
-bool RawChannel::WriteBuffer::HavePlatformHandlesToSend() const {
- if (message_queue_.empty())
- return false;
-
- const TransportData* transport_data =
- message_queue_.front()->transport_data();
- if (!transport_data)
- return false;
-
- const embedder::PlatformHandleVector* all_platform_handles =
- transport_data->platform_handles();
- if (!all_platform_handles) {
- DCHECK_EQ(platform_handles_offset_, 0u);
- return false;
- }
- if (platform_handles_offset_ >= all_platform_handles->size()) {
- DCHECK_EQ(platform_handles_offset_, all_platform_handles->size());
- return false;
- }
-
- return true;
-}
-
-void RawChannel::WriteBuffer::GetPlatformHandlesToSend(
- size_t* num_platform_handles,
- embedder::PlatformHandle** platform_handles,
- void** serialization_data) {
- DCHECK(HavePlatformHandlesToSend());
-
- MessageInTransit* message = message_queue_.front();
- TransportData* transport_data = message->transport_data();
- embedder::PlatformHandleVector* all_platform_handles =
- transport_data->platform_handles();
- *num_platform_handles =
- all_platform_handles->size() - platform_handles_offset_;
- *platform_handles = &(*all_platform_handles)[platform_handles_offset_];
-
- if (serialized_platform_handle_size_ > 0) {
- size_t serialization_data_offset =
- transport_data->platform_handle_table_offset();
- DCHECK_GT(serialization_data_offset, 0u);
- serialization_data_offset +=
- platform_handles_offset_ * serialized_platform_handle_size_;
- *serialization_data = static_cast<char*>(transport_data->buffer()) +
- serialization_data_offset;
- } else {
- *serialization_data = nullptr;
- }
-}
-
-void RawChannel::WriteBuffer::GetBuffers(std::vector<Buffer>* buffers) const {
- buffers->clear();
-
- if (message_queue_.empty())
- return;
-
- MessageInTransit* message = message_queue_.front();
- DCHECK_LT(data_offset_, message->total_size());
- size_t bytes_to_write = message->total_size() - data_offset_;
-
- size_t transport_data_buffer_size =
- message->transport_data() ? message->transport_data()->buffer_size() : 0;
-
- if (!transport_data_buffer_size) {
- // Only write from the main buffer.
- DCHECK_LT(data_offset_, message->main_buffer_size());
- DCHECK_LE(bytes_to_write, message->main_buffer_size());
- Buffer buffer = {
- static_cast<const char*>(message->main_buffer()) + data_offset_,
- bytes_to_write};
- buffers->push_back(buffer);
- return;
- }
-
- if (data_offset_ >= message->main_buffer_size()) {
- // Only write from the transport data buffer.
- DCHECK_LT(data_offset_ - message->main_buffer_size(),
- transport_data_buffer_size);
- DCHECK_LE(bytes_to_write, transport_data_buffer_size);
- Buffer buffer = {
- static_cast<const char*>(message->transport_data()->buffer()) +
- (data_offset_ - message->main_buffer_size()),
- bytes_to_write};
- buffers->push_back(buffer);
- return;
- }
-
- // TODO(vtl): We could actually send out buffers from multiple messages, with
- // the "stopping" condition being reaching a message with platform handles
- // attached.
-
- // Write from both buffers.
- DCHECK_EQ(bytes_to_write, message->main_buffer_size() - data_offset_ +
- transport_data_buffer_size);
- Buffer buffer1 = {
- static_cast<const char*>(message->main_buffer()) + data_offset_,
- message->main_buffer_size() - data_offset_};
- buffers->push_back(buffer1);
- Buffer buffer2 = {
- static_cast<const char*>(message->transport_data()->buffer()),
- transport_data_buffer_size};
- buffers->push_back(buffer2);
-}
-
-// RawChannel ------------------------------------------------------------------
-
-RawChannel::RawChannel()
- : message_loop_for_io_(nullptr),
- delegate_(nullptr),
- read_stopped_(false),
- write_stopped_(false),
- weak_ptr_factory_(this) {
-}
-
-RawChannel::~RawChannel() {
- DCHECK(!read_buffer_);
- DCHECK(!write_buffer_);
-
- // No need to take the |write_lock_| here -- if there are still weak pointers
- // outstanding, then we're hosed anyway (since we wouldn't be able to
- // invalidate them cleanly, since we might not be on the I/O thread).
- DCHECK(!weak_ptr_factory_.HasWeakPtrs());
-}
-
-void RawChannel::Init(Delegate* delegate) {
- DCHECK(delegate);
-
- DCHECK(!delegate_);
- delegate_ = delegate;
-
- CHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_IO);
- DCHECK(!message_loop_for_io_);
- message_loop_for_io_ =
- static_cast<base::MessageLoopForIO*>(base::MessageLoop::current());
-
- // No need to take the lock. No one should be using us yet.
- DCHECK(!read_buffer_);
- read_buffer_.reset(new ReadBuffer);
- DCHECK(!write_buffer_);
- write_buffer_.reset(new WriteBuffer(GetSerializedPlatformHandleSize()));
-
- OnInit();
-
- IOResult io_result = ScheduleRead();
- if (io_result != IO_PENDING) {
- // This will notify the delegate about the read failure. Although we're on
- // the I/O thread, don't call it in the nested context.
- message_loop_for_io_->PostTask(
- FROM_HERE, base::Bind(&RawChannel::OnReadCompleted,
- weak_ptr_factory_.GetWeakPtr(), io_result, 0));
- }
- // Note: |ScheduleRead()| failure is treated as a read failure (by notifying
- // the delegate), not an initialization failure.
-}
-
-void RawChannel::Shutdown() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_);
-
- base::AutoLock locker(write_lock_);
-
- LOG_IF(WARNING, !write_buffer_->message_queue_.empty())
- << "Shutting down RawChannel with write buffer nonempty";
-
- // Reset the delegate so that it won't receive further calls.
- delegate_ = nullptr;
- read_stopped_ = true;
- write_stopped_ = true;
- weak_ptr_factory_.InvalidateWeakPtrs();
-
- OnShutdownNoLock(read_buffer_.Pass(), write_buffer_.Pass());
-}
-
-// Reminder: This must be thread-safe.
-bool RawChannel::WriteMessage(scoped_ptr<MessageInTransit> message) {
- DCHECK(message);
-
- base::AutoLock locker(write_lock_);
- if (write_stopped_)
- return false;
-
- if (!write_buffer_->message_queue_.empty()) {
- EnqueueMessageNoLock(message.Pass());
- return true;
- }
-
- EnqueueMessageNoLock(message.Pass());
- DCHECK_EQ(write_buffer_->data_offset_, 0u);
-
- size_t platform_handles_written = 0;
- size_t bytes_written = 0;
- IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written);
- if (io_result == IO_PENDING)
- return true;
-
- bool result = OnWriteCompletedNoLock(io_result, platform_handles_written,
- bytes_written);
- if (!result) {
- // Even if we're on the I/O thread, don't call |OnError()| in the nested
- // context.
- message_loop_for_io_->PostTask(
- FROM_HERE,
- base::Bind(&RawChannel::CallOnError, weak_ptr_factory_.GetWeakPtr(),
- Delegate::ERROR_WRITE));
- }
-
- return result;
-}
-
-// Reminder: This must be thread-safe.
-bool RawChannel::IsWriteBufferEmpty() {
- base::AutoLock locker(write_lock_);
- return write_buffer_->message_queue_.empty();
-}
-
-void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_);
-
- if (read_stopped_) {
- NOTREACHED();
- return;
- }
-
- // Keep reading data in a loop, and dispatch messages if enough data is
- // received. Exit the loop if any of the following happens:
- // - one or more messages were dispatched;
- // - the last read failed, was a partial read or would block;
- // - |Shutdown()| was called.
- do {
- switch (io_result) {
- case IO_SUCCEEDED:
- break;
- case IO_FAILED_SHUTDOWN:
- case IO_FAILED_BROKEN:
- case IO_FAILED_UNKNOWN:
- read_stopped_ = true;
- CallOnError(ReadIOResultToError(io_result));
- return;
- case IO_PENDING:
- NOTREACHED();
- return;
- }
-
- read_buffer_->num_valid_bytes_ += bytes_read;
-
- // Dispatch all the messages that we can.
- bool did_dispatch_message = false;
- // Tracks the offset of the first undispatched message in |read_buffer_|.
- // Currently, we copy data to ensure that this is zero at the beginning.
- size_t read_buffer_start = 0;
- size_t remaining_bytes = read_buffer_->num_valid_bytes_;
- size_t message_size;
- // Note that we rely on short-circuit evaluation here:
- // - |read_buffer_start| may be an invalid index into
- // |read_buffer_->buffer_| if |remaining_bytes| is zero.
- // - |message_size| is only valid if |GetNextMessageSize()| returns true.
- // TODO(vtl): Use |message_size| more intelligently (e.g., to request the
- // next read).
- // TODO(vtl): Validate that |message_size| is sane.
- while (remaining_bytes > 0 && MessageInTransit::GetNextMessageSize(
- &read_buffer_->buffer_[read_buffer_start],
- remaining_bytes, &message_size) &&
- remaining_bytes >= message_size) {
- MessageInTransit::View message_view(
- message_size, &read_buffer_->buffer_[read_buffer_start]);
- DCHECK_EQ(message_view.total_size(), message_size);
-
- const char* error_message = nullptr;
- if (!message_view.IsValid(GetSerializedPlatformHandleSize(),
- &error_message)) {
- DCHECK(error_message);
- LOG(ERROR) << "Received invalid message: " << error_message;
- read_stopped_ = true;
- CallOnError(Delegate::ERROR_READ_BAD_MESSAGE);
- return;
- }
-
- if (message_view.type() == MessageInTransit::kTypeRawChannel) {
- if (!OnReadMessageForRawChannel(message_view)) {
- read_stopped_ = true;
- CallOnError(Delegate::ERROR_READ_BAD_MESSAGE);
- return;
- }
- } else {
- embedder::ScopedPlatformHandleVectorPtr platform_handles;
- if (message_view.transport_data_buffer()) {
- size_t num_platform_handles;
- const void* platform_handle_table;
- TransportData::GetPlatformHandleTable(
- message_view.transport_data_buffer(), &num_platform_handles,
- &platform_handle_table);
-
- if (num_platform_handles > 0) {
- platform_handles =
- GetReadPlatformHandles(num_platform_handles,
- platform_handle_table).Pass();
- if (!platform_handles) {
- LOG(ERROR) << "Invalid number of platform handles received";
- read_stopped_ = true;
- CallOnError(Delegate::ERROR_READ_BAD_MESSAGE);
- return;
- }
- }
- }
-
- // TODO(vtl): In the case that we aren't expecting any platform handles,
- // for the POSIX implementation, we should confirm that none are stored.
-
- // Dispatch the message.
- DCHECK(delegate_);
- delegate_->OnReadMessage(message_view, platform_handles.Pass());
- if (read_stopped_) {
- // |Shutdown()| was called in |OnReadMessage()|.
- // TODO(vtl): Add test for this case.
- return;
- }
- }
-
- did_dispatch_message = true;
-
- // Update our state.
- read_buffer_start += message_size;
- remaining_bytes -= message_size;
- }
-
- if (read_buffer_start > 0) {
- // Move data back to start.
- read_buffer_->num_valid_bytes_ = remaining_bytes;
- if (read_buffer_->num_valid_bytes_ > 0) {
- memmove(&read_buffer_->buffer_[0],
- &read_buffer_->buffer_[read_buffer_start], remaining_bytes);
- }
- read_buffer_start = 0;
- }
-
- if (read_buffer_->buffer_.size() - read_buffer_->num_valid_bytes_ <
- kReadSize) {
- // Use power-of-2 buffer sizes.
- // TODO(vtl): Make sure the buffer doesn't get too large (and enforce the
- // maximum message size to whatever extent necessary).
- // TODO(vtl): We may often be able to peek at the header and get the real
- // required extra space (which may be much bigger than |kReadSize|).
- size_t new_size = std::max(read_buffer_->buffer_.size(), kReadSize);
- while (new_size < read_buffer_->num_valid_bytes_ + kReadSize)
- new_size *= 2;
-
- // TODO(vtl): It's suboptimal to zero out the fresh memory.
- read_buffer_->buffer_.resize(new_size, 0);
- }
-
- // (1) If we dispatched any messages, stop reading for now (and let the
- // message loop do its thing for another round).
- // TODO(vtl): Is this the behavior we want? (Alternatives: i. Dispatch only
- // a single message. Risks: slower, more complex if we want to avoid lots of
- // copying. ii. Keep reading until there's no more data and dispatch all the
- // messages we can. Risks: starvation of other users of the message loop.)
- // (2) If we didn't max out |kReadSize|, stop reading for now.
- bool schedule_for_later = did_dispatch_message || bytes_read < kReadSize;
- bytes_read = 0;
- io_result = schedule_for_later ? ScheduleRead() : Read(&bytes_read);
- } while (io_result != IO_PENDING);
-}
-
-void RawChannel::OnWriteCompleted(IOResult io_result,
- size_t platform_handles_written,
- size_t bytes_written) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_);
- DCHECK_NE(io_result, IO_PENDING);
-
- bool did_fail = false;
- {
- base::AutoLock locker(write_lock_);
- DCHECK_EQ(write_stopped_, write_buffer_->message_queue_.empty());
-
- if (write_stopped_) {
- NOTREACHED();
- return;
- }
-
- did_fail = !OnWriteCompletedNoLock(io_result, platform_handles_written,
- bytes_written);
- }
-
- if (did_fail)
- CallOnError(Delegate::ERROR_WRITE);
-}
-
-void RawChannel::EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) {
- write_lock_.AssertAcquired();
- write_buffer_->message_queue_.push_back(message.release());
-}
-
-bool RawChannel::OnReadMessageForRawChannel(
- const MessageInTransit::View& message_view) {
- // No non-implementation specific |RawChannel| control messages.
- LOG(ERROR) << "Invalid control message (subtype " << message_view.subtype()
- << ")";
- return false;
-}
-
-// static
-RawChannel::Delegate::Error RawChannel::ReadIOResultToError(
- IOResult io_result) {
- switch (io_result) {
- case IO_FAILED_SHUTDOWN:
- return Delegate::ERROR_READ_SHUTDOWN;
- case IO_FAILED_BROKEN:
- return Delegate::ERROR_READ_BROKEN;
- case IO_FAILED_UNKNOWN:
- return Delegate::ERROR_READ_UNKNOWN;
- case IO_SUCCEEDED:
- case IO_PENDING:
- NOTREACHED();
- break;
- }
- return Delegate::ERROR_READ_UNKNOWN;
-}
-
-void RawChannel::CallOnError(Delegate::Error error) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_);
- // TODO(vtl): Add a "write_lock_.AssertNotAcquired()"?
- if (delegate_)
- delegate_->OnError(error);
-}
-
-bool RawChannel::OnWriteCompletedNoLock(IOResult io_result,
- size_t platform_handles_written,
- size_t bytes_written) {
- write_lock_.AssertAcquired();
-
- DCHECK(!write_stopped_);
- DCHECK(!write_buffer_->message_queue_.empty());
-
- if (io_result == IO_SUCCEEDED) {
- write_buffer_->platform_handles_offset_ += platform_handles_written;
- write_buffer_->data_offset_ += bytes_written;
-
- MessageInTransit* message = write_buffer_->message_queue_.front();
- if (write_buffer_->data_offset_ >= message->total_size()) {
- // Complete write.
- CHECK_EQ(write_buffer_->data_offset_, message->total_size());
- write_buffer_->message_queue_.pop_front();
- delete message;
- write_buffer_->platform_handles_offset_ = 0;
- write_buffer_->data_offset_ = 0;
-
- if (write_buffer_->message_queue_.empty())
- return true;
- }
-
- // Schedule the next write.
- io_result = ScheduleWriteNoLock();
- if (io_result == IO_PENDING)
- return true;
- DCHECK_NE(io_result, IO_SUCCEEDED);
- }
-
- write_stopped_ = true;
- STLDeleteElements(&write_buffer_->message_queue_);
- write_buffer_->platform_handles_offset_ = 0;
- write_buffer_->data_offset_ = 0;
- return false;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/raw_channel.h b/mojo/edk/system/raw_channel.h
deleted file mode 100644
index f567767..0000000
--- a/mojo/edk/system/raw_channel.h
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_RAW_CHANNEL_H_
-#define MOJO_EDK_SYSTEM_RAW_CHANNEL_H_
-
-#include <deque>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace base {
-class MessageLoopForIO;
-}
-
-namespace mojo {
-namespace system {
-
-// |RawChannel| is an interface and base class for objects that wrap an OS
-// "pipe". It presents the following interface to users:
-// - Receives and dispatches messages on an I/O thread (running a
-// |MessageLoopForIO|.
-// - Provides a thread-safe way of writing messages (|WriteMessage()|);
-// writing/queueing messages will not block and is atomic from the point of
-// view of the caller. If necessary, messages are queued (to be written on
-// the aforementioned thread).
-//
-// OS-specific implementation subclasses are to be instantiated using the
-// |Create()| static factory method.
-//
-// With the exception of |WriteMessage()|, this class is thread-unsafe (and in
-// general its methods should only be used on the I/O thread, i.e., the thread
-// on which |Init()| is called).
-class MOJO_SYSTEM_IMPL_EXPORT RawChannel {
- public:
- virtual ~RawChannel();
-
- // The |Delegate| is only accessed on the same thread as the message loop
- // (passed in on creation).
- class MOJO_SYSTEM_IMPL_EXPORT Delegate {
- public:
- enum Error {
- // Failed read due to raw channel shutdown (e.g., on the other side).
- ERROR_READ_SHUTDOWN,
- // Failed read due to raw channel being broken (e.g., if the other side
- // died without shutting down).
- ERROR_READ_BROKEN,
- // Received a bad message.
- ERROR_READ_BAD_MESSAGE,
- // Unknown read error.
- ERROR_READ_UNKNOWN,
- // Generic write error.
- ERROR_WRITE
- };
-
- // Called when a message is read. This may call |Shutdown()| (on the
- // |RawChannel|), but must not destroy it.
- virtual void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) = 0;
-
- // Called when there's a (fatal) error. This may call the raw channel's
- // |Shutdown()|, but must not destroy it.
- //
- // For each raw channel, there'll be at most one |ERROR_READ_...| and at
- // most one |ERROR_WRITE| notification. After |OnError(ERROR_READ_...)|,
- // |OnReadMessage()| won't be called again.
- virtual void OnError(Error error) = 0;
-
- protected:
- virtual ~Delegate() {}
- };
-
- // Static factory method. |handle| should be a handle to a
- // (platform-appropriate) bidirectional communication channel (e.g., a socket
- // on POSIX, a named pipe on Windows).
- static scoped_ptr<RawChannel> Create(embedder::ScopedPlatformHandle handle);
-
- // This must be called (on an I/O thread) before this object is used. Does
- // *not* take ownership of |delegate|. Both the I/O thread and |delegate| must
- // remain alive until |Shutdown()| is called (unless this fails); |delegate|
- // will no longer be used after |Shutdown()|.
- void Init(Delegate* delegate);
-
- // This must be called (on the I/O thread) before this object is destroyed.
- void Shutdown();
-
- // Writes the given message (or schedules it to be written). |message| must
- // have no |Dispatcher|s still attached (i.e.,
- // |SerializeAndCloseDispatchers()| should have been called). This method is
- // thread-safe and may be called from any thread. Returns true on success.
- bool WriteMessage(scoped_ptr<MessageInTransit> message);
-
- // Returns true if the write buffer is empty (i.e., all messages written using
- // |WriteMessage()| have actually been sent.
- // TODO(vtl): We should really also notify our delegate when the write buffer
- // becomes empty (or something like that).
- bool IsWriteBufferEmpty();
-
- // Returns the amount of space needed in the |MessageInTransit|'s
- // |TransportData|'s "platform handle table" per platform handle (to be
- // attached to a message). (This amount may be zero.)
- virtual size_t GetSerializedPlatformHandleSize() const = 0;
-
- protected:
- // Result of I/O operations.
- enum IOResult {
- IO_SUCCEEDED,
- // Failed due to a (probably) clean shutdown (e.g., of the other end).
- IO_FAILED_SHUTDOWN,
- // Failed due to the connection being broken (e.g., the other end dying).
- IO_FAILED_BROKEN,
- // Failed due to some other (unexpected) reason.
- IO_FAILED_UNKNOWN,
- IO_PENDING
- };
-
- class MOJO_SYSTEM_IMPL_EXPORT ReadBuffer {
- public:
- ReadBuffer();
- ~ReadBuffer();
-
- void GetBuffer(char** addr, size_t* size);
-
- private:
- friend class RawChannel;
-
- // We store data from |[Schedule]Read()|s in |buffer_|. The start of
- // |buffer_| is always aligned with a message boundary (we will copy memory
- // to ensure this), but |buffer_| may be larger than the actual number of
- // bytes we have.
- std::vector<char> buffer_;
- size_t num_valid_bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadBuffer);
- };
-
- class MOJO_SYSTEM_IMPL_EXPORT WriteBuffer {
- public:
- struct Buffer {
- const char* addr;
- size_t size;
- };
-
- explicit WriteBuffer(size_t serialized_platform_handle_size);
- ~WriteBuffer();
-
- // Returns true if there are (more) platform handles to be sent (from the
- // front of |message_queue_|).
- bool HavePlatformHandlesToSend() const;
- // Gets platform handles to be sent (from the front of |message_queue_|).
- // This should only be called if |HavePlatformHandlesToSend()| returned
- // true. There are two components to this: the actual |PlatformHandle|s
- // (which should be closed once sent) and any additional serialization
- // information (which will be embedded in the message's data; there are
- // |GetSerializedPlatformHandleSize()| bytes per handle). Once all platform
- // handles have been sent, the message data should be written next (see
- // |GetBuffers()|).
- void GetPlatformHandlesToSend(size_t* num_platform_handles,
- embedder::PlatformHandle** platform_handles,
- void** serialization_data);
-
- // Gets buffers to be written. These buffers will always come from the front
- // of |message_queue_|. Once they are completely written, the front
- // |MessageInTransit| should be popped (and destroyed); this is done in
- // |OnWriteCompletedNoLock()|.
- void GetBuffers(std::vector<Buffer>* buffers) const;
-
- private:
- friend class RawChannel;
-
- const size_t serialized_platform_handle_size_;
-
- // TODO(vtl): When C++11 is available, switch this to a deque of
- // |scoped_ptr|/|unique_ptr|s.
- std::deque<MessageInTransit*> message_queue_;
- // Platform handles are sent before the message data, but doing so may
- // require several passes. |platform_handles_offset_| indicates the position
- // in the first message's vector of platform handles to send next.
- size_t platform_handles_offset_;
- // The first message's data may have been partially sent. |data_offset_|
- // indicates the position in the first message's data to start the next
- // write.
- size_t data_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(WriteBuffer);
- };
-
- RawChannel();
-
- // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT
- // |write_lock_| held.
- void OnReadCompleted(IOResult io_result, size_t bytes_read);
- // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT
- // |write_lock_| held.
- void OnWriteCompleted(IOResult io_result,
- size_t platform_handles_written,
- size_t bytes_written);
-
- base::MessageLoopForIO* message_loop_for_io() { return message_loop_for_io_; }
- base::Lock& write_lock() { return write_lock_; }
-
- // Should only be called on the I/O thread.
- ReadBuffer* read_buffer() { return read_buffer_.get(); }
-
- // Only called under |write_lock_|.
- WriteBuffer* write_buffer_no_lock() {
- write_lock_.AssertAcquired();
- return write_buffer_.get();
- }
-
- // Adds |message| to the write message queue. Implementation subclasses may
- // override this to add any additional "control" messages needed. This is
- // called (on any thread) with |write_lock_| held.
- virtual void EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message);
-
- // Handles any control messages targeted to the |RawChannel| (or
- // implementation subclass). Implementation subclasses may override this to
- // handle any implementation-specific control messages, but should call
- // |RawChannel::OnReadMessageForRawChannel()| for any remaining messages.
- // Returns true on success and false on error (e.g., invalid control message).
- // This is only called on the I/O thread.
- virtual bool OnReadMessageForRawChannel(
- const MessageInTransit::View& message_view);
-
- // Reads into |read_buffer()|.
- // This class guarantees that:
- // - the area indicated by |GetBuffer()| will stay valid until read completion
- // (but please also see the comments for |OnShutdownNoLock()|);
- // - a second read is not started if there is a pending read;
- // - the method is called on the I/O thread WITHOUT |write_lock_| held.
- //
- // The implementing subclass must guarantee that:
- // - |bytes_read| is untouched unless |Read()| returns |IO_SUCCEEDED|;
- // - if the method returns |IO_PENDING|, |OnReadCompleted()| will be called on
- // the I/O thread to report the result, unless |Shutdown()| is called.
- virtual IOResult Read(size_t* bytes_read) = 0;
- // Similar to |Read()|, except that the implementing subclass must also
- // guarantee that the method doesn't succeed synchronously, i.e., it only
- // returns |IO_FAILED_...| or |IO_PENDING|.
- virtual IOResult ScheduleRead() = 0;
-
- // Called by |OnReadCompleted()| to get the platform handles associated with
- // the given platform handle table (from a message). This should only be
- // called when |num_platform_handles| is nonzero. Returns null if the
- // |num_platform_handles| handles are not available. Only called on the I/O
- // thread (without |write_lock_| held).
- virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* platform_handle_table) = 0;
-
- // Writes contents in |write_buffer_no_lock()|.
- // This class guarantees that:
- // - the |PlatformHandle|s given by |GetPlatformHandlesToSend()| and the
- // buffer(s) given by |GetBuffers()| will remain valid until write
- // completion (see also the comments for |OnShutdownNoLock()|);
- // - a second write is not started if there is a pending write;
- // - the method is called under |write_lock_|.
- //
- // The implementing subclass must guarantee that:
- // - |platform_handles_written| and |bytes_written| are untouched unless
- // |WriteNoLock()| returns |IO_SUCCEEDED|;
- // - if the method returns |IO_PENDING|, |OnWriteCompleted()| will be called
- // on the I/O thread to report the result, unless |Shutdown()| is called.
- virtual IOResult WriteNoLock(size_t* platform_handles_written,
- size_t* bytes_written) = 0;
- // Similar to |WriteNoLock()|, except that the implementing subclass must also
- // guarantee that the method doesn't succeed synchronously, i.e., it only
- // returns |IO_FAILED_...| or |IO_PENDING|.
- virtual IOResult ScheduleWriteNoLock() = 0;
-
- // Must be called on the I/O thread WITHOUT |write_lock_| held.
- virtual void OnInit() = 0;
- // On shutdown, passes the ownership of the buffers to subclasses, which may
- // want to preserve them if there are pending read/write. Must be called on
- // the I/O thread under |write_lock_|.
- virtual void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) = 0;
-
- private:
- // Converts an |IO_FAILED_...| for a read to a |Delegate::Error|.
- static Delegate::Error ReadIOResultToError(IOResult io_result);
-
- // Calls |delegate_->OnError(error)|. Must be called on the I/O thread WITHOUT
- // |write_lock_| held.
- void CallOnError(Delegate::Error error);
-
- // If |io_result| is |IO_SUCCESS|, updates the write buffer and schedules a
- // write operation to run later if there is more to write. If |io_result| is
- // failure or any other error occurs, cancels pending writes and returns
- // false. Must be called under |write_lock_| and only if |write_stopped_| is
- // false.
- bool OnWriteCompletedNoLock(IOResult io_result,
- size_t platform_handles_written,
- size_t bytes_written);
-
- // Set in |Init()| and never changed (hence usable on any thread without
- // locking):
- base::MessageLoopForIO* message_loop_for_io_;
-
- // Only used on the I/O thread:
- Delegate* delegate_;
- bool read_stopped_;
- scoped_ptr<ReadBuffer> read_buffer_;
-
- base::Lock write_lock_; // Protects the following members.
- bool write_stopped_;
- scoped_ptr<WriteBuffer> write_buffer_;
-
- // This is used for posting tasks from write threads to the I/O thread. It
- // must only be accessed under |write_lock_|. The weak pointers it produces
- // are only used/invalidated on the I/O thread.
- base::WeakPtrFactory<RawChannel> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannel);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_RAW_CHANNEL_H_
diff --git a/mojo/edk/system/raw_channel_posix.cc b/mojo/edk/system/raw_channel_posix.cc
deleted file mode 100644
index 078f8cb..0000000
--- a/mojo/edk/system/raw_channel_posix.cc
+++ /dev/null
@@ -1,469 +0,0 @@
-// Copyright 2013 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/raw_channel.h"
-
-#include <errno.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <deque>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/system/transport_data.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-class RawChannelPosix : public RawChannel,
- public base::MessageLoopForIO::Watcher {
- public:
- explicit RawChannelPosix(embedder::ScopedPlatformHandle handle);
- ~RawChannelPosix() override;
-
- // |RawChannel| public methods:
- size_t GetSerializedPlatformHandleSize() const override;
-
- private:
- // |RawChannel| protected methods:
- // Actually override this so that we can send multiple messages with (only)
- // FDs if necessary.
- void EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) override;
- // Override this to handle those extra FD-only messages.
- bool OnReadMessageForRawChannel(
- const MessageInTransit::View& message_view) override;
- IOResult Read(size_t* bytes_read) override;
- IOResult ScheduleRead() override;
- embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* platform_handle_table) override;
- IOResult WriteNoLock(size_t* platform_handles_written,
- size_t* bytes_written) override;
- IOResult ScheduleWriteNoLock() override;
- void OnInit() override;
- void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) override;
-
- // |base::MessageLoopForIO::Watcher| implementation:
- void OnFileCanReadWithoutBlocking(int fd) override;
- void OnFileCanWriteWithoutBlocking(int fd) override;
-
- // Implements most of |Read()| (except for a bit of clean-up):
- IOResult ReadImpl(size_t* bytes_read);
-
- // Watches for |fd_| to become writable. Must be called on the I/O thread.
- void WaitToWrite();
-
- embedder::ScopedPlatformHandle fd_;
-
- // The following members are only used on the I/O thread:
- scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_;
- scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_;
-
- bool pending_read_;
-
- std::deque<embedder::PlatformHandle> read_platform_handles_;
-
- // The following members are used on multiple threads and protected by
- // |write_lock()|:
- bool pending_write_;
-
- // This is used for posting tasks from write threads to the I/O thread. It
- // must only be accessed under |write_lock_|. The weak pointers it produces
- // are only used/invalidated on the I/O thread.
- base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannelPosix);
-};
-
-RawChannelPosix::RawChannelPosix(embedder::ScopedPlatformHandle handle)
- : fd_(handle.Pass()),
- pending_read_(false),
- pending_write_(false),
- weak_ptr_factory_(this) {
- DCHECK(fd_.is_valid());
-}
-
-RawChannelPosix::~RawChannelPosix() {
- DCHECK(!pending_read_);
- DCHECK(!pending_write_);
-
- // No need to take the |write_lock()| here -- if there are still weak pointers
- // outstanding, then we're hosed anyway (since we wouldn't be able to
- // invalidate them cleanly, since we might not be on the I/O thread).
- DCHECK(!weak_ptr_factory_.HasWeakPtrs());
-
- // These must have been shut down/destroyed on the I/O thread.
- DCHECK(!read_watcher_);
- DCHECK(!write_watcher_);
-
- embedder::CloseAllPlatformHandles(&read_platform_handles_);
-}
-
-size_t RawChannelPosix::GetSerializedPlatformHandleSize() const {
- // We don't actually need any space on POSIX (since we just send FDs).
- return 0;
-}
-
-void RawChannelPosix::EnqueueMessageNoLock(
- scoped_ptr<MessageInTransit> message) {
- if (message->transport_data()) {
- embedder::PlatformHandleVector* const platform_handles =
- message->transport_data()->platform_handles();
- if (platform_handles &&
- platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) {
- // We can't attach all the FDs to a single message, so we have to "split"
- // the message. Send as many control messages as needed first with FDs
- // attached (and no data).
- size_t i = 0;
- for (; platform_handles->size() - i >
- embedder::kPlatformChannelMaxNumHandles;
- i += embedder::kPlatformChannelMaxNumHandles) {
- scoped_ptr<MessageInTransit> fd_message(new MessageInTransit(
- MessageInTransit::kTypeRawChannel,
- MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles, 0,
- nullptr));
- embedder::ScopedPlatformHandleVectorPtr fds(
- new embedder::PlatformHandleVector(
- platform_handles->begin() + i,
- platform_handles->begin() + i +
- embedder::kPlatformChannelMaxNumHandles));
- fd_message->SetTransportData(
- make_scoped_ptr(new TransportData(fds.Pass())));
- RawChannel::EnqueueMessageNoLock(fd_message.Pass());
- }
-
- // Remove the handles that we "moved" into the other messages.
- platform_handles->erase(platform_handles->begin(),
- platform_handles->begin() + i);
- }
- }
-
- RawChannel::EnqueueMessageNoLock(message.Pass());
-}
-
-bool RawChannelPosix::OnReadMessageForRawChannel(
- const MessageInTransit::View& message_view) {
- DCHECK_EQ(message_view.type(), MessageInTransit::kTypeRawChannel);
-
- if (message_view.subtype() ==
- MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles) {
- // We don't need to do anything. |RawChannel| won't extract the platform
- // handles, and they'll be accumulated in |Read()|.
- return true;
- }
-
- return RawChannel::OnReadMessageForRawChannel(message_view);
-}
-
-RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- DCHECK(!pending_read_);
-
- IOResult rv = ReadImpl(bytes_read);
- if (rv != IO_SUCCEEDED && rv != IO_PENDING) {
- // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again.
- read_watcher_.reset();
- }
- return rv;
-}
-
-RawChannel::IOResult RawChannelPosix::ScheduleRead() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- DCHECK(!pending_read_);
-
- pending_read_ = true;
-
- return IO_PENDING;
-}
-
-embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* /*platform_handle_table*/) {
- DCHECK_GT(num_platform_handles, 0u);
-
- if (read_platform_handles_.size() < num_platform_handles) {
- embedder::CloseAllPlatformHandles(&read_platform_handles_);
- read_platform_handles_.clear();
- return embedder::ScopedPlatformHandleVectorPtr();
- }
-
- embedder::ScopedPlatformHandleVectorPtr rv(
- new embedder::PlatformHandleVector(num_platform_handles));
- rv->assign(read_platform_handles_.begin(),
- read_platform_handles_.begin() + num_platform_handles);
- read_platform_handles_.erase(
- read_platform_handles_.begin(),
- read_platform_handles_.begin() + num_platform_handles);
- return rv.Pass();
-}
-
-RawChannel::IOResult RawChannelPosix::WriteNoLock(
- size_t* platform_handles_written,
- size_t* bytes_written) {
- write_lock().AssertAcquired();
-
- DCHECK(!pending_write_);
-
- size_t num_platform_handles = 0;
- ssize_t write_result;
- if (write_buffer_no_lock()->HavePlatformHandlesToSend()) {
- embedder::PlatformHandle* platform_handles;
- void* serialization_data; // Actually unused.
- write_buffer_no_lock()->GetPlatformHandlesToSend(
- &num_platform_handles, &platform_handles, &serialization_data);
- DCHECK_GT(num_platform_handles, 0u);
- DCHECK_LE(num_platform_handles, embedder::kPlatformChannelMaxNumHandles);
- DCHECK(platform_handles);
-
- // TODO(vtl): Reduce code duplication. (This is duplicated from below.)
- std::vector<WriteBuffer::Buffer> buffers;
- write_buffer_no_lock()->GetBuffers(&buffers);
- DCHECK(!buffers.empty());
- const size_t kMaxBufferCount = 10;
- iovec iov[kMaxBufferCount];
- size_t buffer_count = std::min(buffers.size(), kMaxBufferCount);
- for (size_t i = 0; i < buffer_count; ++i) {
- iov[i].iov_base = const_cast<char*>(buffers[i].addr);
- iov[i].iov_len = buffers[i].size;
- }
-
- write_result = embedder::PlatformChannelSendmsgWithHandles(
- fd_.get(), iov, buffer_count, platform_handles, num_platform_handles);
- for (size_t i = 0; i < num_platform_handles; i++)
- platform_handles[i].CloseIfNecessary();
- } else {
- std::vector<WriteBuffer::Buffer> buffers;
- write_buffer_no_lock()->GetBuffers(&buffers);
- DCHECK(!buffers.empty());
-
- if (buffers.size() == 1) {
- write_result = embedder::PlatformChannelWrite(fd_.get(), buffers[0].addr,
- buffers[0].size);
- } else {
- const size_t kMaxBufferCount = 10;
- iovec iov[kMaxBufferCount];
- size_t buffer_count = std::min(buffers.size(), kMaxBufferCount);
- for (size_t i = 0; i < buffer_count; ++i) {
- iov[i].iov_base = const_cast<char*>(buffers[i].addr);
- iov[i].iov_len = buffers[i].size;
- }
-
- write_result =
- embedder::PlatformChannelWritev(fd_.get(), iov, buffer_count);
- }
- }
-
- if (write_result >= 0) {
- *platform_handles_written = num_platform_handles;
- *bytes_written = static_cast<size_t>(write_result);
- return IO_SUCCEEDED;
- }
-
- if (errno == EPIPE)
- return IO_FAILED_SHUTDOWN;
-
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- PLOG(WARNING) << "sendmsg/write/writev";
- return IO_FAILED_UNKNOWN;
- }
-
- return ScheduleWriteNoLock();
-}
-
-RawChannel::IOResult RawChannelPosix::ScheduleWriteNoLock() {
- write_lock().AssertAcquired();
-
- DCHECK(!pending_write_);
-
- // Set up to wait for the FD to become writable.
- // If we're not on the I/O thread, we have to post a task to do this.
- if (base::MessageLoop::current() != message_loop_for_io()) {
- message_loop_for_io()->PostTask(FROM_HERE,
- base::Bind(&RawChannelPosix::WaitToWrite,
- weak_ptr_factory_.GetWeakPtr()));
- pending_write_ = true;
- return IO_PENDING;
- }
-
- if (message_loop_for_io()->WatchFileDescriptor(
- fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE,
- write_watcher_.get(), this)) {
- pending_write_ = true;
- return IO_PENDING;
- }
-
- return IO_FAILED_UNKNOWN;
-}
-
-void RawChannelPosix::OnInit() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
-
- DCHECK(!read_watcher_);
- read_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher());
- DCHECK(!write_watcher_);
- write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher());
-
- // I don't know how this can fail (unless |fd_| is bad, in which case it's a
- // bug in our code). I also don't know if |WatchFileDescriptor()| actually
- // fails cleanly.
- CHECK(message_loop_for_io()->WatchFileDescriptor(
- fd_.get().fd, true, base::MessageLoopForIO::WATCH_READ,
- read_watcher_.get(), this));
-}
-
-void RawChannelPosix::OnShutdownNoLock(
- scoped_ptr<ReadBuffer> /*read_buffer*/,
- scoped_ptr<WriteBuffer> /*write_buffer*/) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- write_lock().AssertAcquired();
-
- read_watcher_.reset(); // This will stop watching (if necessary).
- write_watcher_.reset(); // This will stop watching (if necessary).
-
- pending_read_ = false;
- pending_write_ = false;
-
- DCHECK(fd_.is_valid());
- fd_.reset();
-
- weak_ptr_factory_.InvalidateWeakPtrs();
-}
-
-void RawChannelPosix::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK_EQ(fd, fd_.get().fd);
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
-
- if (!pending_read_) {
- NOTREACHED();
- return;
- }
-
- pending_read_ = false;
- size_t bytes_read = 0;
- IOResult io_result = Read(&bytes_read);
- if (io_result != IO_PENDING)
- OnReadCompleted(io_result, bytes_read);
-
- // On failure, |read_watcher_| must have been reset; on success,
- // we assume that |OnReadCompleted()| always schedules another read.
- // Otherwise, we could end up spinning -- getting
- // |OnFileCanReadWithoutBlocking()| again and again but not doing any actual
- // read.
- // TODO(yzshen): An alternative is to stop watching if RawChannel doesn't
- // schedule a new read. But that code won't be reached under the current
- // RawChannel implementation.
- DCHECK(!read_watcher_ || pending_read_);
-}
-
-void RawChannelPosix::OnFileCanWriteWithoutBlocking(int fd) {
- DCHECK_EQ(fd, fd_.get().fd);
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
-
- IOResult io_result;
- size_t platform_handles_written = 0;
- size_t bytes_written = 0;
- {
- base::AutoLock locker(write_lock());
-
- DCHECK(pending_write_);
-
- pending_write_ = false;
- io_result = WriteNoLock(&platform_handles_written, &bytes_written);
- }
-
- if (io_result != IO_PENDING)
- OnWriteCompleted(io_result, platform_handles_written, bytes_written);
-}
-
-RawChannel::IOResult RawChannelPosix::ReadImpl(size_t* bytes_read) {
- char* buffer = nullptr;
- size_t bytes_to_read = 0;
- read_buffer()->GetBuffer(&buffer, &bytes_to_read);
-
- size_t old_num_platform_handles = read_platform_handles_.size();
- ssize_t read_result = embedder::PlatformChannelRecvmsg(
- fd_.get(), buffer, bytes_to_read, &read_platform_handles_);
- if (read_platform_handles_.size() > old_num_platform_handles) {
- DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles,
- embedder::kPlatformChannelMaxNumHandles);
-
- // We should never accumulate more than |TransportData::kMaxPlatformHandles
- // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is
- // possible because we could have accumulated all the handles for a message,
- // then received the message data plus the first set of handles for the next
- // message in the subsequent |recvmsg()|.)
- if (read_platform_handles_.size() >
- (TransportData::GetMaxPlatformHandles() +
- embedder::kPlatformChannelMaxNumHandles)) {
- LOG(ERROR) << "Received too many platform handles";
- embedder::CloseAllPlatformHandles(&read_platform_handles_);
- read_platform_handles_.clear();
- return IO_FAILED_UNKNOWN;
- }
- }
-
- if (read_result > 0) {
- *bytes_read = static_cast<size_t>(read_result);
- return IO_SUCCEEDED;
- }
-
- // |read_result == 0| means "end of file".
- if (read_result == 0)
- return IO_FAILED_SHUTDOWN;
-
- if (errno == EAGAIN || errno == EWOULDBLOCK)
- return ScheduleRead();
-
- if (errno == ECONNRESET)
- return IO_FAILED_BROKEN;
-
- PLOG(WARNING) << "recvmsg";
- return IO_FAILED_UNKNOWN;
-}
-
-void RawChannelPosix::WaitToWrite() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
-
- DCHECK(write_watcher_);
-
- if (!message_loop_for_io()->WatchFileDescriptor(
- fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE,
- write_watcher_.get(), this)) {
- {
- base::AutoLock locker(write_lock());
-
- DCHECK(pending_write_);
- pending_write_ = false;
- }
- OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0);
- }
-}
-
-} // namespace
-
-// -----------------------------------------------------------------------------
-
-// Static factory method declared in raw_channel.h.
-// static
-scoped_ptr<RawChannel> RawChannel::Create(
- embedder::ScopedPlatformHandle handle) {
- return make_scoped_ptr(new RawChannelPosix(handle.Pass()));
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/raw_channel_unittest.cc b/mojo/edk/system/raw_channel_unittest.cc
deleted file mode 100644
index a8cbcba..0000000
--- a/mojo/edk/system/raw_channel_unittest.cc
+++ /dev/null
@@ -1,805 +0,0 @@
-// 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/raw_channel.h"
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/rand_util.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_io_thread.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h" // TODO(vtl): Remove this.
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/message_in_transit.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/transport_data.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-scoped_ptr<MessageInTransit> MakeTestMessage(uint32_t num_bytes) {
- std::vector<unsigned char> bytes(num_bytes, 0);
- for (size_t i = 0; i < num_bytes; i++)
- bytes[i] = static_cast<unsigned char>(i + num_bytes);
- return make_scoped_ptr(new MessageInTransit(
- MessageInTransit::kTypeEndpoint, MessageInTransit::kSubtypeEndpointData,
- num_bytes, bytes.empty() ? nullptr : &bytes[0]));
-}
-
-bool CheckMessageData(const void* bytes, uint32_t num_bytes) {
- const unsigned char* b = static_cast<const unsigned char*>(bytes);
- for (uint32_t i = 0; i < num_bytes; i++) {
- if (b[i] != static_cast<unsigned char>(i + num_bytes))
- return false;
- }
- return true;
-}
-
-void InitOnIOThread(RawChannel* raw_channel, RawChannel::Delegate* delegate) {
- raw_channel->Init(delegate);
-}
-
-bool WriteTestMessageToHandle(const embedder::PlatformHandle& handle,
- uint32_t num_bytes) {
- scoped_ptr<MessageInTransit> message(MakeTestMessage(num_bytes));
-
- size_t write_size = 0;
- mojo::test::BlockingWrite(handle, message->main_buffer(),
- message->main_buffer_size(), &write_size);
- return write_size == message->main_buffer_size();
-}
-
-// -----------------------------------------------------------------------------
-
-class RawChannelTest : public testing::Test {
- public:
- RawChannelTest() : io_thread_(base::TestIOThread::kManualStart) {}
- ~RawChannelTest() override {}
-
- void SetUp() override {
- embedder::PlatformChannelPair channel_pair;
- handles[0] = channel_pair.PassServerHandle();
- handles[1] = channel_pair.PassClientHandle();
- io_thread_.Start();
- }
-
- void TearDown() override {
- io_thread_.Stop();
- handles[0].reset();
- handles[1].reset();
- }
-
- protected:
- base::TestIOThread* io_thread() { return &io_thread_; }
-
- embedder::ScopedPlatformHandle handles[2];
-
- private:
- base::TestIOThread io_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannelTest);
-};
-
-// RawChannelTest.WriteMessage -------------------------------------------------
-
-class WriteOnlyRawChannelDelegate : public RawChannel::Delegate {
- public:
- WriteOnlyRawChannelDelegate() {}
- ~WriteOnlyRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation:
- void OnReadMessage(
- const MessageInTransit::View& /*message_view*/,
- embedder::ScopedPlatformHandleVectorPtr /*platform_handles*/) override {
- CHECK(false); // Should not get called.
- }
- void OnError(Error error) override {
- // We'll get a read (shutdown) error when the connection is closed.
- CHECK_EQ(error, ERROR_READ_SHUTDOWN);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WriteOnlyRawChannelDelegate);
-};
-
-static const int64_t kMessageReaderSleepMs = 1;
-static const size_t kMessageReaderMaxPollIterations = 3000;
-
-class TestMessageReaderAndChecker {
- public:
- explicit TestMessageReaderAndChecker(embedder::PlatformHandle handle)
- : handle_(handle) {}
- ~TestMessageReaderAndChecker() { CHECK(bytes_.empty()); }
-
- bool ReadAndCheckNextMessage(uint32_t expected_size) {
- unsigned char buffer[4096];
-
- for (size_t i = 0; i < kMessageReaderMaxPollIterations;) {
- size_t read_size = 0;
- CHECK(mojo::test::NonBlockingRead(handle_, buffer, sizeof(buffer),
- &read_size));
-
- // Append newly-read data to |bytes_|.
- bytes_.insert(bytes_.end(), buffer, buffer + read_size);
-
- // If we have the header....
- size_t message_size;
- if (MessageInTransit::GetNextMessageSize(
- bytes_.empty() ? nullptr : &bytes_[0], bytes_.size(),
- &message_size)) {
- // If we've read the whole message....
- if (bytes_.size() >= message_size) {
- bool rv = true;
- MessageInTransit::View message_view(message_size, &bytes_[0]);
- CHECK_EQ(message_view.main_buffer_size(), message_size);
-
- if (message_view.num_bytes() != expected_size) {
- LOG(ERROR) << "Wrong size: " << message_size << " instead of "
- << expected_size << " bytes.";
- rv = false;
- } else if (!CheckMessageData(message_view.bytes(),
- message_view.num_bytes())) {
- LOG(ERROR) << "Incorrect message bytes.";
- rv = false;
- }
-
- // Erase message data.
- bytes_.erase(bytes_.begin(),
- bytes_.begin() + message_view.main_buffer_size());
- return rv;
- }
- }
-
- if (static_cast<size_t>(read_size) < sizeof(buffer)) {
- i++;
- base::PlatformThread::Sleep(
- base::TimeDelta::FromMilliseconds(kMessageReaderSleepMs));
- }
- }
-
- LOG(ERROR) << "Too many iterations.";
- return false;
- }
-
- private:
- const embedder::PlatformHandle handle_;
-
- // The start of the received data should always be on a message boundary.
- std::vector<unsigned char> bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(TestMessageReaderAndChecker);
-};
-
-// Tests writing (and verifies reading using our own custom reader).
-TEST_F(RawChannelTest, WriteMessage) {
- WriteOnlyRawChannelDelegate delegate;
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- TestMessageReaderAndChecker checker(handles[1].get());
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Write and read, for a variety of sizes.
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) {
- EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size)));
- EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size;
- }
-
- // Write/queue and read afterwards, for a variety of sizes.
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1)
- EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size)));
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1)
- EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size;
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get())));
-}
-
-// RawChannelTest.OnReadMessage ------------------------------------------------
-
-class ReadCheckerRawChannelDelegate : public RawChannel::Delegate {
- public:
- ReadCheckerRawChannelDelegate() : done_event_(false, false), position_(0) {}
- ~ReadCheckerRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation (called on the I/O thread):
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override {
- EXPECT_FALSE(platform_handles);
-
- size_t position;
- size_t expected_size;
- bool should_signal = false;
- {
- base::AutoLock locker(lock_);
- CHECK_LT(position_, expected_sizes_.size());
- position = position_;
- expected_size = expected_sizes_[position];
- position_++;
- if (position_ >= expected_sizes_.size())
- should_signal = true;
- }
-
- EXPECT_EQ(expected_size, message_view.num_bytes()) << position;
- if (message_view.num_bytes() == expected_size) {
- EXPECT_TRUE(
- CheckMessageData(message_view.bytes(), message_view.num_bytes()))
- << position;
- }
-
- if (should_signal)
- done_event_.Signal();
- }
- void OnError(Error error) override {
- // We'll get a read (shutdown) error when the connection is closed.
- CHECK_EQ(error, ERROR_READ_SHUTDOWN);
- }
-
- // Waits for all the messages (of sizes |expected_sizes_|) to be seen.
- void Wait() { done_event_.Wait(); }
-
- void SetExpectedSizes(const std::vector<uint32_t>& expected_sizes) {
- base::AutoLock locker(lock_);
- CHECK_EQ(position_, expected_sizes_.size());
- expected_sizes_ = expected_sizes;
- position_ = 0;
- }
-
- private:
- base::WaitableEvent done_event_;
-
- base::Lock lock_; // Protects the following members.
- std::vector<uint32_t> expected_sizes_;
- size_t position_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadCheckerRawChannelDelegate);
-};
-
-// Tests reading (writing using our own custom writer).
-TEST_F(RawChannelTest, OnReadMessage) {
- ReadCheckerRawChannelDelegate delegate;
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Write and read, for a variety of sizes.
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) {
- delegate.SetExpectedSizes(std::vector<uint32_t>(1, size));
-
- EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size));
-
- delegate.Wait();
- }
-
- // Set up reader and write as fast as we can.
- // Write/queue and read afterwards, for a variety of sizes.
- std::vector<uint32_t> expected_sizes;
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1)
- expected_sizes.push_back(size);
- delegate.SetExpectedSizes(expected_sizes);
- for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1)
- EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size));
- delegate.Wait();
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get())));
-}
-
-// RawChannelTest.WriteMessageAndOnReadMessage ---------------------------------
-
-class RawChannelWriterThread : public base::SimpleThread {
- public:
- RawChannelWriterThread(RawChannel* raw_channel, size_t write_count)
- : base::SimpleThread("raw_channel_writer_thread"),
- raw_channel_(raw_channel),
- left_to_write_(write_count) {}
-
- ~RawChannelWriterThread() override { Join(); }
-
- private:
- void Run() override {
- static const int kMaxRandomMessageSize = 25000;
-
- while (left_to_write_-- > 0) {
- EXPECT_TRUE(raw_channel_->WriteMessage(MakeTestMessage(
- static_cast<uint32_t>(base::RandInt(1, kMaxRandomMessageSize)))));
- }
- }
-
- RawChannel* const raw_channel_;
- size_t left_to_write_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannelWriterThread);
-};
-
-class ReadCountdownRawChannelDelegate : public RawChannel::Delegate {
- public:
- explicit ReadCountdownRawChannelDelegate(size_t expected_count)
- : done_event_(false, false), expected_count_(expected_count), count_(0) {}
- ~ReadCountdownRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation (called on the I/O thread):
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override {
- EXPECT_FALSE(platform_handles);
-
- EXPECT_LT(count_, expected_count_);
- count_++;
-
- EXPECT_TRUE(
- CheckMessageData(message_view.bytes(), message_view.num_bytes()));
-
- if (count_ >= expected_count_)
- done_event_.Signal();
- }
- void OnError(Error error) override {
- // We'll get a read (shutdown) error when the connection is closed.
- CHECK_EQ(error, ERROR_READ_SHUTDOWN);
- }
-
- // Waits for all the messages to have been seen.
- void Wait() { done_event_.Wait(); }
-
- private:
- base::WaitableEvent done_event_;
- size_t expected_count_;
- size_t count_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadCountdownRawChannelDelegate);
-};
-
-TEST_F(RawChannelTest, WriteMessageAndOnReadMessage) {
- static const size_t kNumWriterThreads = 10;
- static const size_t kNumWriteMessagesPerThread = 4000;
-
- WriteOnlyRawChannelDelegate writer_delegate;
- scoped_ptr<RawChannel> writer_rc(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&InitOnIOThread, writer_rc.get(),
- base::Unretained(&writer_delegate)));
-
- ReadCountdownRawChannelDelegate reader_delegate(kNumWriterThreads *
- kNumWriteMessagesPerThread);
- scoped_ptr<RawChannel> reader_rc(RawChannel::Create(handles[1].Pass()));
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&InitOnIOThread, reader_rc.get(),
- base::Unretained(&reader_delegate)));
-
- {
- ScopedVector<RawChannelWriterThread> writer_threads;
- for (size_t i = 0; i < kNumWriterThreads; i++) {
- writer_threads.push_back(new RawChannelWriterThread(
- writer_rc.get(), kNumWriteMessagesPerThread));
- }
- for (size_t i = 0; i < writer_threads.size(); i++)
- writer_threads[i]->Start();
- } // Joins all the writer threads.
-
- // Sleep a bit, to let any extraneous reads be processed. (There shouldn't be
- // any, but we want to know about them.)
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
-
- // Wait for reading to finish.
- reader_delegate.Wait();
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RawChannel::Shutdown, base::Unretained(reader_rc.get())));
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RawChannel::Shutdown, base::Unretained(writer_rc.get())));
-}
-
-// RawChannelTest.OnError ------------------------------------------------------
-
-class ErrorRecordingRawChannelDelegate
- : public ReadCountdownRawChannelDelegate {
- public:
- ErrorRecordingRawChannelDelegate(size_t expected_read_count,
- bool expect_read_error,
- bool expect_write_error)
- : ReadCountdownRawChannelDelegate(expected_read_count),
- got_read_error_event_(false, false),
- got_write_error_event_(false, false),
- expecting_read_error_(expect_read_error),
- expecting_write_error_(expect_write_error) {}
-
- ~ErrorRecordingRawChannelDelegate() override {}
-
- void OnError(Error error) override {
- switch (error) {
- case ERROR_READ_SHUTDOWN:
- ASSERT_TRUE(expecting_read_error_);
- expecting_read_error_ = false;
- got_read_error_event_.Signal();
- break;
- case ERROR_READ_BROKEN:
- // TODO(vtl): Test broken connections.
- CHECK(false);
- break;
- case ERROR_READ_BAD_MESSAGE:
- // TODO(vtl): Test reception/detection of bad messages.
- CHECK(false);
- break;
- case ERROR_READ_UNKNOWN:
- // TODO(vtl): Test however it is we might get here.
- CHECK(false);
- break;
- case ERROR_WRITE:
- ASSERT_TRUE(expecting_write_error_);
- expecting_write_error_ = false;
- got_write_error_event_.Signal();
- break;
- }
- }
-
- void WaitForReadError() { got_read_error_event_.Wait(); }
- void WaitForWriteError() { got_write_error_event_.Wait(); }
-
- private:
- base::WaitableEvent got_read_error_event_;
- base::WaitableEvent got_write_error_event_;
-
- bool expecting_read_error_;
- bool expecting_write_error_;
-
- DISALLOW_COPY_AND_ASSIGN(ErrorRecordingRawChannelDelegate);
-};
-
-// Tests (fatal) errors.
-TEST_F(RawChannelTest, OnError) {
- ErrorRecordingRawChannelDelegate delegate(0, true, true);
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Close the handle of the other end, which should make writing fail.
- handles[1].reset();
-
- EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1)));
-
- // We should get a write error.
- delegate.WaitForWriteError();
-
- // We should also get a read error.
- delegate.WaitForReadError();
-
- EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(2)));
-
- // Sleep a bit, to make sure we don't get another |OnError()|
- // notification. (If we actually get another one, |OnError()| crashes.)
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get())));
-}
-
-// RawChannelTest.ReadUnaffectedByWriteError -----------------------------------
-
-TEST_F(RawChannelTest, ReadUnaffectedByWriteError) {
- const size_t kMessageCount = 5;
-
- // Write a few messages into the other end.
- uint32_t message_size = 1;
- for (size_t i = 0; i < kMessageCount;
- i++, message_size += message_size / 2 + 1)
- EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), message_size));
-
- // Close the other end, which should make writing fail.
- handles[1].reset();
-
- // Only start up reading here. The system buffer should still contain the
- // messages that were written.
- ErrorRecordingRawChannelDelegate delegate(kMessageCount, true, true);
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1)));
-
- // We should definitely get a write error.
- delegate.WaitForWriteError();
-
- // Wait for reading to finish. A writing failure shouldn't affect reading.
- delegate.Wait();
-
- // And then we should get a read error.
- delegate.WaitForReadError();
-
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get())));
-}
-
-// RawChannelTest.WriteMessageAfterShutdown ------------------------------------
-
-// Makes sure that calling |WriteMessage()| after |Shutdown()| behaves
-// correctly.
-TEST_F(RawChannelTest, WriteMessageAfterShutdown) {
- WriteOnlyRawChannelDelegate delegate;
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
- io_thread()->PostTaskAndWait(
- FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc.get())));
-
- EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1)));
-}
-
-// RawChannelTest.ShutdownOnReadMessage ----------------------------------------
-
-class ShutdownOnReadMessageRawChannelDelegate : public RawChannel::Delegate {
- public:
- explicit ShutdownOnReadMessageRawChannelDelegate(RawChannel* raw_channel)
- : raw_channel_(raw_channel),
- done_event_(false, false),
- did_shutdown_(false) {}
- ~ShutdownOnReadMessageRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation (called on the I/O thread):
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override {
- EXPECT_FALSE(platform_handles);
- EXPECT_FALSE(did_shutdown_);
- EXPECT_TRUE(
- CheckMessageData(message_view.bytes(), message_view.num_bytes()));
- raw_channel_->Shutdown();
- did_shutdown_ = true;
- done_event_.Signal();
- }
- void OnError(Error /*error*/) override {
- CHECK(false); // Should not get called.
- }
-
- // Waits for shutdown.
- void Wait() {
- done_event_.Wait();
- EXPECT_TRUE(did_shutdown_);
- }
-
- private:
- RawChannel* const raw_channel_;
- base::WaitableEvent done_event_;
- bool did_shutdown_;
-
- DISALLOW_COPY_AND_ASSIGN(ShutdownOnReadMessageRawChannelDelegate);
-};
-
-TEST_F(RawChannelTest, ShutdownOnReadMessage) {
- // Write a few messages into the other end.
- for (size_t count = 0; count < 5; count++)
- EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10));
-
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- ShutdownOnReadMessageRawChannelDelegate delegate(rc.get());
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Wait for the delegate, which will shut the |RawChannel| down.
- delegate.Wait();
-}
-
-// RawChannelTest.ShutdownOnError{Read, Write} ---------------------------------
-
-class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate {
- public:
- ShutdownOnErrorRawChannelDelegate(RawChannel* raw_channel,
- Error shutdown_on_error_type)
- : raw_channel_(raw_channel),
- shutdown_on_error_type_(shutdown_on_error_type),
- done_event_(false, false),
- did_shutdown_(false) {}
- ~ShutdownOnErrorRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation (called on the I/O thread):
- void OnReadMessage(
- const MessageInTransit::View& /*message_view*/,
- embedder::ScopedPlatformHandleVectorPtr /*platform_handles*/) override {
- CHECK(false); // Should not get called.
- }
- void OnError(Error error) override {
- EXPECT_FALSE(did_shutdown_);
- if (error != shutdown_on_error_type_)
- return;
- raw_channel_->Shutdown();
- did_shutdown_ = true;
- done_event_.Signal();
- }
-
- // Waits for shutdown.
- void Wait() {
- done_event_.Wait();
- EXPECT_TRUE(did_shutdown_);
- }
-
- private:
- RawChannel* const raw_channel_;
- const Error shutdown_on_error_type_;
- base::WaitableEvent done_event_;
- bool did_shutdown_;
-
- DISALLOW_COPY_AND_ASSIGN(ShutdownOnErrorRawChannelDelegate);
-};
-
-TEST_F(RawChannelTest, ShutdownOnErrorRead) {
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- ShutdownOnErrorRawChannelDelegate delegate(
- rc.get(), RawChannel::Delegate::ERROR_READ_SHUTDOWN);
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Close the handle of the other end, which should stuff fail.
- handles[1].reset();
-
- // Wait for the delegate, which will shut the |RawChannel| down.
- delegate.Wait();
-}
-
-TEST_F(RawChannelTest, ShutdownOnErrorWrite) {
- scoped_ptr<RawChannel> rc(RawChannel::Create(handles[0].Pass()));
- ShutdownOnErrorRawChannelDelegate delegate(rc.get(),
- RawChannel::Delegate::ERROR_WRITE);
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate)));
-
- // Close the handle of the other end, which should stuff fail.
- handles[1].reset();
-
- EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1)));
-
- // Wait for the delegate, which will shut the |RawChannel| down.
- delegate.Wait();
-}
-
-// RawChannelTest.ReadWritePlatformHandles -------------------------------------
-
-class ReadPlatformHandlesCheckerRawChannelDelegate
- : public RawChannel::Delegate {
- public:
- ReadPlatformHandlesCheckerRawChannelDelegate() : done_event_(false, false) {}
- ~ReadPlatformHandlesCheckerRawChannelDelegate() override {}
-
- // |RawChannel::Delegate| implementation (called on the I/O thread):
- void OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) override {
- const char kHello[] = "hello";
-
- EXPECT_EQ(sizeof(kHello), message_view.num_bytes());
- EXPECT_STREQ(kHello, static_cast<const char*>(message_view.bytes()));
-
- ASSERT_TRUE(platform_handles);
- ASSERT_EQ(2u, platform_handles->size());
- embedder::ScopedPlatformHandle h1(platform_handles->at(0));
- EXPECT_TRUE(h1.is_valid());
- embedder::ScopedPlatformHandle h2(platform_handles->at(1));
- EXPECT_TRUE(h2.is_valid());
- platform_handles->clear();
-
- {
- char buffer[100] = {};
-
- base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h1.Pass(), "rb"));
- EXPECT_TRUE(fp);
- rewind(fp.get());
- EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get()));
- EXPECT_EQ('1', buffer[0]);
- }
-
- {
- char buffer[100] = {};
- base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h2.Pass(), "rb"));
- EXPECT_TRUE(fp);
- rewind(fp.get());
- EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get()));
- EXPECT_EQ('2', buffer[0]);
- }
-
- done_event_.Signal();
- }
- void OnError(Error error) override {
- // We'll get a read (shutdown) error when the connection is closed.
- CHECK_EQ(error, ERROR_READ_SHUTDOWN);
- }
-
- void Wait() { done_event_.Wait(); }
-
- private:
- base::WaitableEvent done_event_;
-
- DISALLOW_COPY_AND_ASSIGN(ReadPlatformHandlesCheckerRawChannelDelegate);
-};
-
-#if defined(OS_POSIX)
-#define MAYBE_ReadWritePlatformHandles ReadWritePlatformHandles
-#else
-// Not yet implemented (on Windows).
-#define MAYBE_ReadWritePlatformHandles DISABLED_ReadWritePlatformHandles
-#endif
-TEST_F(RawChannelTest, MAYBE_ReadWritePlatformHandles) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- WriteOnlyRawChannelDelegate write_delegate;
- scoped_ptr<RawChannel> rc_write(RawChannel::Create(handles[0].Pass()));
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&InitOnIOThread, rc_write.get(),
- base::Unretained(&write_delegate)));
-
- ReadPlatformHandlesCheckerRawChannelDelegate read_delegate;
- scoped_ptr<RawChannel> rc_read(RawChannel::Create(handles[1].Pass()));
- io_thread()->PostTaskAndWait(FROM_HERE,
- base::Bind(&InitOnIOThread, rc_read.get(),
- base::Unretained(&read_delegate)));
-
- base::FilePath unused;
- base::ScopedFILE fp1(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- EXPECT_EQ(1u, fwrite("1", 1, 1, fp1.get()));
- base::ScopedFILE fp2(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- EXPECT_EQ(1u, fwrite("2", 1, 1, fp2.get()));
-
- {
- const char kHello[] = "hello";
- embedder::ScopedPlatformHandleVectorPtr platform_handles(
- new embedder::PlatformHandleVector());
- platform_handles->push_back(
- mojo::test::PlatformHandleFromFILE(fp1.Pass()).release());
- platform_handles->push_back(
- mojo::test::PlatformHandleFromFILE(fp2.Pass()).release());
-
- scoped_ptr<MessageInTransit> message(new MessageInTransit(
- MessageInTransit::kTypeEndpoint, MessageInTransit::kSubtypeEndpointData,
- sizeof(kHello), kHello));
- message->SetTransportData(
- make_scoped_ptr(new TransportData(platform_handles.Pass())));
- EXPECT_TRUE(rc_write->WriteMessage(message.Pass()));
- }
-
- read_delegate.Wait();
-
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RawChannel::Shutdown, base::Unretained(rc_read.get())));
- io_thread()->PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RawChannel::Shutdown, base::Unretained(rc_write.get())));
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/raw_channel_win.cc b/mojo/edk/system/raw_channel_win.cc
deleted file mode 100644
index 7ec7ad7..0000000
--- a/mojo/edk/system/raw_channel_win.cc
+++ /dev/null
@@ -1,576 +0,0 @@
-// Copyright 2013 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/raw_channel.h"
-
-#include <windows.h>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "base/win/windows_version.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-namespace mojo {
-namespace system {
-
-namespace {
-
-class VistaOrHigherFunctions {
- public:
- VistaOrHigherFunctions();
-
- bool is_vista_or_higher() const { return is_vista_or_higher_; }
-
- BOOL SetFileCompletionNotificationModes(HANDLE handle, UCHAR flags) {
- return set_file_completion_notification_modes_(handle, flags);
- }
-
- BOOL CancelIoEx(HANDLE handle, LPOVERLAPPED overlapped) {
- return cancel_io_ex_(handle, overlapped);
- }
-
- private:
- typedef BOOL(WINAPI* SetFileCompletionNotificationModesFunc)(HANDLE, UCHAR);
- typedef BOOL(WINAPI* CancelIoExFunc)(HANDLE, LPOVERLAPPED);
-
- bool is_vista_or_higher_;
- SetFileCompletionNotificationModesFunc
- set_file_completion_notification_modes_;
- CancelIoExFunc cancel_io_ex_;
-};
-
-VistaOrHigherFunctions::VistaOrHigherFunctions()
- : is_vista_or_higher_(base::win::GetVersion() >= base::win::VERSION_VISTA),
- set_file_completion_notification_modes_(nullptr),
- cancel_io_ex_(nullptr) {
- if (!is_vista_or_higher_)
- return;
-
- HMODULE module = GetModuleHandleW(L"kernel32.dll");
- set_file_completion_notification_modes_ =
- reinterpret_cast<SetFileCompletionNotificationModesFunc>(
- GetProcAddress(module, "SetFileCompletionNotificationModes"));
- DCHECK(set_file_completion_notification_modes_);
-
- cancel_io_ex_ =
- reinterpret_cast<CancelIoExFunc>(GetProcAddress(module, "CancelIoEx"));
- DCHECK(cancel_io_ex_);
-}
-
-base::LazyInstance<VistaOrHigherFunctions> g_vista_or_higher_functions =
- LAZY_INSTANCE_INITIALIZER;
-
-class RawChannelWin : public RawChannel {
- public:
- RawChannelWin(embedder::ScopedPlatformHandle handle);
- ~RawChannelWin() override;
-
- // |RawChannel| public methods:
- size_t GetSerializedPlatformHandleSize() const override;
-
- private:
- // RawChannelIOHandler receives OS notifications for I/O completion. It must
- // be created on the I/O thread.
- //
- // It manages its own destruction. Destruction happens on the I/O thread when
- // all the following conditions are satisfied:
- // - |DetachFromOwnerNoLock()| has been called;
- // - there is no pending read;
- // - there is no pending write.
- class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler {
- public:
- RawChannelIOHandler(RawChannelWin* owner,
- embedder::ScopedPlatformHandle handle);
-
- HANDLE handle() const { return handle_.get().handle; }
-
- // The following methods are only called by the owner on the I/O thread.
- bool pending_read() const;
- base::MessageLoopForIO::IOContext* read_context();
- // Instructs the object to wait for an |OnIOCompleted()| notification.
- void OnPendingReadStarted();
-
- // The following methods are only called by the owner under
- // |owner_->write_lock()|.
- bool pending_write_no_lock() const;
- base::MessageLoopForIO::IOContext* write_context_no_lock();
- // Instructs the object to wait for an |OnIOCompleted()| notification.
- void OnPendingWriteStartedNoLock();
-
- // |base::MessageLoopForIO::IOHandler| implementation:
- // Must be called on the I/O thread. It could be called before or after
- // detached from the owner.
- void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
- DWORD bytes_transferred,
- DWORD error) override;
-
- // Must be called on the I/O thread under |owner_->write_lock()|.
- // After this call, the owner must not make any further calls on this
- // object, and therefore the object is used on the I/O thread exclusively
- // (if it stays alive).
- void DetachFromOwnerNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer);
-
- private:
- ~RawChannelIOHandler() override;
-
- // Returns true if |owner_| has been reset and there is not pending read or
- // write.
- // Must be called on the I/O thread.
- bool ShouldSelfDestruct() const;
-
- // Must be called on the I/O thread. It may be called before or after
- // detaching from the owner.
- void OnReadCompleted(DWORD bytes_read, DWORD error);
- // Must be called on the I/O thread. It may be called before or after
- // detaching from the owner.
- void OnWriteCompleted(DWORD bytes_written, DWORD error);
-
- embedder::ScopedPlatformHandle handle_;
-
- // |owner_| is reset on the I/O thread under |owner_->write_lock()|.
- // Therefore, it may be used on any thread under lock; or on the I/O thread
- // without locking.
- RawChannelWin* owner_;
-
- // The following members must be used on the I/O thread.
- scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_;
- scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_;
- bool suppress_self_destruct_;
-
- bool pending_read_;
- base::MessageLoopForIO::IOContext read_context_;
-
- // The following members must be used under |owner_->write_lock()| while the
- // object is still attached to the owner, and only on the I/O thread
- // afterwards.
- bool pending_write_;
- base::MessageLoopForIO::IOContext write_context_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler);
- };
-
- // |RawChannel| private methods:
- IOResult Read(size_t* bytes_read) override;
- IOResult ScheduleRead() override;
- embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* platform_handle_table) override;
- IOResult WriteNoLock(size_t* platform_handles_written,
- size_t* bytes_written) override;
- IOResult ScheduleWriteNoLock() override;
- void OnInit() override;
- void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) override;
-
- // Passed to |io_handler_| during initialization.
- embedder::ScopedPlatformHandle handle_;
-
- RawChannelIOHandler* io_handler_;
-
- const bool skip_completion_port_on_success_;
-
- DISALLOW_COPY_AND_ASSIGN(RawChannelWin);
-};
-
-RawChannelWin::RawChannelIOHandler::RawChannelIOHandler(
- RawChannelWin* owner,
- embedder::ScopedPlatformHandle handle)
- : handle_(handle.Pass()),
- owner_(owner),
- suppress_self_destruct_(false),
- pending_read_(false),
- pending_write_(false) {
- memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
- read_context_.handler = this;
- memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
- write_context_.handler = this;
-
- owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this);
-}
-
-RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() {
- DCHECK(ShouldSelfDestruct());
-}
-
-bool RawChannelWin::RawChannelIOHandler::pending_read() const {
- DCHECK(owner_);
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
- return pending_read_;
-}
-
-base::MessageLoopForIO::IOContext*
-RawChannelWin::RawChannelIOHandler::read_context() {
- DCHECK(owner_);
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
- return &read_context_;
-}
-
-void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() {
- DCHECK(owner_);
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
- DCHECK(!pending_read_);
- pending_read_ = true;
-}
-
-bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- return pending_write_;
-}
-
-base::MessageLoopForIO::IOContext*
-RawChannelWin::RawChannelIOHandler::write_context_no_lock() {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- return &write_context_;
-}
-
-void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock() {
- DCHECK(owner_);
- owner_->write_lock().AssertAcquired();
- DCHECK(!pending_write_);
- pending_write_ = true;
-}
-
-void RawChannelWin::RawChannelIOHandler::OnIOCompleted(
- base::MessageLoopForIO::IOContext* context,
- DWORD bytes_transferred,
- DWORD error) {
- DCHECK(!owner_ ||
- base::MessageLoop::current() == owner_->message_loop_for_io());
-
- {
- // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they
- // result in a call to |Shutdown()|).
- base::AutoReset<bool> resetter(&suppress_self_destruct_, true);
-
- if (context == &read_context_)
- OnReadCompleted(bytes_transferred, error);
- else if (context == &write_context_)
- OnWriteCompleted(bytes_transferred, error);
- else
- NOTREACHED();
- }
-
- if (ShouldSelfDestruct())
- delete this;
-}
-
-void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock(
- scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) {
- DCHECK(owner_);
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
- owner_->write_lock().AssertAcquired();
-
- // If read/write is pending, we have to retain the corresponding buffer.
- if (pending_read_)
- preserved_read_buffer_after_detach_ = read_buffer.Pass();
- if (pending_write_)
- preserved_write_buffer_after_detach_ = write_buffer.Pass();
-
- owner_ = nullptr;
- if (ShouldSelfDestruct())
- delete this;
-}
-
-bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const {
- if (owner_ || suppress_self_destruct_)
- return false;
-
- // Note: Detached, hence no lock needed for |pending_write_|.
- return !pending_read_ && !pending_write_;
-}
-
-void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read,
- DWORD error) {
- DCHECK(!owner_ ||
- base::MessageLoop::current() == owner_->message_loop_for_io());
- DCHECK(suppress_self_destruct_);
-
- CHECK(pending_read_);
- pending_read_ = false;
- if (!owner_)
- return;
-
- if (error == ERROR_SUCCESS) {
- DCHECK_GT(bytes_read, 0u);
- owner_->OnReadCompleted(IO_SUCCEEDED, bytes_read);
- } else if (error == ERROR_BROKEN_PIPE) {
- DCHECK_EQ(bytes_read, 0u);
- owner_->OnReadCompleted(IO_FAILED_SHUTDOWN, 0);
- } else {
- DCHECK_EQ(bytes_read, 0u);
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error);
- owner_->OnReadCompleted(IO_FAILED_UNKNOWN, 0);
- }
-}
-
-void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written,
- DWORD error) {
- DCHECK(!owner_ ||
- base::MessageLoop::current() == owner_->message_loop_for_io());
- DCHECK(suppress_self_destruct_);
-
- if (!owner_) {
- // No lock needed.
- CHECK(pending_write_);
- pending_write_ = false;
- return;
- }
-
- {
- base::AutoLock locker(owner_->write_lock());
- CHECK(pending_write_);
- pending_write_ = false;
- }
-
- if (error == ERROR_SUCCESS) {
- owner_->OnWriteCompleted(IO_SUCCEEDED, 0, bytes_written);
- } else if (error == ERROR_BROKEN_PIPE) {
- owner_->OnWriteCompleted(IO_FAILED_SHUTDOWN, 0, 0);
- } else {
- LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error);
- owner_->OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0);
- }
-}
-
-RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle)
- : handle_(handle.Pass()),
- io_handler_(nullptr),
- skip_completion_port_on_success_(
- g_vista_or_higher_functions.Get().is_vista_or_higher()) {
- DCHECK(handle_.is_valid());
-}
-
-RawChannelWin::~RawChannelWin() {
- DCHECK(!io_handler_);
-}
-
-size_t RawChannelWin::GetSerializedPlatformHandleSize() const {
- // TODO(vtl): Implement.
- return 0;
-}
-
-RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_read());
-
- char* buffer = nullptr;
- size_t bytes_to_read = 0;
- read_buffer()->GetBuffer(&buffer, &bytes_to_read);
-
- BOOL result =
- ReadFile(io_handler_->handle(), buffer, static_cast<DWORD>(bytes_to_read),
- nullptr, &io_handler_->read_context()->overlapped);
- if (!result) {
- DWORD error = GetLastError();
- if (error == ERROR_BROKEN_PIPE)
- return IO_FAILED_SHUTDOWN;
- if (error != ERROR_IO_PENDING) {
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error);
- return IO_FAILED_UNKNOWN;
- }
- }
-
- if (result && skip_completion_port_on_success_) {
- DWORD bytes_read_dword = 0;
- BOOL get_size_result = GetOverlappedResult(
- io_handler_->handle(), &io_handler_->read_context()->overlapped,
- &bytes_read_dword, FALSE);
- DPCHECK(get_size_result);
- *bytes_read = bytes_read_dword;
- return IO_SUCCEEDED;
- }
-
- // If the read is pending or the read has succeeded but we don't skip
- // completion port on success, instruct |io_handler_| to wait for the
- // completion packet.
- //
- // TODO(yzshen): It seems there isn't document saying that all error cases
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
- // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()|
- // will crash so we will learn about it.
-
- io_handler_->OnPendingReadStarted();
- return IO_PENDING;
-}
-
-RawChannel::IOResult RawChannelWin::ScheduleRead() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_read());
-
- size_t bytes_read = 0;
- IOResult io_result = Read(&bytes_read);
- if (io_result == IO_SUCCEEDED) {
- DCHECK(skip_completion_port_on_success_);
-
- // We have finished reading successfully. Queue a notification manually.
- io_handler_->OnPendingReadStarted();
- // |io_handler_| won't go away before the task is run, so it is safe to use
- // |base::Unretained()|.
- message_loop_for_io()->PostTask(
- FROM_HERE, base::Bind(&RawChannelIOHandler::OnIOCompleted,
- base::Unretained(io_handler_),
- base::Unretained(io_handler_->read_context()),
- static_cast<DWORD>(bytes_read), ERROR_SUCCESS));
- return IO_PENDING;
- }
-
- return io_result;
-}
-
-embedder::ScopedPlatformHandleVectorPtr RawChannelWin::GetReadPlatformHandles(
- size_t num_platform_handles,
- const void* platform_handle_table) {
- // TODO(vtl): Implement.
- NOTIMPLEMENTED();
- return embedder::ScopedPlatformHandleVectorPtr();
-}
-
-RawChannel::IOResult RawChannelWin::WriteNoLock(
- size_t* platform_handles_written,
- size_t* bytes_written) {
- write_lock().AssertAcquired();
-
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_write_no_lock());
-
- if (write_buffer_no_lock()->HavePlatformHandlesToSend()) {
- // TODO(vtl): Implement.
- NOTIMPLEMENTED();
- }
-
- std::vector<WriteBuffer::Buffer> buffers;
- write_buffer_no_lock()->GetBuffers(&buffers);
- DCHECK(!buffers.empty());
-
- // TODO(yzshen): Handle multi-segment writes more efficiently.
- DWORD bytes_written_dword = 0;
- BOOL result =
- WriteFile(io_handler_->handle(), buffers[0].addr,
- static_cast<DWORD>(buffers[0].size), &bytes_written_dword,
- &io_handler_->write_context_no_lock()->overlapped);
- if (!result) {
- DWORD error = GetLastError();
- if (error == ERROR_BROKEN_PIPE)
- return IO_FAILED_SHUTDOWN;
- if (error != ERROR_IO_PENDING) {
- LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error);
- return IO_FAILED_UNKNOWN;
- }
- }
-
- if (result && skip_completion_port_on_success_) {
- *platform_handles_written = 0;
- *bytes_written = bytes_written_dword;
- return IO_SUCCEEDED;
- }
-
- // If the write is pending or the write has succeeded but we don't skip
- // completion port on success, instruct |io_handler_| to wait for the
- // completion packet.
- //
- // TODO(yzshen): it seems there isn't document saying that all error cases
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
- // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()|
- // will crash so we will learn about it.
-
- io_handler_->OnPendingWriteStartedNoLock();
- return IO_PENDING;
-}
-
-RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() {
- write_lock().AssertAcquired();
-
- DCHECK(io_handler_);
- DCHECK(!io_handler_->pending_write_no_lock());
-
- // TODO(vtl): Do something with |platform_handles_written|.
- size_t platform_handles_written = 0;
- size_t bytes_written = 0;
- IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written);
- if (io_result == IO_SUCCEEDED) {
- DCHECK(skip_completion_port_on_success_);
-
- // We have finished writing successfully. Queue a notification manually.
- io_handler_->OnPendingWriteStartedNoLock();
- // |io_handler_| won't go away before that task is run, so it is safe to use
- // |base::Unretained()|.
- message_loop_for_io()->PostTask(
- FROM_HERE,
- base::Bind(&RawChannelIOHandler::OnIOCompleted,
- base::Unretained(io_handler_),
- base::Unretained(io_handler_->write_context_no_lock()),
- static_cast<DWORD>(bytes_written), ERROR_SUCCESS));
- return IO_PENDING;
- }
-
- return io_result;
-}
-
-void RawChannelWin::OnInit() {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
-
- DCHECK(handle_.is_valid());
- if (skip_completion_port_on_success_) {
- // I don't know how this can fail (unless |handle_| is bad, in which case
- // it's a bug in our code).
- CHECK(g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes(
- handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS));
- }
-
- DCHECK(!io_handler_);
- io_handler_ = new RawChannelIOHandler(this, handle_.Pass());
-}
-
-void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
- scoped_ptr<WriteBuffer> write_buffer) {
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
- DCHECK(io_handler_);
-
- write_lock().AssertAcquired();
-
- if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) {
- // |io_handler_| will be alive until pending read/write (if any) completes.
- // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as
- // soon as possible.
- // Note: |CancelIo()| only cancels read/write requests started from this
- // thread.
- if (g_vista_or_higher_functions.Get().is_vista_or_higher()) {
- g_vista_or_higher_functions.Get().CancelIoEx(io_handler_->handle(),
- nullptr);
- } else {
- CancelIo(io_handler_->handle());
- }
- }
-
- io_handler_->DetachFromOwnerNoLock(read_buffer.Pass(), write_buffer.Pass());
- io_handler_ = nullptr;
-}
-
-} // namespace
-
-// -----------------------------------------------------------------------------
-
-// Static factory method declared in raw_channel.h.
-// static
-scoped_ptr<RawChannel> RawChannel::Create(
- embedder::ScopedPlatformHandle handle) {
- return make_scoped_ptr(new RawChannelWin(handle.Pass()));
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc
deleted file mode 100644
index 1860c23..0000000
--- a/mojo/edk/system/remote_message_pipe_unittest.cc
+++ /dev/null
@@ -1,1376 +0,0 @@
-// 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 <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/test_io_thread.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "build/build_config.h" // TODO(vtl): Remove this.
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/channel_endpoint.h"
-#include "mojo/edk/system/channel_endpoint_id.h"
-#include "mojo/edk/system/incoming_endpoint.h"
-#include "mojo/edk/system/message_pipe.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/raw_channel.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED;
-
-class RemoteMessagePipeTest : public testing::Test {
- public:
- RemoteMessagePipeTest() : io_thread_(base::TestIOThread::kAutoStart) {}
- ~RemoteMessagePipeTest() override {}
-
- void SetUp() override {
- io_thread_.PostTaskAndWait(
- FROM_HERE, base::Bind(&RemoteMessagePipeTest::SetUpOnIOThread,
- base::Unretained(this)));
- }
-
- void TearDown() override {
- io_thread_.PostTaskAndWait(
- FROM_HERE, base::Bind(&RemoteMessagePipeTest::TearDownOnIOThread,
- base::Unretained(this)));
- }
-
- protected:
- // This connects the two given |ChannelEndpoint|s. It assumes/requires that
- // this is the bootstrap case (i.e., no other message pipes have ever been
- // hosted on the channel).
- void BootstrapChannelEndpoints(scoped_refptr<ChannelEndpoint> ep0,
- scoped_refptr<ChannelEndpoint> ep1) {
- io_thread_.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointsOnIOThread,
- base::Unretained(this), ep0, ep1));
- }
-
- // This bootstraps |ep| on |channels_[channel_index]|. It assumes/requires
- // that this is the bootstrap case (i.e., no message pipes have ever been
- // hosted on the channel). This returns *without* waiting.
- void BootstrapChannelEndpointNoWait(unsigned channel_index,
- scoped_refptr<ChannelEndpoint> ep) {
- io_thread_.PostTask(
- FROM_HERE,
- base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointOnIOThread,
- base::Unretained(this), channel_index, ep));
- }
-
- void RestoreInitialState() {
- io_thread_.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&RemoteMessagePipeTest::RestoreInitialStateOnIOThread,
- base::Unretained(this)));
- }
-
- embedder::PlatformSupport* platform_support() { return &platform_support_; }
- base::TestIOThread* io_thread() { return &io_thread_; }
- // Warning: It's up to the caller to ensure that the returned channel
- // is/remains valid.
- Channel* channels(size_t i) { return channels_[i].get(); }
-
- private:
- void SetUpOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- embedder::PlatformChannelPair channel_pair;
- platform_handles_[0] = channel_pair.PassServerHandle();
- platform_handles_[1] = channel_pair.PassClientHandle();
- }
-
- void TearDownOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- if (channels_[0]) {
- channels_[0]->Shutdown();
- channels_[0] = nullptr;
- }
- if (channels_[1]) {
- channels_[1]->Shutdown();
- channels_[1] = nullptr;
- }
- }
-
- void CreateAndInitChannel(unsigned channel_index) {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
- CHECK(channel_index == 0 || channel_index == 1);
- CHECK(!channels_[channel_index]);
-
- channels_[channel_index] = new Channel(&platform_support_);
- channels_[channel_index]->Init(
- RawChannel::Create(platform_handles_[channel_index].Pass()));
- }
-
- void BootstrapChannelEndpointsOnIOThread(scoped_refptr<ChannelEndpoint> ep0,
- scoped_refptr<ChannelEndpoint> ep1) {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- if (!channels_[0])
- CreateAndInitChannel(0);
- if (!channels_[1])
- CreateAndInitChannel(1);
-
- channels_[0]->SetBootstrapEndpoint(ep0);
- channels_[1]->SetBootstrapEndpoint(ep1);
- }
-
- void BootstrapChannelEndpointOnIOThread(unsigned channel_index,
- scoped_refptr<ChannelEndpoint> ep) {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
- CHECK(channel_index == 0 || channel_index == 1);
-
- CreateAndInitChannel(channel_index);
- channels_[channel_index]->SetBootstrapEndpoint(ep);
- }
-
- void RestoreInitialStateOnIOThread() {
- CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop());
-
- TearDownOnIOThread();
- SetUpOnIOThread();
- }
-
- embedder::SimplePlatformSupport platform_support_;
- base::TestIOThread io_thread_;
- embedder::ScopedPlatformHandle platform_handles_[2];
- scoped_refptr<Channel> channels_[2];
-
- DISALLOW_COPY_AND_ASSIGN(RemoteMessagePipeTest);
-};
-
-TEST_F(RemoteMessagePipeTest, Basic) {
- static const char kHello[] = "hello";
- static const char kWorld[] = "world!!!1!!!1!";
- char buffer[100] = {0};
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
- // connected to MP 1, port 0, which will be attached to channel 1. This leaves
- // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // Write in one direction: MP 0, port 0 -> ... -> MP 1, port 1.
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- EXPECT_EQ(MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kHello, buffer);
-
- // Write in the other direction: MP 1, port 1 -> ... -> MP 0, port 0.
-
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr));
-
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(456u, context);
- hss = HandleSignalsState();
- mp0->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- mp0->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kWorld, buffer);
-
- // Close MP 0, port 0.
- mp0->Close(0);
-
- // Try to wait for MP 1, port 1 to become readable. This will eventually fail
- // when it realizes that MP 0, port 0 has been closed. (It may also fail
- // immediately.)
- waiter.Init();
- hss = HandleSignalsState();
- MojoResult result =
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss);
- if (result == MOJO_RESULT_OK) {
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(789u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- }
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- // And MP 1, port 1.
- mp1->Close(1);
-}
-
-TEST_F(RemoteMessagePipeTest, PeerClosed) {
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
- // connected to MP 1, port 0, which will be attached to channel 1. This leaves
- // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // Close MP 0, port 0.
- mp0->Close(0);
-
- // Try to wait for MP 1, port 1 to be signaled with peer closed.
- waiter.Init();
- hss = HandleSignalsState();
- MojoResult result =
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss);
- if (result == MOJO_RESULT_OK) {
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(101u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- }
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- // And MP 1, port 1.
- mp1->Close(1);
-}
-
-TEST_F(RemoteMessagePipeTest, Multiplex) {
- static const char kHello[] = "hello";
- static const char kWorld[] = "world!!!1!!!1!";
- char buffer[100] = {0};
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // Connect message pipes as in the |Basic| test.
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // Now put another message pipe on the channel.
-
- // Do this by creating a message pipe (for the |channels(0)| side) and
- // attaching and running it, yielding the remote ID. A message is then sent
- // via |ep0| (i.e., sent using |mp0|, port 0) with this remote ID. Upon
- // receiving this message, |PassIncomingMessagePipe()| is used to obtain the
- // message pipe on the other side.
- scoped_refptr<MessagePipe> mp2(MessagePipe::CreateLocalLocal());
- ASSERT_TRUE(channels(0));
- size_t max_endpoint_info_size;
- size_t max_platform_handle_count;
- mp2->StartSerialize(1, channels(0), &max_endpoint_info_size,
- &max_platform_handle_count);
- EXPECT_GT(max_endpoint_info_size, 0u);
- ASSERT_EQ(0u, max_platform_handle_count);
- scoped_ptr<char[]> endpoint_info(new char[max_endpoint_info_size]);
- size_t endpoint_info_size;
- mp2->EndSerialize(1, channels(0), endpoint_info.get(), &endpoint_info_size,
- nullptr);
- EXPECT_EQ(max_endpoint_info_size, endpoint_info_size);
-
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(endpoint_info.get()),
- static_cast<uint32_t>(endpoint_info_size),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- EXPECT_EQ(endpoint_info_size, channels(1)->GetSerializedEndpointSize());
- scoped_ptr<char[]> received_endpoint_info(new char[endpoint_info_size]);
- buffer_size = static_cast<uint32_t>(endpoint_info_size);
- EXPECT_EQ(MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(received_endpoint_info.get()),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(endpoint_info_size, static_cast<size_t>(buffer_size));
- EXPECT_EQ(0, memcmp(received_endpoint_info.get(), endpoint_info.get(),
- endpoint_info_size));
-
- // Warning: The local side of mp3 is port 0, not port 1.
- scoped_refptr<IncomingEndpoint> incoming_endpoint =
- channels(1)->DeserializeEndpoint(received_endpoint_info.get());
- ASSERT_TRUE(incoming_endpoint);
- scoped_refptr<MessagePipe> mp3 = incoming_endpoint->ConvertToMessagePipe();
- ASSERT_TRUE(mp3);
-
- // Write: MP 2, port 0 -> MP 3, port 1.
-
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp3->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, nullptr));
-
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp2->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(789u, context);
- hss = HandleSignalsState();
- mp3->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0.
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp0->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp1->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp2->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- // Read from MP 3, port 1.
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- mp3->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kHello, buffer);
-
- // Write: MP 0, port 0 -> MP 1, port 1 again.
-
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
-
- // Make sure there's nothing on the other ports.
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp0->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp2->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- mp3->ReadMessage(0, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
-
- buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kWorld, buffer);
-
- mp0->Close(0);
- mp1->Close(1);
- mp2->Close(0);
- mp3->Close(0);
-}
-
-TEST_F(RemoteMessagePipeTest, CloseBeforeAttachAndRun) {
- static const char kHello[] = "hello";
- char buffer[100] = {0};
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
- // connected to MP 1, port 0, which will be attached to channel 1. This leaves
- // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
-
- // Write to MP 0, port 0.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Close MP 0, port 0 before it's even been attached to the channel and run.
- mp0->Close(0);
-
- BootstrapChannelEndpointNoWait(0, ep0);
-
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- BootstrapChannelEndpointNoWait(1, ep1);
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- // Note: MP 1, port 1 should definitely should be readable, but it may or may
- // not appear as writable (there's a race, and it may not have noticed that
- // the other side was closed yet -- e.g., inserting a sleep here would make it
- // much more likely to notice that it's no longer writable).
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- // Read from MP 1, port 1.
- EXPECT_EQ(MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kHello, buffer);
-
- // And MP 1, port 1.
- mp1->Close(1);
-}
-
-TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) {
- static const char kHello[] = "hello";
- char buffer[100] = {0};
- uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
- // connected to MP 1, port 0, which will be attached to channel 1. This leaves
- // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
-
- // Write to MP 0, port 0.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- BootstrapChannelEndpointNoWait(0, ep0);
-
- // Close MP 0, port 0 before channel 1 is even connected.
- mp0->Close(0);
-
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- BootstrapChannelEndpointNoWait(1, ep1);
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- // Note: MP 1, port 1 should definitely should be readable, but it may or may
- // not appear as writable (there's a race, and it may not have noticed that
- // the other side was closed yet -- e.g., inserting a sleep here would make it
- // much more likely to notice that it's no longer writable).
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
- EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
-
- // Read from MP 1, port 1.
- EXPECT_EQ(MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size));
- EXPECT_STREQ(kHello, buffer);
-
- // And MP 1, port 1.
- mp1->Close(1);
-}
-
-TEST_F(RemoteMessagePipeTest, HandlePassing) {
- static const char kHello[] = "hello";
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // We'll try to pass this dispatcher.
- scoped_refptr<MessagePipeDispatcher> dispatcher(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal());
- dispatcher->Init(local_mp, 0);
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- char read_buffer[100] = {0};
- uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- DispatcherVector read_dispatchers;
- uint32_t read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType());
- dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get());
-
- // Add the waiter now, before it becomes readable to avoid a race.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456,
- nullptr));
-
- // Write to "local_mp", port 1.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // TODO(vtl): FIXME -- We (racily) crash if I close |dispatcher| immediately
- // here. (We don't crash if I sleep and then close.)
-
- // Wait for the dispatcher to become readable.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(456u, context);
- hss = HandleSignalsState();
- dispatcher->RemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from the dispatcher.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher->ReadMessage(UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), 0,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
-
- // Prepare to wait on "local_mp", port 1.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789,
- nullptr));
-
- // Write to the dispatcher.
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage(
- UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(789u, context);
- hss = HandleSignalsState();
- local_mp->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from "local_mp", port 1.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- local_mp->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
-
- // TODO(vtl): Also test that messages queued up before the handle was sent are
- // delivered properly.
-
- // Close everything that belongs to us.
- mp0->Close(0);
- mp1->Close(1);
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
- // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed.
- local_mp->Close(1);
-}
-
-TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
- static const char kHello[] = "hello";
- static const char kWorld[] = "world!";
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- // We'll try to pass this dispatcher.
- scoped_refptr<MessagePipeDispatcher> dispatcher(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal());
- dispatcher->Init(local_mp, 0);
-
- hss = local_mp->GetHandleSignalsState(0);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // Write to the other end (|local_mp|, port 1), and then close it.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = local_mp->GetHandleSignalsState(0);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // Then the second message....
- EXPECT_EQ(
- MOJO_RESULT_OK,
- local_mp->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
- hss = local_mp->GetHandleSignalsState(0);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- // Then close it.
- local_mp->Close(1);
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- char read_buffer[100] = {0};
- uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- DispatcherVector read_dispatchers;
- uint32_t read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType());
- dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get());
-
- // |dispatcher| should already be readable and not writable.
- hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- // So read from it.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher->ReadMessage(UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), 0,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
- // It should still be readable.
- hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
- // So read from it.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher->ReadMessage(UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), 0,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kWorld, read_buffer);
- // Now it should no longer be readable.
- hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
-
- // Close everything that belongs to us.
- mp0->Close(0);
- mp1->Close(1);
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-}
-
-#if defined(OS_POSIX)
-#define MAYBE_SharedBufferPassing SharedBufferPassing
-#else
-// Not yet implemented (on Windows).
-#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing
-#endif
-TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
- static const char kHello[] = "hello";
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // We'll try to pass this dispatcher.
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher));
- ASSERT_TRUE(dispatcher);
-
- // Make a mapping.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping0;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0));
- ASSERT_TRUE(mapping0);
- ASSERT_TRUE(mapping0->GetBase());
- ASSERT_EQ(100u, mapping0->GetLength());
- static_cast<char*>(mapping0->GetBase())[0] = 'A';
- static_cast<char*>(mapping0->GetBase())[50] = 'B';
- static_cast<char*>(mapping0->GetBase())[99] = 'C';
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- char read_buffer[100] = {0};
- uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- DispatcherVector read_dispatchers;
- uint32_t read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypeSharedBuffer, read_dispatchers[0]->GetType());
- dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get());
-
- // Make another mapping.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
- ASSERT_TRUE(mapping1);
- ASSERT_TRUE(mapping1->GetBase());
- ASSERT_EQ(100u, mapping1->GetLength());
- EXPECT_NE(mapping1->GetBase(), mapping0->GetBase());
- EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]);
- EXPECT_EQ('B', static_cast<char*>(mapping1->GetBase())[50]);
- EXPECT_EQ('C', static_cast<char*>(mapping1->GetBase())[99]);
-
- // Write stuff either way.
- static_cast<char*>(mapping1->GetBase())[1] = 'x';
- EXPECT_EQ('x', static_cast<char*>(mapping0->GetBase())[1]);
- static_cast<char*>(mapping0->GetBase())[2] = 'y';
- EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[2]);
-
- // Kill the first mapping; the second should still be valid.
- mapping0.reset();
- EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]);
-
- // Close everything that belongs to us.
- mp0->Close(0);
- mp1->Close(1);
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-
- // The second mapping should still be good.
- EXPECT_EQ('x', static_cast<char*>(mapping1->GetBase())[1]);
-}
-
-#if defined(OS_POSIX)
-#define MAYBE_PlatformHandlePassing PlatformHandlePassing
-#else
-// Not yet implemented (on Windows).
-#define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing
-#endif
-TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHello[] = "hello";
- static const char kWorld[] = "world";
- Waiter waiter;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- base::FilePath unused;
- base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
- EXPECT_EQ(sizeof(kHello), fwrite(kHello, 1, sizeof(kHello), fp.get()));
- // We'll try to pass this dispatcher, which will cause a |PlatformHandle| to
- // be passed.
- scoped_refptr<PlatformHandleDispatcher> dispatcher(
- new PlatformHandleDispatcher(
- mojo::test::PlatformHandleFromFILE(fp.Pass())));
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- char read_buffer[100] = {0};
- uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- DispatcherVector read_dispatchers;
- uint32_t read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kWorld, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypePlatformHandle, read_dispatchers[0]->GetType());
- dispatcher =
- static_cast<PlatformHandleDispatcher*>(read_dispatchers[0].get());
-
- embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle().Pass();
- EXPECT_TRUE(h.is_valid());
-
- fp = mojo::test::FILEFromPlatformHandle(h.Pass(), "rb").Pass();
- EXPECT_FALSE(h.is_valid());
- EXPECT_TRUE(fp);
-
- rewind(fp.get());
- memset(read_buffer, 0, sizeof(read_buffer));
- EXPECT_EQ(sizeof(kHello),
- fread(read_buffer, 1, sizeof(read_buffer), fp.get()));
- EXPECT_STREQ(kHello, read_buffer);
-
- // Close everything that belongs to us.
- mp0->Close(0);
- mp1->Close(1);
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-}
-
-// Test racing closes (on each end).
-// Note: A flaky failure would almost certainly indicate a problem in the code
-// itself (not in the test). Also, any logged warnings/errors would also
-// probably be indicative of bugs.
-TEST_F(RemoteMessagePipeTest, RacingClosesStress) {
- base::TimeDelta delay = base::TimeDelta::FromMilliseconds(5);
-
- for (unsigned i = 0; i < 256; i++) {
- DVLOG(2) << "---------------------------------------- " << i;
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- BootstrapChannelEndpointNoWait(0, ep0);
-
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpointNoWait(1, ep1);
-
- if (i & 1u) {
- io_thread()->task_runner()->PostTask(
- FROM_HERE, base::Bind(&base::PlatformThread::Sleep, delay));
- }
- if (i & 2u)
- base::PlatformThread::Sleep(delay);
-
- mp0->Close(0);
-
- if (i & 4u) {
- io_thread()->task_runner()->PostTask(
- FROM_HERE, base::Bind(&base::PlatformThread::Sleep, delay));
- }
- if (i & 8u)
- base::PlatformThread::Sleep(delay);
-
- mp1->Close(1);
-
- RestoreInitialState();
- }
-}
-
-// Tests passing an end of a message pipe over a remote message pipe, and then
-// passing that end back.
-// TODO(vtl): Also test passing a message pipe across two remote message pipes.
-TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) {
- static const char kHello[] = "hello";
- static const char kWorld[] = "world";
- Waiter waiter;
- HandleSignalsState hss;
- uint32_t context = 0;
-
- scoped_refptr<ChannelEndpoint> ep0;
- scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
- scoped_refptr<ChannelEndpoint> ep1;
- scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
- BootstrapChannelEndpoints(ep0, ep1);
-
- // We'll try to pass this dispatcher.
- scoped_refptr<MessagePipeDispatcher> dispatcher(
- new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
- scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal());
- dispatcher->Init(local_mp, 0);
-
- // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr));
-
- // Write to MP 0, port 0.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(123u, context);
- hss = HandleSignalsState();
- mp1->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 1, port 1.
- char read_buffer[100] = {0};
- uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- DispatcherVector read_dispatchers;
- uint32_t read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType());
- dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get());
- read_dispatchers.clear();
-
- // Now pass it back.
-
- // Prepare to wait on MP 0, port 0. (Add the waiter now. Otherwise, if we do
- // it later, it might already be readable.)
- waiter.Init();
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr));
-
- // Write to MP 1, port 1.
- {
- DispatcherTransport transport(
- test::DispatcherTryStartTransport(dispatcher.get()));
- EXPECT_TRUE(transport.is_valid());
-
- std::vector<DispatcherTransport> transports;
- transports.push_back(transport);
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld),
- &transports, MOJO_WRITE_MESSAGE_FLAG_NONE));
- transport.End();
-
- // |dispatcher| should have been closed. This is |DCHECK()|ed when the
- // |dispatcher| is destroyed.
- EXPECT_TRUE(dispatcher->HasOneRef());
- dispatcher = nullptr;
- }
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(456u, context);
- hss = HandleSignalsState();
- mp0->RemoveAwakable(0, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from MP 0, port 0.
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- read_num_dispatchers = 10; // Maximum to get.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- mp0->ReadMessage(0, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), &read_dispatchers,
- &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kWorld, read_buffer);
- EXPECT_EQ(1u, read_dispatchers.size());
- EXPECT_EQ(1u, read_num_dispatchers);
- ASSERT_TRUE(read_dispatchers[0]);
- EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
-
- EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType());
- dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get());
- read_dispatchers.clear();
-
- // Add the waiter now, before it becomes readable to avoid a race.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789,
- nullptr));
-
- // Write to "local_mp", port 1.
- EXPECT_EQ(
- MOJO_RESULT_OK,
- local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait for the dispatcher to become readable.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(789u, context);
- hss = HandleSignalsState();
- dispatcher->RemoveAwakable(&waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from the dispatcher.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- dispatcher->ReadMessage(UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), 0,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
-
- // Prepare to wait on "local_mp", port 1.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789,
- nullptr));
-
- // Write to the dispatcher.
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage(
- UserPointer<const void>(kHello), sizeof(kHello),
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Wait.
- EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_EQ(789u, context);
- hss = HandleSignalsState();
- local_mp->RemoveAwakable(1, &waiter, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfied_signals);
- EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
-
- // Read from "local_mp", port 1.
- memset(read_buffer, 0, sizeof(read_buffer));
- read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
- EXPECT_EQ(MOJO_RESULT_OK,
- local_mp->ReadMessage(1, UserPointer<void>(read_buffer),
- MakeUserPointer(&read_buffer_size), nullptr,
- nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size));
- EXPECT_STREQ(kHello, read_buffer);
-
- // TODO(vtl): Also test the cases where messages are written and read (at
- // various points) on the message pipe being passed around.
-
- // Close everything that belongs to us.
- mp0->Close(0);
- mp1->Close(1);
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
- // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed.
- local_mp->Close(1);
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/run_all_unittests.cc b/mojo/edk/system/run_all_unittests.cc
deleted file mode 100644
index cd61337..0000000
--- a/mojo/edk/system/run_all_unittests.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 "base/bind.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-int main(int argc, char** argv) {
-// Silence death test thread warnings on Linux. We can afford to run our death
-// tests a little more slowly (< 10 ms per death test on a Z620).
-// On android, we need to run in the default mode, as the threadsafe mode
-// relies on execve which is not available.
-#if !defined(OS_ANDROID)
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
-#endif
-
- base::TestSuite test_suite(argc, argv);
-
- return base::LaunchUnitTests(
- argc, argv,
- base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
-}
diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc
deleted file mode 100644
index db823d5..0000000
--- a/mojo/edk/system/shared_buffer_dispatcher.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// 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 "base/memory/scoped_ptr.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 = new SharedBufferDispatcher(shared_buffer);
- return MOJO_RESULT_OK;
-}
-
-Dispatcher::Type SharedBufferDispatcher::GetType() const {
- return kTypeSharedBuffer;
-}
-
-// 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 scoped_refptr<SharedBufferDispatcher>(
- new SharedBufferDispatcher(shared_buffer));
-}
-
-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() {
- lock().AssertAcquired();
- DCHECK(shared_buffer_);
- shared_buffer_ = nullptr;
-}
-
-scoped_refptr<Dispatcher>
-SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
- lock().AssertAcquired();
- DCHECK(shared_buffer_);
- scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer;
- shared_buffer.swap(shared_buffer_);
- return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer));
-}
-
-MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- scoped_refptr<Dispatcher>* new_dispatcher) {
- lock().AssertAcquired();
-
- MojoDuplicateBufferHandleOptions validated_options;
- MojoResult result = ValidateDuplicateOptions(options, &validated_options);
- if (result != MOJO_RESULT_OK)
- return result;
-
- *new_dispatcher = new SharedBufferDispatcher(shared_buffer_);
- return MOJO_RESULT_OK;
-}
-
-MojoResult SharedBufferDispatcher::MapBufferImplNoLock(
- uint64_t offset,
- uint64_t num_bytes,
- MojoMapBufferFlags flags,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
- lock().AssertAcquired();
- 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
diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h
deleted file mode 100644
index db04d2a..0000000
--- a/mojo/edk/system/shared_buffer_dispatcher.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/memory.h"
-#include "mojo/edk/system/simple_dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformSupport;
-}
-
-namespace system {
-
-// TODO(vtl): We derive from SimpleDispatcher, even though we don't currently
-// have anything that's waitable. I want to add a "transferrable" wait flag
-// (which would entail overriding |GetHandleSignalsStateImplNoLock()|, etc.).
-class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
- public:
- // The default options to use for |MojoCreateSharedBuffer()|. (Real uses
- // should obtain this via |ValidateCreateOptions()| with a null |in_options|;
- // this is exposed directly for testing convenience.)
- static const MojoCreateSharedBufferOptions kDefaultCreateOptions;
-
- // Validates and/or sets default options for |MojoCreateSharedBufferOptions|.
- // If non-null, |in_options| must point to a struct of at least
- // |in_options->struct_size| bytes. |out_options| must point to a (current)
- // |MojoCreateSharedBufferOptions| and will be entirely overwritten on success
- // (it may be partly overwritten on failure).
- static MojoResult ValidateCreateOptions(
- UserPointer<const MojoCreateSharedBufferOptions> in_options,
- MojoCreateSharedBufferOptions* out_options);
-
- // Static factory method: |validated_options| must be validated (obviously).
- // On failure, |*result| will be left as-is.
- static MojoResult Create(
- embedder::PlatformSupport* platform_support,
- const MojoCreateSharedBufferOptions& validated_options,
- uint64_t num_bytes,
- scoped_refptr<SharedBufferDispatcher>* result);
-
- // |Dispatcher| public methods:
- Type GetType() const override;
-
- // The "opposite" of |SerializeAndClose()|. (Typically this is called by
- // |Dispatcher::Deserialize()|.)
- static scoped_refptr<SharedBufferDispatcher> Deserialize(
- Channel* channel,
- const void* source,
- size_t size,
- embedder::PlatformHandleVector* platform_handles);
-
- private:
- explicit SharedBufferDispatcher(
- scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer_);
- ~SharedBufferDispatcher() override;
-
- // Validates and/or sets default options for
- // |MojoDuplicateBufferHandleOptions|. If non-null, |in_options| must point to
- // a struct of at least |in_options->struct_size| bytes. |out_options| must
- // point to a (current) |MojoDuplicateBufferHandleOptions| and will be
- // entirely overwritten on success (it may be partly overwritten on failure).
- static MojoResult ValidateDuplicateOptions(
- UserPointer<const MojoDuplicateBufferHandleOptions> in_options,
- MojoDuplicateBufferHandleOptions* out_options);
-
- // |Dispatcher| protected methods:
- void CloseImplNoLock() override;
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
- MojoResult DuplicateBufferHandleImplNoLock(
- UserPointer<const MojoDuplicateBufferHandleOptions> options,
- scoped_refptr<Dispatcher>* new_dispatcher) override;
- MojoResult MapBufferImplNoLock(
- uint64_t offset,
- uint64_t num_bytes,
- MojoMapBufferFlags flags,
- scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) override;
- void StartSerializeImplNoLock(Channel* channel,
- size_t* max_size,
- size_t* max_platform_handles) override;
- bool EndSerializeAndCloseImplNoLock(
- Channel* channel,
- void* destination,
- size_t* actual_size,
- embedder::PlatformHandleVector* platform_handles) override;
-
- scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
deleted file mode 100644
index 29dcb57..0000000
--- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// 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/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-// NOTE(vtl): There's currently not much to test for in
-// |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be
-// expanded if/when options are added, so I've kept the general form of the
-// tests from data_pipe_unittest.cc.
-
-const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions);
-
-// Does a cursory sanity check of |validated_options|. Calls
-// |ValidateCreateOptions()| on already-validated options. The validated options
-// should be valid, and the revalidated copy should be the same.
-void RevalidateCreateOptions(
- const MojoCreateSharedBufferOptions& validated_options) {
- EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size);
- // Nothing to check for flags.
-
- MojoCreateSharedBufferOptions revalidated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- SharedBufferDispatcher::ValidateCreateOptions(
- MakeUserPointer(&validated_options), &revalidated_options));
- EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
- EXPECT_EQ(validated_options.flags, revalidated_options.flags);
-}
-
-class SharedBufferDispatcherTest : public testing::Test {
- public:
- SharedBufferDispatcherTest() {}
- ~SharedBufferDispatcherTest() override {}
-
- embedder::PlatformSupport* platform_support() { return &platform_support_; }
-
- private:
- embedder::SimplePlatformSupport platform_support_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest);
-};
-
-// Tests valid inputs to |ValidateCreateOptions()|.
-TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
- // Default options.
- {
- MojoCreateSharedBufferOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
- NullUserPointer(), &validated_options));
- RevalidateCreateOptions(validated_options);
- }
-
- // Different flags.
- MojoCreateSharedBufferOptionsFlags flags_values[] = {
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
- for (size_t i = 0; i < arraysize(flags_values); i++) {
- const MojoCreateSharedBufferOptionsFlags flags = flags_values[i];
-
- // Different capacities (size 1).
- for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
- MojoCreateSharedBufferOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- flags // |flags|.
- };
- MojoCreateSharedBufferOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- SharedBufferDispatcher::ValidateCreateOptions(
- MakeUserPointer(&options), &validated_options))
- << capacity;
- RevalidateCreateOptions(validated_options);
- EXPECT_EQ(options.flags, validated_options.flags);
- }
- }
-}
-
-TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
- // Invalid |struct_size|.
- {
- MojoCreateSharedBufferOptions options = {
- 1, // |struct_size|.
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE // |flags|.
- };
- MojoCreateSharedBufferOptions unused;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- SharedBufferDispatcher::ValidateCreateOptions(
- MakeUserPointer(&options), &unused));
- }
-
- // Unknown |flags|.
- {
- MojoCreateSharedBufferOptions options = {
- kSizeOfCreateOptions, // |struct_size|.
- ~0u // |flags|.
- };
- MojoCreateSharedBufferOptions unused;
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- SharedBufferDispatcher::ValidateCreateOptions(
- MakeUserPointer(&options), &unused));
- }
-}
-
-TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) {
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher));
- ASSERT_TRUE(dispatcher);
- EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType());
-
- // Make a couple of mappings.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
- ASSERT_TRUE(mapping1);
- ASSERT_TRUE(mapping1->GetBase());
- EXPECT_EQ(100u, mapping1->GetLength());
- // Write something.
- static_cast<char*>(mapping1->GetBase())[50] = 'x';
-
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2));
- ASSERT_TRUE(mapping2);
- ASSERT_TRUE(mapping2->GetBase());
- EXPECT_EQ(50u, mapping2->GetLength());
- EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-
- // Check that we can still read/write to mappings after the dispatcher has
- // gone away.
- static_cast<char*>(mapping2->GetBase())[1] = 'y';
- EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
-}
-
-TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
- scoped_refptr<SharedBufferDispatcher> dispatcher1;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher1));
-
- // Map and write something.
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- static_cast<char*>(mapping->GetBase())[0] = 'x';
- mapping.reset();
-
- // Duplicate |dispatcher1| and then close it.
- scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
- NullUserPointer(), &dispatcher2));
- ASSERT_TRUE(dispatcher2);
- EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType());
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
-
- // Map |dispatcher2| and read something.
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]);
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
-}
-
-TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) {
- scoped_refptr<SharedBufferDispatcher> dispatcher1;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher1));
-
- MojoDuplicateBufferHandleOptions options[] = {
- {sizeof(MojoDuplicateBufferHandleOptions),
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE},
- {sizeof(MojoDuplicateBufferHandleOptionsFlags), ~0u}};
- for (size_t i = 0; i < arraysize(options); i++) {
- scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
- MakeUserPointer(&options[i]), &dispatcher2));
- ASSERT_TRUE(dispatcher2);
- EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType());
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
- }
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
-}
-
-TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
- scoped_refptr<SharedBufferDispatcher> dispatcher1;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher1));
-
- // Invalid |struct_size|.
- {
- MojoDuplicateBufferHandleOptions options = {
- 1u, MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
- scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options),
- &dispatcher2));
- EXPECT_FALSE(dispatcher2);
- }
-
- // Unknown |flags|.
- {
- MojoDuplicateBufferHandleOptions options = {
- sizeof(MojoDuplicateBufferHandleOptions), ~0u};
- scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options),
- &dispatcher2));
- EXPECT_FALSE(dispatcher2);
- }
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
-}
-
-TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) {
- // Size too big.
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- EXPECT_EQ(
- MOJO_RESULT_RESOURCE_EXHAUSTED,
- SharedBufferDispatcher::Create(
- platform_support(), SharedBufferDispatcher::kDefaultCreateOptions,
- std::numeric_limits<uint64_t>::max(), &dispatcher));
- EXPECT_FALSE(dispatcher);
-
- // Zero size.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions, 0, &dispatcher));
- EXPECT_FALSE(dispatcher);
-}
-
-TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
- platform_support(),
- SharedBufferDispatcher::kDefaultCreateOptions,
- 100, &dispatcher));
-
- scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- EXPECT_FALSE(mapping);
-
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- EXPECT_FALSE(mapping);
-
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
- EXPECT_FALSE(mapping);
-
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/simple_dispatcher.cc b/mojo/edk/system/simple_dispatcher.cc
deleted file mode 100644
index f7db875..0000000
--- a/mojo/edk/system/simple_dispatcher.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 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/simple_dispatcher.h"
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace system {
-
-SimpleDispatcher::SimpleDispatcher() {
-}
-
-SimpleDispatcher::~SimpleDispatcher() {
-}
-
-void SimpleDispatcher::HandleSignalsStateChangedNoLock() {
- lock().AssertAcquired();
- awakable_list_.AwakeForStateChange(GetHandleSignalsStateImplNoLock());
-}
-
-void SimpleDispatcher::CancelAllAwakablesNoLock() {
- lock().AssertAcquired();
- awakable_list_.CancelAll();
-}
-
-MojoResult SimpleDispatcher::AddAwakableImplNoLock(
- Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
-
- HandleSignalsState state(GetHandleSignalsStateImplNoLock());
- if (state.satisfies(signals)) {
- if (signals_state)
- *signals_state = state;
- return MOJO_RESULT_ALREADY_EXISTS;
- }
- if (!state.can_satisfy(signals)) {
- if (signals_state)
- *signals_state = state;
- return MOJO_RESULT_FAILED_PRECONDITION;
- }
-
- awakable_list_.Add(awakable, signals, context);
- return MOJO_RESULT_OK;
-}
-
-void SimpleDispatcher::RemoveAwakableImplNoLock(
- Awakable* awakable,
- HandleSignalsState* signals_state) {
- lock().AssertAcquired();
- awakable_list_.Remove(awakable);
- if (signals_state)
- *signals_state = GetHandleSignalsStateImplNoLock();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/simple_dispatcher.h b/mojo/edk/system/simple_dispatcher.h
deleted file mode 100644
index eddf614..0000000
--- a/mojo/edk/system/simple_dispatcher.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_SIMPLE_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_SIMPLE_DISPATCHER_H_
-
-#include <list>
-
-#include "base/macros.h"
-#include "mojo/edk/system/awakable_list.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// A base class for simple dispatchers. "Simple" means that there's a one-to-one
-// correspondence between handles and dispatchers (see the explanatory comment
-// in core.cc). This class implements the standard waiter-signalling mechanism
-// in that case.
-class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher {
- protected:
- SimpleDispatcher();
- ~SimpleDispatcher() override;
-
- // To be called by subclasses when the state changes (so
- // |GetHandleSignalsStateImplNoLock()| should be checked again). Must be
- // called under lock.
- void HandleSignalsStateChangedNoLock();
-
- // |Dispatcher| protected methods:
- void CancelAllAwakablesNoLock() override;
- MojoResult AddAwakableImplNoLock(Awakable* awakable,
- MojoHandleSignals signals,
- uint32_t context,
- HandleSignalsState* signals_state) override;
- void RemoveAwakableImplNoLock(Awakable* awakable,
- HandleSignalsState* signals_state) override;
-
- private:
- // Protected by |lock()|:
- AwakableList awakable_list_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleDispatcher);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_SIMPLE_DISPATCHER_H_
diff --git a/mojo/edk/system/simple_dispatcher_unittest.cc b/mojo/edk/system/simple_dispatcher_unittest.cc
deleted file mode 100644
index b8e57e9..0000000
--- a/mojo/edk/system/simple_dispatcher_unittest.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2013 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.
-
-// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
-// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
-// increase tolerance and reduce observed flakiness (though doing so reduces the
-// meaningfulness of the test).
-
-#include "mojo/edk/system/simple_dispatcher.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/time/time.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/system/waiter_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-class MockSimpleDispatcher : public SimpleDispatcher {
- public:
- MockSimpleDispatcher()
- : state_(MOJO_HANDLE_SIGNAL_NONE,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {}
-
- void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) {
- base::AutoLock locker(lock());
-
- // Any new signals that are set should be satisfiable.
- CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals,
- new_satisfied_signals & ~state_.satisfied_signals &
- state_.satisfiable_signals);
-
- if (new_satisfied_signals == state_.satisfied_signals)
- return;
-
- state_.satisfied_signals = new_satisfied_signals;
- HandleSignalsStateChangedNoLock();
- }
-
- void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) {
- base::AutoLock locker(lock());
-
- // Satisfied implies satisfiable.
- CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals,
- state_.satisfied_signals);
-
- if (new_satisfiable_signals == state_.satisfiable_signals)
- return;
-
- state_.satisfiable_signals = new_satisfiable_signals;
- HandleSignalsStateChangedNoLock();
- }
-
- Type GetType() const override { return kTypeUnknown; }
-
- private:
- friend class base::RefCountedThreadSafe<MockSimpleDispatcher>;
- ~MockSimpleDispatcher() override {}
-
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override {
- scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher());
- rv->state_ = state_;
- return scoped_refptr<Dispatcher>(rv.get());
- }
-
- // |Dispatcher| override:
- HandleSignalsState GetHandleSignalsStateImplNoLock() const override {
- lock().AssertAcquired();
- return state_;
- }
-
- // Protected by |lock()|:
- HandleSignalsState state_;
-
- DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher);
-};
-
-#if defined(OS_WIN)
-// http://crbug.com/396404
-#define MAYBE_Basic DISABLED_Basic
-#else
-#define MAYBE_Basic Basic
-#endif
-TEST(SimpleDispatcherTest, MAYBE_Basic) {
- test::Stopwatch stopwatch;
-
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- Waiter w;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Try adding a readable waiter when already readable.
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
- // Shouldn't need to remove the waiter (it was not added).
-
- // Wait (forever) for writable when already writable.
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr));
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(1u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for zero time for writable when already writable.
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr));
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(2u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for non-zero, finite time for writable when already writable.
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr));
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_OK,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(3u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for zero time for writable when not writable (will time out).
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr));
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for non-zero, finite time for writable when not writable (will time
- // out).
- w.Init();
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr));
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr));
- base::TimeDelta elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
-}
-
-TEST(SimpleDispatcherTest, BasicUnsatisfiable) {
- test::Stopwatch stopwatch;
-
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- Waiter w;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Try adding a writable waiter when it can never be writable.
- w.Init();
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
- d->SetSatisfiedSignals(0);
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
- // Shouldn't need to remove the waiter (it was not added).
-
- // Wait (forever) for writable and then it becomes never writable.
- w.Init();
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr));
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(2u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
-
- // Wait for zero time for writable and then it becomes never writable.
- w.Init();
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr));
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(3u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
-
- // Wait for non-zero, finite time for writable and then it becomes never
- // writable.
- w.Init();
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
- MOJO_HANDLE_SIGNAL_WRITABLE);
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr));
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(4u, context);
- hss = HandleSignalsState();
- d->RemoveAwakable(&w, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
-
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
-}
-
-TEST(SimpleDispatcherTest, BasicClosed) {
- test::Stopwatch stopwatch;
-
- scoped_refptr<MockSimpleDispatcher> d;
- Waiter w;
- uint32_t context = 0;
- HandleSignalsState hss;
-
- // Try adding a writable waiter when the dispatcher has been closed.
- d = new MockSimpleDispatcher();
- w.Init();
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- hss = HandleSignalsState();
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
- // Shouldn't need to remove the waiter (it was not added).
-
- // Wait (forever) for writable and then the dispatcher is closed.
- d = new MockSimpleDispatcher();
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(2u, context);
- // Don't need to remove waiters from closed dispatchers.
-
- // Wait for zero time for writable and then the dispatcher is closed.
- d = new MockSimpleDispatcher();
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(3u, context);
- // Don't need to remove waiters from closed dispatchers.
-
- // Wait for non-zero, finite time for writable and then the dispatcher is
- // closed.
- d = new MockSimpleDispatcher();
- w.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_CANCELLED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_EQ(4u, context);
- // Don't need to remove waiters from closed dispatchers.
-}
-
-#if defined(OS_WIN)
-// http://crbug.com/396393
-#define MAYBE_BasicThreaded DISABLED_BasicThreaded
-#else
-#define MAYBE_BasicThreaded BasicThreaded
-#endif
-TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) {
- test::Stopwatch stopwatch;
- bool did_wait;
- MojoResult result;
- uint32_t context;
- HandleSignalsState hss;
-
- // Wait for readable (already readable).
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- {
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- } // Joins the thread.
- // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- }
- EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
- EXPECT_FALSE(did_wait);
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for readable and becomes readable after some time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- {
- test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- } // Joins the thread.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- }
- base::TimeDelta elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(2u, context);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-
- // Wait for readable and becomes never-readable after some time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- {
- test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE);
- } // Joins the thread.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- }
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(3u, context);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- // Wait for readable and dispatcher gets closed.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result,
- &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- } // Joins the thread.
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(4u, context);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
-
- // Wait for readable and times out.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- {
- test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE,
- 2 * test::EpsilonTimeout().InMicroseconds(), 5,
- &did_wait, &result, &context, &hss);
- stopwatch.Start();
- thread.Start();
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- // Not what we're waiting for.
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
- } // Joins the thread (after its wait times out).
- // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- }
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_TRUE(did_wait);
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
-}
-
-#if defined(OS_WIN)
-// http://crbug.com/387124
-#define MAYBE_MultipleWaiters DISABLED_MultipleWaiters
-#else
-#define MAYBE_MultipleWaiters MultipleWaiters
-#endif
-TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) {
- static const uint32_t kNumWaiters = 20;
-
- bool did_wait[kNumWaiters];
- MojoResult result[kNumWaiters];
- uint32_t context[kNumWaiters];
- HandleSignalsState hss[kNumWaiters];
-
- // All wait for readable and becomes readable after some time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- ScopedVector<test::WaiterThread> threads;
- for (uint32_t i = 0; i < kNumWaiters; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i,
- &did_wait[i], &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- } // Joins the threads.
- for (uint32_t i = 0; i < kNumWaiters; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
-
- // Some wait for readable, some for writable, and becomes readable after some
- // time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- ScopedVector<test::WaiterThread> threads;
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i,
- &did_wait[i], &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i,
- &did_wait[i], &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- // This will wake up the ones waiting to write.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- } // Joins the threads.
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
-
- // Some wait for readable, some for writable, and becomes readable and
- // never-writable after some time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- ScopedVector<test::WaiterThread> threads;
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i,
- &did_wait[i], &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i,
- &did_wait[i], &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- } // Joins the threads.
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
-
- // Some wait for readable, some for writable, and becomes readable after some
- // time.
- {
- scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
- ScopedVector<test::WaiterThread> threads;
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_READABLE,
- 3 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i],
- &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- threads.push_back(new test::WaiterThread(
- d, MOJO_HANDLE_SIGNAL_WRITABLE,
- 1 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i],
- &result[i], &context[i], &hss[i]));
- threads.back()->Start();
- }
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
- // All those waiting for writable should have timed out.
- EXPECT_EQ(MOJO_RESULT_OK, d->Close());
- } // Joins the threads.
- for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
- EXPECT_EQ(i, context[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
- for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
- EXPECT_TRUE(did_wait[i]) << i;
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i;
- // Since we closed before joining, we can't say much about what each thread
- // saw as the state.
- }
-}
-
-// TODO(vtl): Stress test?
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/system_impl_export.h b/mojo/edk/system/system_impl_export.h
deleted file mode 100644
index 5bbf005..0000000
--- a/mojo/edk/system/system_impl_export.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
-#define MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION)
-#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllexport)
-#else
-#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllimport)
-#endif // defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION)
-
-#else // defined(WIN32)
-#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION)
-#define MOJO_SYSTEM_IMPL_EXPORT __attribute__((visibility("default")))
-#else
-#define MOJO_SYSTEM_IMPL_EXPORT
-#endif
-#endif
-
-#else // defined(COMPONENT_BUILD)
-#define MOJO_SYSTEM_IMPL_EXPORT
-#endif
-
-#endif // MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
diff --git a/mojo/edk/system/test_utils.cc b/mojo/edk/system/test_utils.cc
deleted file mode 100644
index d43a818..0000000
--- a/mojo/edk/system/test_utils.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 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/test_utils.h"
-
-#include "base/test/test_timeouts.h"
-#include "build/build_config.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-base::TimeDelta EpsilonTimeout() {
-// Originally, our epsilon timeout was 10 ms, which was mostly fine but flaky on
-// some Windows bots. I don't recall ever seeing flakes on other bots. At 30 ms
-// tests seem reliable on Windows bots, but not at 25 ms. We'd like this timeout
-// to be as small as possible (see the description in the .h file).
-//
-// Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN,
-// etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms
-// elsewhere.
-#if defined(OS_WIN) || defined(OS_ANDROID)
- return (TestTimeouts::tiny_timeout() * 3) / 10;
-#else
- return (TestTimeouts::tiny_timeout() * 2) / 10;
-#endif
-}
-
-} // namespace test
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/test_utils.h b/mojo/edk/system/test_utils.h
deleted file mode 100644
index b16c516..0000000
--- a/mojo/edk/system/test_utils.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_TEST_UTILS_H_
-#define MOJO_EDK_SYSTEM_TEST_UTILS_H_
-
-#include "base/macros.h"
-#include "base/time/time.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-// A timeout smaller than |TestTimeouts::tiny_timeout()|. Warning: This may lead
-// to flakiness, but this is unavoidable if, e.g., you're trying to ensure that
-// functions with timeouts are reasonably accurate. We want this to be as small
-// as possible without causing too much flakiness.
-base::TimeDelta EpsilonTimeout();
-
-// Stopwatch -------------------------------------------------------------------
-
-// A simple "stopwatch" for measuring time elapsed from a given starting point.
-class Stopwatch {
- public:
- Stopwatch() {}
- ~Stopwatch() {}
-
- void Start() { start_time_ = base::TimeTicks::Now(); }
-
- base::TimeDelta Elapsed() { return base::TimeTicks::Now() - start_time_; }
-
- private:
- base::TimeTicks start_time_;
-
- DISALLOW_COPY_AND_ASSIGN(Stopwatch);
-};
-
-} // namespace test
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_TEST_UTILS_H_
diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc
deleted file mode 100644
index d388151..0000000
--- a/mojo/edk/system/transport_data.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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/transport_data.h"
-
-#include <string.h>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/message_in_transit.h"
-
-namespace mojo {
-namespace system {
-
-// The maximum amount of space needed per platform handle.
-// (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always
-// return a value which is at most this. This is only used to calculate
-// |TransportData::kMaxBufferSize|. This value should be a multiple of the
-// alignment in order to simplify calculations, even though the actual amount of
-// space needed need not be a multiple of the alignment.
-const size_t kMaxSizePerPlatformHandle = 8;
-static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment ==
- 0,
- "kMaxSizePerPlatformHandle not a multiple of alignment");
-
-STATIC_CONST_MEMBER_DEFINITION const size_t
- TransportData::kMaxSerializedDispatcherSize;
-STATIC_CONST_MEMBER_DEFINITION const size_t
- TransportData::kMaxSerializedDispatcherPlatformHandles;
-
-// static
-size_t TransportData::GetMaxBufferSize() {
- // In additional to the header, for each attached (Mojo) handle there'll be a
- // handle table entry and serialized dispatcher data.
- return sizeof(Header) +
- GetConfiguration().max_message_num_handles *
- (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) +
- GetMaxPlatformHandles() * kMaxSizePerPlatformHandle;
-}
-
-// static
-size_t TransportData::GetMaxPlatformHandles() {
- return GetConfiguration().max_message_num_handles *
- kMaxSerializedDispatcherPlatformHandles;
-}
-
-struct TransportData::PrivateStructForCompileAsserts {
- static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0,
- "sizeof(MessageInTransit::Header) not a multiple of alignment");
- static_assert(kMaxSerializedDispatcherSize %
- MessageInTransit::kMessageAlignment ==
- 0,
- "kMaxSerializedDispatcherSize not a multiple of alignment");
- static_assert(sizeof(HandleTableEntry) %
- MessageInTransit::kMessageAlignment ==
- 0,
- "sizeof(MessageInTransit::HandleTableEntry) not a multiple of "
- "alignment");
-};
-
-TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers,
- Channel* channel) {
- DCHECK(dispatchers);
- DCHECK(channel);
-
- const size_t num_handles = dispatchers->size();
- DCHECK_GT(num_handles, 0u);
-
- // The offset to the start of the (Mojo) handle table.
- const size_t handle_table_start_offset = sizeof(Header);
- // The offset to the start of the serialized dispatcher data.
- const size_t serialized_dispatcher_start_offset =
- handle_table_start_offset + num_handles * sizeof(HandleTableEntry);
- // The estimated size of the secondary buffer. We compute this estimate below.
- // It must be at least as big as the (eventual) actual size.
- size_t estimated_size = serialized_dispatcher_start_offset;
- size_t estimated_num_platform_handles = 0;
-#if DCHECK_IS_ON()
- std::vector<size_t> all_max_sizes(num_handles);
- std::vector<size_t> all_max_platform_handles(num_handles);
-#endif
- for (size_t i = 0; i < num_handles; i++) {
- if (Dispatcher* dispatcher = (*dispatchers)[i].get()) {
- size_t max_size = 0;
- size_t max_platform_handles = 0;
- Dispatcher::TransportDataAccess::StartSerialize(
- dispatcher, channel, &max_size, &max_platform_handles);
-
- DCHECK_LE(max_size, kMaxSerializedDispatcherSize);
- estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size);
- DCHECK_LE(estimated_size, GetMaxBufferSize());
-
- DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles);
- estimated_num_platform_handles += max_platform_handles;
- DCHECK_LE(estimated_num_platform_handles, GetMaxPlatformHandles());
-
-#if DCHECK_IS_ON()
- all_max_sizes[i] = max_size;
- all_max_platform_handles[i] = max_platform_handles;
-#endif
- }
- }
-
- size_t size_per_platform_handle = 0;
- if (estimated_num_platform_handles > 0) {
- size_per_platform_handle = channel->GetSerializedPlatformHandleSize();
- DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle);
- estimated_size += estimated_num_platform_handles * size_per_platform_handle;
- estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size);
- DCHECK_LE(estimated_size, GetMaxBufferSize());
- }
-
- buffer_.reset(static_cast<char*>(
- base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment)));
- // Entirely clear out the secondary buffer, since then we won't have to worry
- // about clearing padding or unused space (e.g., if a dispatcher fails to
- // serialize).
- memset(buffer_.get(), 0, estimated_size);
-
- if (estimated_num_platform_handles > 0) {
- DCHECK(!platform_handles_);
- platform_handles_.reset(new embedder::PlatformHandleVector());
- }
-
- Header* header = reinterpret_cast<Header*>(buffer_.get());
- header->num_handles = static_cast<uint32_t>(num_handles);
- // (Okay to leave |platform_handle_table_offset|, |num_platform_handles|, and
- // |unused| be zero; we'll set the former two later if necessary.)
-
- HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>(
- buffer_.get() + handle_table_start_offset);
- size_t current_offset = serialized_dispatcher_start_offset;
- for (size_t i = 0; i < num_handles; i++) {
- Dispatcher* dispatcher = (*dispatchers)[i].get();
- if (!dispatcher) {
- static_assert(Dispatcher::kTypeUnknown == 0,
- "Value of Dispatcher::kTypeUnknown must be 0");
- continue;
- }
-
-#if DCHECK_IS_ON()
- size_t old_platform_handles_size =
- platform_handles_ ? platform_handles_->size() : 0;
-#endif
-
- void* destination = buffer_.get() + current_offset;
- size_t actual_size = 0;
- if (Dispatcher::TransportDataAccess::EndSerializeAndClose(
- dispatcher, channel, destination, &actual_size,
- platform_handles_.get())) {
- handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
- handle_table[i].offset = static_cast<uint32_t>(current_offset);
- handle_table[i].size = static_cast<uint32_t>(actual_size);
-// (Okay to not set |unused| since we cleared the entire buffer.)
-
-#if DCHECK_IS_ON()
- DCHECK_LE(actual_size, all_max_sizes[i]);
- DCHECK_LE(platform_handles_
- ? (platform_handles_->size() - old_platform_handles_size)
- : 0,
- all_max_platform_handles[i]);
-#endif
- } else {
- // Nothing to do on failure, since |buffer_| was cleared, and
- // |kTypeUnknown| is zero. The handle was simply closed.
- LOG(ERROR) << "Failed to serialize handle to remote message pipe";
- }
-
- current_offset += MessageInTransit::RoundUpMessageAlignment(actual_size);
- DCHECK_LE(current_offset, estimated_size);
- DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0,
- estimated_num_platform_handles);
- }
-
- if (platform_handles_ && platform_handles_->size() > 0) {
- header->platform_handle_table_offset =
- static_cast<uint32_t>(current_offset);
- header->num_platform_handles =
- static_cast<uint32_t>(platform_handles_->size());
- current_offset += platform_handles_->size() * size_per_platform_handle;
- current_offset = MessageInTransit::RoundUpMessageAlignment(current_offset);
- }
-
- // There's no aligned realloc, so it's no good way to release unused space (if
- // we overshot our estimated space requirements).
- buffer_size_ = current_offset;
-
- // |dispatchers_| will be destroyed as it goes out of scope.
-}
-
-TransportData::TransportData(
- embedder::ScopedPlatformHandleVectorPtr platform_handles)
- : buffer_size_(sizeof(Header)), platform_handles_(platform_handles.Pass()) {
- buffer_.reset(static_cast<char*>(
- base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment)));
- memset(buffer_.get(), 0, buffer_size_);
-
- Header* header = reinterpret_cast<Header*>(buffer_.get());
- header->num_platform_handles =
- static_cast<uint32_t>(platform_handles_->size());
-}
-
-TransportData::~TransportData() {
-}
-
-// static
-const char* TransportData::ValidateBuffer(
- size_t serialized_platform_handle_size,
- const void* buffer,
- size_t buffer_size) {
- DCHECK(buffer);
- DCHECK_GT(buffer_size, 0u);
-
- // Always make sure that the buffer size is sane; if it's not, someone's
- // messing with us.
- if (buffer_size < sizeof(Header) || buffer_size > GetMaxBufferSize() ||
- buffer_size % MessageInTransit::kMessageAlignment != 0)
- return "Invalid message secondary buffer size";
-
- const Header* header = static_cast<const Header*>(buffer);
- const size_t num_handles = header->num_handles;
-
- // Sanity-check |num_handles| (before multiplying it against anything).
- if (num_handles > GetConfiguration().max_message_num_handles)
- return "Message handle payload too large";
-
- if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry))
- return "Message secondary buffer too small";
-
- if (header->num_platform_handles == 0) {
- // Then |platform_handle_table_offset| should also be zero.
- if (header->platform_handle_table_offset != 0) {
- return "Message has no handles attached, but platform handle table "
- "present";
- }
- } else {
- if (header->num_platform_handles >
- GetConfiguration().max_message_num_handles *
- kMaxSerializedDispatcherPlatformHandles)
- return "Message has too many platform handles attached";
-
- static const char kInvalidPlatformHandleTableOffset[] =
- "Message has invalid platform handle table offset";
- // This doesn't check that the platform handle table doesn't alias other
- // stuff, but it doesn't matter, since it's all read-only.
- if (header->platform_handle_table_offset %
- MessageInTransit::kMessageAlignment !=
- 0)
- return kInvalidPlatformHandleTableOffset;
-
- // ">" instead of ">=" since the size per handle may be zero.
- if (header->platform_handle_table_offset > buffer_size)
- return kInvalidPlatformHandleTableOffset;
-
- // We already checked |platform_handle_table_offset| and
- // |num_platform_handles|, so the addition and multiplication are okay.
- if (header->platform_handle_table_offset +
- header->num_platform_handles * serialized_platform_handle_size >
- buffer_size)
- return kInvalidPlatformHandleTableOffset;
- }
-
- const HandleTableEntry* handle_table =
- reinterpret_cast<const HandleTableEntry*>(
- static_cast<const char*>(buffer) + sizeof(Header));
- static const char kInvalidSerializedDispatcher[] =
- "Message contains invalid serialized dispatcher";
- for (size_t i = 0; i < num_handles; i++) {
- size_t offset = handle_table[i].offset;
- if (offset % MessageInTransit::kMessageAlignment != 0)
- return kInvalidSerializedDispatcher;
-
- size_t size = handle_table[i].size;
- if (size > kMaxSerializedDispatcherSize || size > buffer_size)
- return kInvalidSerializedDispatcher;
-
- // Note: This is an overflow-safe check for |offset + size > buffer_size|
- // (we know that |size <= buffer_size| from the previous check).
- if (offset > buffer_size - size)
- return kInvalidSerializedDispatcher;
- }
-
- return nullptr;
-}
-
-// static
-void TransportData::GetPlatformHandleTable(const void* transport_data_buffer,
- size_t* num_platform_handles,
- const void** platform_handle_table) {
- DCHECK(transport_data_buffer);
- DCHECK(num_platform_handles);
- DCHECK(platform_handle_table);
-
- const Header* header = static_cast<const Header*>(transport_data_buffer);
- *num_platform_handles = header->num_platform_handles;
- *platform_handle_table = static_cast<const char*>(transport_data_buffer) +
- header->platform_handle_table_offset;
-}
-
-// static
-scoped_ptr<DispatcherVector> TransportData::DeserializeDispatchers(
- const void* buffer,
- size_t buffer_size,
- embedder::ScopedPlatformHandleVectorPtr platform_handles,
- Channel* channel) {
- DCHECK(buffer);
- DCHECK_GT(buffer_size, 0u);
- DCHECK(channel);
-
- const Header* header = static_cast<const Header*>(buffer);
- const size_t num_handles = header->num_handles;
- scoped_ptr<DispatcherVector> dispatchers(new DispatcherVector(num_handles));
-
- const HandleTableEntry* handle_table =
- reinterpret_cast<const HandleTableEntry*>(
- static_cast<const char*>(buffer) + sizeof(Header));
- for (size_t i = 0; i < num_handles; i++) {
- size_t offset = handle_table[i].offset;
- size_t size = handle_table[i].size;
- // Should already have been checked by |ValidateBuffer()|:
- DCHECK_EQ(offset % MessageInTransit::kMessageAlignment, 0u);
- DCHECK_LE(offset, buffer_size);
- DCHECK_LE(offset + size, buffer_size);
-
- const void* source = static_cast<const char*>(buffer) + offset;
- (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize(
- channel, handle_table[i].type, source, size, platform_handles.get());
- }
-
- return dispatchers.Pass();
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/transport_data.h b/mojo/edk/system/transport_data.h
deleted file mode 100644
index 1258f49..0000000
--- a/mojo/edk/system/transport_data.h
+++ /dev/null
@@ -1,189 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_
-#define MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/scoped_ptr.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class Channel;
-
-// This class is used by |MessageInTransit| to represent handles (|Dispatcher|s)
-// in various stages of serialization.
-//
-// The stages are:
-// - Before reaching |TransportData|: Turn |DispatcherTransport|s into
-// |Dispatcher|s that are "owned" by (and attached to) a |MessageInTransit|.
-// This invalidates the handles in the space of the sending application
-// (and, e.g., if another thread is waiting on such a handle, it'll be
-// notified of this invalidation).
-// - Serialize these dispatchers into the |TransportData|: First, for each
-// attached dispatcher, there's an entry in the |TransportData|'s "handle
-// table", which points to a segment of (dispatcher-type-dependent) data.
-// - During the serialization of the dispatchers, |PlatformHandle|s may be
-// detached from the dispatchers and attached to the |TransportData|.
-// - Before sending the |MessageInTransit|, including its main buffer and the
-// |TransportData|'s buffer, the |Channel| sends any |PlatformHandle|s (in a
-// platform-, and possibly sandbox-situation-, specific way) first. In doing
-// so, it appends a "platform handle table" to the |TransportData|
-// containing information about how to deserialize these |PlatformHandle|s.
-// - Finally, at this point, to send the |MessageInTransit|, there only
-// remains "inert" data: the |MessageInTransit|'s main buffer and data from
-// the |TransportData|, consisting of the "handle table" (one entry for each
-// attached dispatcher), dispatcher-type-specific data (one segment for each
-// entry in the "handle table"), and the "platform handle table" (one entry
-// for each attached |PlatformHandle|).
-//
-// To receive a message (|MessageInTransit|), the "reverse" happens:
-// - On POSIX, receive and buffer |PlatformHandle|s (i.e., FDs), which were
-// sent before the "inert" data.
-// - Receive the "inert" data from the |MessageInTransit|. Examine its
-// "platform handle table". On POSIX, match its entries with the buffered
-// |PlatformHandle|s, which were previously received. On Windows, do what's
-// necessary to obtain |PlatformHandle|s (e.g.: i. if the sender is fully
-// trusted and able to duplicate handle into the receiver, then just pick
-// out the |HANDLE| value; ii. if the receiver is fully trusted and able to
-// duplicate handles from the receiver, do the |DuplicateHandle()|; iii.
-// otherwise, talk to a broker to get handles). Reattach all the
-// |PlatformHandle|s to the |MessageInTransit|.
-// - For each entry in the "handle table", use serialized dispatcher data to
-// reconstitute a dispatcher, taking ownership of associated
-// |PlatformHandle|s (and detaching them). Attach these dispatchers to the
-// |MessageInTransit|.
-// - At this point, the |MessageInTransit| consists of its main buffer
-// (primarily the data payload) and the attached dispatchers; the
-// |TransportData| can be discarded.
-// - When |MojoReadMessage()| is to give data to the application, attach the
-// dispatchers to the (global, "core") handle table, getting handles; give
-// the application the data payload and these handles.
-//
-// TODO(vtl): Everything above involving |PlatformHandle|s.
-class MOJO_SYSTEM_IMPL_EXPORT TransportData {
- public:
- // The maximum size of a single serialized dispatcher. This must be a multiple
- // of |kMessageAlignment|.
- static const size_t kMaxSerializedDispatcherSize = 10000;
-
- // The maximum number of platform handles to attach for a single serialized
- // dispatcher.
- static const size_t kMaxSerializedDispatcherPlatformHandles = 2;
-
- // The maximum possible size of a valid transport data buffer.
- static size_t GetMaxBufferSize();
-
- // The maximum total number of platform handles that may be attached.
- static size_t GetMaxPlatformHandles();
-
- TransportData(scoped_ptr<DispatcherVector> dispatchers, Channel* channel);
-
- // This is used for users of |MessageInTransit|/|TransportData|/|RawChannel|
- // that want to simply transport data and platform handles, and not
- // |Dispatcher|s. (|Header| will be present, and zero except for
- // |num_platform_handles|, and |platform_handle_table_offset| if necessary.)
- explicit TransportData(
- embedder::ScopedPlatformHandleVectorPtr platform_handles);
-
- ~TransportData();
-
- const void* buffer() const { return buffer_.get(); }
- void* buffer() { return buffer_.get(); }
- size_t buffer_size() const { return buffer_size_; }
-
- uint32_t platform_handle_table_offset() const {
- return header()->platform_handle_table_offset;
- }
-
- // Gets attached platform-specific handles; this may return null if there are
- // none. Note that the caller may mutate the set of platform-specific handles.
- const embedder::PlatformHandleVector* platform_handles() const {
- return platform_handles_.get();
- }
- embedder::PlatformHandleVector* platform_handles() {
- return platform_handles_.get();
- }
-
- // Receive-side functions:
-
- // Checks if the given buffer (from the "wire") looks like a valid
- // |TransportData| buffer. (Should only be called if |buffer_size| is
- // nonzero.) Returns null if valid, and a pointer to a human-readable error
- // message (for debug/logging purposes) on error. Note: This checks the
- // validity of the handle table entries (i.e., does range checking), but does
- // not check that the validity of the actual serialized dispatcher
- // information.
- static const char* ValidateBuffer(size_t serialized_platform_handle_size,
- const void* buffer,
- size_t buffer_size);
-
- // Gets the platform handle table from a (valid) |TransportData| buffer (which
- // should have been validated using |ValidateBuffer()| first).
- static void GetPlatformHandleTable(const void* transport_data_buffer,
- size_t* num_platform_handles,
- const void** platform_handle_table);
-
- // Deserializes dispatchers from the given (serialized) transport data buffer
- // (typically from a |MessageInTransit::View|) and vector of platform handles.
- // |buffer| should be non-null and |buffer_size| should be nonzero.
- static scoped_ptr<DispatcherVector> DeserializeDispatchers(
- const void* buffer,
- size_t buffer_size,
- embedder::ScopedPlatformHandleVectorPtr platform_handles,
- Channel* channel);
-
- private:
- // To allow us to make compile-assertions about |Header|, etc. in the .cc
- // file.
- struct PrivateStructForCompileAsserts;
-
- // Header for the "secondary buffer"/"transport data". Must be a multiple of
- // |MessageInTransit::kMessageAlignment| in size. Must be POD.
- struct Header {
- uint32_t num_handles;
- // TODO(vtl): Not used yet:
- uint32_t platform_handle_table_offset;
- uint32_t num_platform_handles;
- uint32_t unused;
- };
-
- struct HandleTableEntry {
- int32_t type; // From |Dispatcher::Type| (|kTypeUnknown| for "invalid").
- uint32_t offset; // Relative to the start of the "secondary buffer".
- uint32_t size; // (Not including any padding.)
- uint32_t unused;
- };
-
- const Header* header() const {
- return reinterpret_cast<const Header*>(buffer_.get());
- }
-
- size_t buffer_size_;
- scoped_ptr<char, base::AlignedFreeDeleter> buffer_; // Never null.
-
- // Any platform-specific handles attached to this message (for inter-process
- // transport). The vector (if any) owns the handles that it contains (and is
- // responsible for closing them).
- // TODO(vtl): With C++11, change it to a vector of |ScopedPlatformHandle|s.
- embedder::ScopedPlatformHandleVectorPtr platform_handles_;
-
- DISALLOW_COPY_AND_ASSIGN(TransportData);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_TRANSPORT_DATA_H_
diff --git a/mojo/edk/system/unique_identifier.cc b/mojo/edk/system/unique_identifier.cc
deleted file mode 100644
index e851e2b..0000000
--- a/mojo/edk/system/unique_identifier.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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/unique_identifier.h"
-
-#include <ostream>
-
-#include "base/strings/string_number_conversions.h"
-#include "crypto/random.h"
-
-namespace mojo {
-namespace system {
-
-std::ostream& operator<<(std::ostream& out,
- const UniqueIdentifier& unique_identifier) {
- return out << base::HexEncode(unique_identifier.data_,
- sizeof(unique_identifier.data_));
-}
-
-// static
-UniqueIdentifier UniqueIdentifier::Generate() {
- UniqueIdentifier rv;
- crypto::RandBytes(rv.data_, sizeof(rv.data_));
- return rv;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/unique_identifier.h b/mojo/edk/system/unique_identifier.h
deleted file mode 100644
index a7f68ba..0000000
--- a/mojo/edk/system/unique_identifier.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_
-#define MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_
-
-#include <stdint.h>
-#include <string.h>
-
-#include <iosfwd>
-
-#include "base/compiler_specific.h"
-#include "base/containers/hash_tables.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-class UniqueIdentifier;
-
-} // namespace system
-} // namespace mojo
-
-namespace BASE_HASH_NAMESPACE {
-
-// Declare this before |UniqueIdentifier|, so that it can be friended.
-template <>
-struct hash<mojo::system::UniqueIdentifier>;
-
-} // BASE_HASH_NAMESPACE
-
-namespace mojo {
-namespace system {
-
-// Declare this before |UniqueIdentifier|, so that it can be friended.
-MOJO_SYSTEM_IMPL_EXPORT std::ostream& operator<<(
- std::ostream& out,
- const UniqueIdentifier& unique_identifier);
-
-// |UniqueIdentifier| is a POD class whose value is used to uniquely identify
-// things.
-class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier {
- public:
- // This generates a new identifier. Uniqueness is "guaranteed" (i.e.,
- // probabilistically) for identifiers.
- static UniqueIdentifier Generate();
-
- bool operator==(const UniqueIdentifier& other) const {
- return memcmp(data_, other.data_, sizeof(data_)) == 0;
- }
- bool operator!=(const UniqueIdentifier& other) const {
- return !operator==(other);
- }
- bool operator<(const UniqueIdentifier& other) const {
- return memcmp(data_, other.data_, sizeof(data_)) < 0;
- }
-
- private:
- friend BASE_HASH_NAMESPACE::hash<mojo::system::UniqueIdentifier>;
- friend std::ostream& operator<<(std::ostream&, const UniqueIdentifier&);
-
- explicit UniqueIdentifier() {}
-
- char data_[16];
-
- // Copying and assignment allowed.
-};
-static_assert(sizeof(UniqueIdentifier) == 16,
- "UniqueIdentifier has wrong size.");
-// We want to be able to take any buffer and cast it to a |UniqueIdentifier|.
-static_assert(ALIGNOF(UniqueIdentifier) == 1,
- "UniqueIdentifier requires nontrivial alignment.");
-
-} // namespace system
-} // namespace mojo
-
-namespace BASE_HASH_NAMESPACE {
-
-template <>
-struct hash<mojo::system::UniqueIdentifier> {
- size_t operator()(mojo::system::UniqueIdentifier unique_identifier) const {
- return base::HashInts64(
- *reinterpret_cast<uint64_t*>(unique_identifier.data_),
- *reinterpret_cast<uint64_t*>(unique_identifier.data_ +
- sizeof(uint64_t)));
- }
-};
-
-} // BASE_HASH_NAMESPACE
-
-#endif // MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_
diff --git a/mojo/edk/system/unique_identifier_unittest.cc b/mojo/edk/system/unique_identifier_unittest.cc
deleted file mode 100644
index 2be4f6e..0000000
--- a/mojo/edk/system/unique_identifier_unittest.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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/unique_identifier.h"
-
-#include <set>
-#include <sstream>
-
-#include "base/containers/hash_tables.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-TEST(UniqueIdentifierTest, Basic) {
- // (This also checks copy constructibility.)
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
-
- EXPECT_EQ(id1, id1);
- EXPECT_FALSE(id1 != id1);
- EXPECT_FALSE(id1 < id1);
-
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
-
- EXPECT_FALSE(id2 == id1);
- EXPECT_NE(id2, id1);
- EXPECT_TRUE((id1 < id2) ^ (id2 < id1));
-
- // Test copyability.
- id2 = id1;
-}
-
-TEST(UniqueIdentifierTest, Logging) {
- std::ostringstream oss1;
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
- oss1 << id1;
- EXPECT_FALSE(oss1.str().empty());
-
- std::ostringstream oss2;
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
- oss2 << id2;
- EXPECT_FALSE(oss2.str().empty());
-
- EXPECT_NE(id1, id2);
- EXPECT_NE(oss1.str(), oss2.str());
-}
-
-TEST(UniqueIdentifierTest, StdSet) {
- std::set<UniqueIdentifier> s;
- EXPECT_TRUE(s.empty());
-
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
- EXPECT_TRUE(s.find(id1) == s.end());
- s.insert(id1);
- EXPECT_TRUE(s.find(id1) != s.end());
- EXPECT_FALSE(s.empty());
-
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
- EXPECT_TRUE(s.find(id2) == s.end());
- s.insert(id2);
- EXPECT_TRUE(s.find(id2) != s.end());
- // Make sure |id1| is still in |s|.
- EXPECT_TRUE(s.find(id1) != s.end());
-
- s.erase(id1);
- EXPECT_TRUE(s.find(id1) == s.end());
- // Make sure |id2| is still in |s|.
- EXPECT_TRUE(s.find(id2) != s.end());
-
- s.erase(id2);
- EXPECT_TRUE(s.find(id2) == s.end());
- EXPECT_TRUE(s.empty());
-}
-
-TEST(UniqueIdentifierTest, HashSet) {
- base::hash_set<UniqueIdentifier> s;
- EXPECT_TRUE(s.empty());
-
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
- EXPECT_TRUE(s.find(id1) == s.end());
- s.insert(id1);
- EXPECT_TRUE(s.find(id1) != s.end());
- EXPECT_FALSE(s.empty());
-
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
- EXPECT_TRUE(s.find(id2) == s.end());
- s.insert(id2);
- EXPECT_TRUE(s.find(id2) != s.end());
- // Make sure |id1| is still in |s|.
- EXPECT_TRUE(s.find(id1) != s.end());
-
- s.erase(id1);
- EXPECT_TRUE(s.find(id1) == s.end());
- // Make sure |id2| is still in |s|.
- EXPECT_TRUE(s.find(id2) != s.end());
-
- s.erase(id2);
- EXPECT_TRUE(s.find(id2) == s.end());
- EXPECT_TRUE(s.empty());
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/waiter.cc b/mojo/edk/system/waiter.cc
deleted file mode 100644
index f18edc8..0000000
--- a/mojo/edk/system/waiter.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2013 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/waiter.h"
-
-#include <limits>
-
-#include "base/logging.h"
-#include "base/time/time.h"
-
-namespace mojo {
-namespace system {
-
-Waiter::Waiter()
- : cv_(&lock_),
-#ifndef NDEBUG
- initialized_(false),
-#endif
- awoken_(false),
- awake_result_(MOJO_RESULT_INTERNAL),
- awake_context_(static_cast<uint32_t>(-1)) {
-}
-
-Waiter::~Waiter() {
-}
-
-void Waiter::Init() {
-#ifndef NDEBUG
- initialized_ = true;
-#endif
- awoken_ = false;
- // NOTE(vtl): If performance ever becomes an issue, we can disable the setting
- // of |awake_result_| (except the first one in |Awake()|) in Release builds.
- awake_result_ = MOJO_RESULT_INTERNAL;
-}
-
-// TODO(vtl): Fast-path the |deadline == 0| case?
-MojoResult Waiter::Wait(MojoDeadline deadline, uint32_t* context) {
- base::AutoLock locker(lock_);
-
-#ifndef NDEBUG
- DCHECK(initialized_);
- // It'll need to be re-initialized after this.
- initialized_ = false;
-#endif
-
- // Fast-path the already-awoken case:
- if (awoken_) {
- DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
- if (context)
- *context = static_cast<uint32_t>(awake_context_);
- return awake_result_;
- }
-
- // |MojoDeadline| is actually a |uint64_t|, but we need a signed quantity.
- // Treat any out-of-range deadline as "forever" (which is wrong, but okay
- // since 2^63 microseconds is ~300000 years). Note that this also takes care
- // of the |MOJO_DEADLINE_INDEFINITE| (= 2^64 - 1) case.
- if (deadline > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
- do {
- cv_.Wait();
- } while (!awoken_);
- } else {
- // NOTE(vtl): This is very inefficient on POSIX, since pthreads condition
- // variables take an absolute deadline.
- const base::TimeTicks end_time =
- base::TimeTicks::Now() +
- base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline));
- do {
- base::TimeTicks now_time = base::TimeTicks::Now();
- if (now_time >= end_time)
- return MOJO_RESULT_DEADLINE_EXCEEDED;
-
- cv_.TimedWait(end_time - now_time);
- } while (!awoken_);
- }
-
- DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
- if (context)
- *context = static_cast<uint32_t>(awake_context_);
- return awake_result_;
-}
-
-bool Waiter::Awake(MojoResult result, uintptr_t context) {
- base::AutoLock locker(lock_);
-
- if (awoken_)
- return true;
-
- awoken_ = true;
- awake_result_ = result;
- awake_context_ = context;
- cv_.Signal();
- // |cv_.Wait()|/|cv_.TimedWait()| will return after |lock_| is released.
- return true;
-}
-
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/waiter.h b/mojo/edk/system/waiter.h
deleted file mode 100644
index b9b63cd..0000000
--- a/mojo/edk/system/waiter.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_WAITER_H_
-#define MOJO_EDK_SYSTEM_WAITER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "mojo/edk/system/awakable.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-
-// IMPORTANT (all-caps gets your attention, right?): |Waiter| methods are called
-// under other locks, in particular, |Dispatcher::lock_|s, so |Waiter| methods
-// must never call out to other objects (in particular, |Dispatcher|s). This
-// class is thread-safe.
-class MOJO_SYSTEM_IMPL_EXPORT Waiter : public Awakable {
- public:
- Waiter();
- ~Waiter();
-
- // A |Waiter| can be used multiple times; |Init()| should be called before
- // each time it's used.
- void Init();
-
- // Waits until a suitable |Awake()| is called. (|context| may be null, in
- // which case, obviously no context is ever returned.)
- // Returns:
- // - The result given to the first call to |Awake()| (possibly before this
- // call to |Wait()|); in this case, |*context| is set to the value passed
- // to that call to |Awake()|.
- // - |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline was exceeded; in this
- // case |*context| is not modified.
- //
- // Usually, the context passed to |Awake()| will be the value passed to
- // |Dispatcher::AddAwakable()|, which is usually the index to the array of
- // handles passed to |MojoWaitMany()| (or 0 for |MojoWait()|).
- //
- // Typical |Awake()| results are:
- // - |MOJO_RESULT_OK| if one of the flags passed to
- // |MojoWait()|/|MojoWaitMany()| (hence |Dispatcher::AddAwakable()|) was
- // satisfied;
- // - |MOJO_RESULT_CANCELLED| if a handle (on which
- // |MojoWait()|/|MojoWaitMany()| was called) was closed (hence the
- // dispatcher closed); and
- // - |MOJO_RESULT_FAILED_PRECONDITION| if one of the set of flags passed to
- // |MojoWait()|/|MojoWaitMany()| cannot or can no longer be satisfied by
- // the corresponding handle (e.g., if the other end of a message or data
- // pipe is closed).
- MojoResult Wait(MojoDeadline deadline, uint32_t* context);
-
- // Wake the waiter up with the given result and context (or no-op if it's been
- // woken up already).
- bool Awake(MojoResult result, uintptr_t context) override;
-
- private:
- base::ConditionVariable cv_; // Associated to |lock_|.
- base::Lock lock_; // Protects the following members.
-#ifndef NDEBUG
- bool initialized_;
-#endif
- bool awoken_;
- MojoResult awake_result_;
- uintptr_t awake_context_;
-
- DISALLOW_COPY_AND_ASSIGN(Waiter);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_WAITER_H_
diff --git a/mojo/edk/system/waiter_test_utils.cc b/mojo/edk/system/waiter_test_utils.cc
deleted file mode 100644
index ea243ed1..0000000
--- a/mojo/edk/system/waiter_test_utils.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 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/waiter_test_utils.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-SimpleWaiterThread::SimpleWaiterThread(MojoResult* result, uint32_t* context)
- : base::SimpleThread("waiter_thread"), result_(result), context_(context) {
- waiter_.Init();
- *result_ = -5420734; // Totally invalid result.
- *context_ = 23489023; // "Random".
-}
-
-SimpleWaiterThread::~SimpleWaiterThread() {
- Join();
-}
-
-void SimpleWaiterThread::Run() {
- *result_ = waiter_.Wait(MOJO_DEADLINE_INDEFINITE, context_);
-}
-
-WaiterThread::WaiterThread(scoped_refptr<Dispatcher> dispatcher,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- uint32_t context,
- bool* did_wait_out,
- MojoResult* result_out,
- uint32_t* context_out,
- HandleSignalsState* signals_state_out)
- : base::SimpleThread("waiter_thread"),
- dispatcher_(dispatcher),
- handle_signals_(handle_signals),
- deadline_(deadline),
- context_(context),
- did_wait_out_(did_wait_out),
- result_out_(result_out),
- context_out_(context_out),
- signals_state_out_(signals_state_out) {
- *did_wait_out_ = false;
- // Initialize these with invalid results (so that we'll be sure to catch any
- // case where they're not set).
- *result_out_ = -8542346;
- *context_out_ = 89023444;
- *signals_state_out_ = HandleSignalsState(~0u, ~0u);
-}
-
-WaiterThread::~WaiterThread() {
- Join();
-}
-
-void WaiterThread::Run() {
- waiter_.Init();
-
- *result_out_ = dispatcher_->AddAwakable(&waiter_, handle_signals_, context_,
- signals_state_out_);
- if (*result_out_ != MOJO_RESULT_OK)
- return;
-
- *did_wait_out_ = true;
- *result_out_ = waiter_.Wait(deadline_, context_out_);
- dispatcher_->RemoveAwakable(&waiter_, signals_state_out_);
-}
-
-} // namespace test
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/system/waiter_test_utils.h b/mojo/edk/system/waiter_test_utils.h
deleted file mode 100644
index b11d78d..0000000
--- a/mojo/edk/system/waiter_test_utils.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2013 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_EDK_SYSTEM_WAITER_TEST_UTILS_H_
-#define MOJO_EDK_SYSTEM_WAITER_TEST_UTILS_H_
-
-#include <stdint.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/simple_thread.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/waiter.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace system {
-namespace test {
-
-// This is a very simple thread that has a |Waiter|, on which it waits
-// indefinitely (and records the result). It will create and initialize the
-// |Waiter| on creation, but the caller must start the thread with |Start()|. It
-// will join the thread on destruction.
-//
-// One usually uses it like:
-//
-// MojoResult result;
-// {
-// AwakableList awakable_list;
-// test::SimpleWaiterThread thread(&result);
-// awakable_list.Add(thread.waiter(), ...);
-// thread.Start();
-// ... some stuff to wake the waiter ...
-// awakable_list.Remove(thread.waiter());
-// } // Join |thread|.
-// EXPECT_EQ(..., result);
-//
-// There's a bit of unrealism in its use: In this sort of usage, calls such as
-// |Waiter::Init()|, |AddAwakable()|, and |RemoveAwakable()| are done in the
-// main (test) thread, not the waiter thread (as would actually happen in real
-// code). (We accept this unrealism for simplicity, since |AwakableList| is
-// thread-unsafe so making it more realistic would require adding nontrivial
-// synchronization machinery.)
-class SimpleWaiterThread : public base::SimpleThread {
- public:
- // For the duration of the lifetime of this object, |*result| belongs to it
- // (in the sense that it will write to it whenever it wants).
- SimpleWaiterThread(MojoResult* result, uint32_t* context);
- ~SimpleWaiterThread() override; // Joins the thread.
-
- Waiter* waiter() { return &waiter_; }
-
- private:
- void Run() override;
-
- MojoResult* const result_;
- uint32_t* const context_;
- Waiter waiter_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleWaiterThread);
-};
-
-// This is a more complex and realistic thread that has a |Waiter|, on which it
-// waits for the given deadline (with the given flags). Unlike
-// |SimpleWaiterThread|, it requires the machinery of |Dispatcher|.
-class WaiterThread : public base::SimpleThread {
- public:
- // Note: |*did_wait_out|, |*result_out|, |*context_out| and
- // |*signals_state_out| "belong" to this object (i.e., may be modified by, on
- // some other thread) while it's alive.
- WaiterThread(scoped_refptr<Dispatcher> dispatcher,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- uint32_t context,
- bool* did_wait_out,
- MojoResult* result_out,
- uint32_t* context_out,
- HandleSignalsState* signals_state_out);
- ~WaiterThread() override;
-
- private:
- void Run() override;
-
- const scoped_refptr<Dispatcher> dispatcher_;
- const MojoHandleSignals handle_signals_;
- const MojoDeadline deadline_;
- const uint32_t context_;
- bool* const did_wait_out_;
- MojoResult* const result_out_;
- uint32_t* const context_out_;
- HandleSignalsState* const signals_state_out_;
-
- Waiter waiter_;
-
- DISALLOW_COPY_AND_ASSIGN(WaiterThread);
-};
-
-} // namespace test
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_WAITER_TEST_UTILS_H_
diff --git a/mojo/edk/system/waiter_unittest.cc b/mojo/edk/system/waiter_unittest.cc
deleted file mode 100644
index 859ff0d..0000000
--- a/mojo/edk/system/waiter_unittest.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2013 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.
-
-// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
-// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
-// increase tolerance and reduce observed flakiness (though doing so reduces the
-// meaningfulness of the test).
-
-#include "mojo/edk/system/waiter.h"
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h" // For |Sleep()|.
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "mojo/edk/system/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace system {
-namespace {
-
-const int64_t kMicrosPerMs = 1000;
-const int64_t kPollTimeMicros = 10 * kMicrosPerMs; // 10 ms.
-
-class WaitingThread : public base::SimpleThread {
- public:
- explicit WaitingThread(MojoDeadline deadline)
- : base::SimpleThread("waiting_thread"),
- deadline_(deadline),
- done_(false),
- result_(MOJO_RESULT_UNKNOWN),
- context_(static_cast<uint32_t>(-1)) {
- waiter_.Init();
- }
-
- ~WaitingThread() override { Join(); }
-
- void WaitUntilDone(MojoResult* result,
- uint32_t* context,
- base::TimeDelta* elapsed) {
- for (;;) {
- {
- base::AutoLock locker(lock_);
- if (done_) {
- *result = result_;
- *context = context_;
- *elapsed = elapsed_;
- break;
- }
- }
-
- base::PlatformThread::Sleep(
- base::TimeDelta::FromMicroseconds(kPollTimeMicros));
- }
- }
-
- Waiter* waiter() { return &waiter_; }
-
- private:
- void Run() override {
- test::Stopwatch stopwatch;
- MojoResult result;
- uint32_t context = static_cast<uint32_t>(-1);
- base::TimeDelta elapsed;
-
- stopwatch.Start();
- result = waiter_.Wait(deadline_, &context);
- elapsed = stopwatch.Elapsed();
-
- {
- base::AutoLock locker(lock_);
- done_ = true;
- result_ = result;
- context_ = context;
- elapsed_ = elapsed;
- }
- }
-
- const MojoDeadline deadline_;
- Waiter waiter_; // Thread-safe.
-
- base::Lock lock_; // Protects the following members.
- bool done_;
- MojoResult result_;
- uint32_t context_;
- base::TimeDelta elapsed_;
-
- DISALLOW_COPY_AND_ASSIGN(WaitingThread);
-};
-
-TEST(WaiterTest, Basic) {
- MojoResult result;
- uint32_t context;
- base::TimeDelta elapsed;
-
- // Finite deadline.
-
- // Awake immediately after thread start.
- {
- WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.Start();
- thread.waiter()->Awake(MOJO_RESULT_OK, 1);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(1u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- // Awake before after thread start.
- {
- WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 2);
- thread.Start();
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(2u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- // Awake some time after thread start.
- {
- WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(1, 3);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(1, result);
- EXPECT_EQ(3u, context);
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- }
-
- // Awake some longer time after thread start.
- {
- WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.Start();
- base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
- thread.waiter()->Awake(2, 4);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(2, result);
- EXPECT_EQ(4u, context);
- EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
- }
-
- // Don't awake -- time out (on another thread).
- {
- WaitingThread thread(2 * test::EpsilonTimeout().InMicroseconds());
- thread.Start();
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
- EXPECT_EQ(static_cast<uint32_t>(-1), context);
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- }
-
- // No (indefinite) deadline.
-
- // Awake immediately after thread start.
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.Start();
- thread.waiter()->Awake(MOJO_RESULT_OK, 5);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(5u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- // Awake before after thread start.
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 6);
- thread.Start();
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
- EXPECT_EQ(6u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- // Awake some time after thread start.
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.Start();
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(1, 7);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(1, result);
- EXPECT_EQ(7u, context);
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- }
-
- // Awake some longer time after thread start.
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.Start();
- base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
- thread.waiter()->Awake(2, 8);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(2, result);
- EXPECT_EQ(8u, context);
- EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
- }
-}
-
-TEST(WaiterTest, TimeOut) {
- test::Stopwatch stopwatch;
- base::TimeDelta elapsed;
-
- Waiter waiter;
- uint32_t context = 123;
-
- waiter.Init();
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, &context));
- elapsed = stopwatch.Elapsed();
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- EXPECT_EQ(123u, context);
-
- waiter.Init();
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- waiter.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
- EXPECT_EQ(123u, context);
-
- waiter.Init();
- stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- waiter.Wait(5 * test::EpsilonTimeout().InMicroseconds(), &context));
- elapsed = stopwatch.Elapsed();
- EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
- EXPECT_EQ(123u, context);
-}
-
-// The first |Awake()| should always win.
-TEST(WaiterTest, MultipleAwakes) {
- MojoResult result;
- uint32_t context;
- base::TimeDelta elapsed;
-
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.Start();
- thread.waiter()->Awake(MOJO_RESULT_OK, 1);
- thread.waiter()->Awake(1, 2);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(1u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.waiter()->Awake(1, 3);
- thread.Start();
- thread.waiter()->Awake(MOJO_RESULT_OK, 4);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(1, result);
- EXPECT_EQ(3u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- {
- WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.Start();
- thread.waiter()->Awake(10, 5);
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(20, 6);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(10, result);
- EXPECT_EQ(5u, context);
- EXPECT_LT(elapsed, test::EpsilonTimeout());
- }
-
- {
- WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.Start();
- base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- thread.waiter()->Awake(MOJO_RESULT_FAILED_PRECONDITION, 7);
- base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(MOJO_RESULT_OK, 8);
- thread.WaitUntilDone(&result, &context, &elapsed);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(7u, context);
- EXPECT_GT(elapsed, (1 - 1) * test::EpsilonTimeout());
- EXPECT_LT(elapsed, (1 + 1) * test::EpsilonTimeout());
- }
-}
-
-} // namespace
-} // namespace system
-} // namespace mojo
diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn
deleted file mode 100644
index d05f6d4..0000000
--- a/mojo/edk/test/BUILD.gn
+++ /dev/null
@@ -1,119 +0,0 @@
-# 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.
-
-import("../mojo_edk.gni")
-
-mojo_edk_source_set("test_support") {
- testonly = true
- sources = [
- "multiprocess_test_helper.cc",
- "multiprocess_test_helper.h",
- "test_utils.h",
- "test_utils_posix.cc",
- "test_utils_win.cc",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-
- mojo_edk_deps = [ "mojo/edk/system" ]
-}
-
-mojo_edk_source_set("run_all_unittests") {
- testonly = true
- sources = [
- "run_all_unittests.cc",
- ]
-
- deps = [
- ":test_support_impl",
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-
- mojo_edk_deps = [ "mojo/edk/system" ]
-
- mojo_sdk_deps = [ "mojo/public/c/test_support" ]
-}
-
-mojo_edk_source_set("run_all_perftests") {
- testonly = true
- deps = [
- ":test_support_impl",
- "//base",
- "//base/test:test_support",
- ]
-
- mojo_edk_deps = [ "mojo/edk/system" ]
-
- mojo_sdk_deps = [ "mojo/public/c/test_support" ]
-
- sources = [
- "run_all_perftests.cc",
- ]
-}
-
-mojo_edk_source_set("test_support_impl") {
- testonly = true
- deps = [
- "//base",
- "//base/test:test_support",
- ]
-
- mojo_sdk_deps = [ "mojo/public/c/test_support" ]
-
- sources = [
- "test_support_impl.cc",
- "test_support_impl.h",
- ]
-}
-
-# Public SDK test targets follow. These targets are not defined within the
-# public SDK itself as running the unittests requires the EDK.
-
-test("mojo_public_application_unittests") {
- deps = [
- ":run_all_unittests",
- "../../public/cpp/application/tests",
- ]
-}
-
-test("mojo_public_bindings_unittests") {
- deps = [
- ":run_all_unittests",
- "../../public/cpp/bindings/tests",
- ]
-}
-
-test("mojo_public_environment_unittests") {
- deps = [
- ":run_all_unittests",
- "../../public/cpp/environment/tests",
- ]
-}
-
-test("mojo_public_system_perftests") {
- deps = [
- ":run_all_perftests",
- "../../public/c/system/tests:perftests",
- ]
-}
-
-test("mojo_public_system_unittests") {
- deps = [
- ":run_all_unittests",
- "../../public/cpp/system/tests",
- ]
-}
-
-test("mojo_public_utility_unittests") {
- deps = [
- ":run_all_unittests",
- "../../public/cpp/utility/tests",
- ]
-}
diff --git a/mojo/edk/test/multiprocess_test_helper.cc b/mojo/edk/test/multiprocess_test_helper.cc
deleted file mode 100644
index 6dd8b72..0000000
--- a/mojo/edk/test/multiprocess_test_helper.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2013 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/test/multiprocess_test_helper.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/process/kill.h"
-#include "base/process/process_handle.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-
-namespace mojo {
-namespace test {
-
-MultiprocessTestHelper::MultiprocessTestHelper() {
- platform_channel_pair_.reset(new embedder::PlatformChannelPair());
- server_platform_handle = platform_channel_pair_->PassServerHandle();
-}
-
-MultiprocessTestHelper::~MultiprocessTestHelper() {
- CHECK(!test_child_.IsValid());
- server_platform_handle.reset();
- platform_channel_pair_.reset();
-}
-
-void MultiprocessTestHelper::StartChild(const std::string& test_child_name) {
- CHECK(platform_channel_pair_);
- CHECK(!test_child_name.empty());
- CHECK(!test_child_.IsValid());
-
- std::string test_child_main = test_child_name + "TestChildMain";
-
- base::CommandLine command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- embedder::HandlePassingInformation handle_passing_info;
- platform_channel_pair_->PrepareToPassClientHandleToChildProcess(
- &command_line, &handle_passing_info);
-
- base::LaunchOptions options;
-#if defined(OS_POSIX)
- options.fds_to_remap = &handle_passing_info;
-#elif defined(OS_WIN)
- options.start_hidden = true;
- options.handles_to_inherit = &handle_passing_info;
-#else
-#error "Not supported yet."
-#endif
-
- test_child_ =
- base::SpawnMultiProcessTestChild(test_child_main, command_line, options);
- platform_channel_pair_->ChildProcessLaunched();
-
- CHECK(test_child_.IsValid());
-}
-
-int MultiprocessTestHelper::WaitForChildShutdown() {
- CHECK(test_child_.IsValid());
-
- int rv = -1;
- CHECK(
- test_child_.WaitForExitWithTimeout(TestTimeouts::action_timeout(), &rv));
- test_child_.Close();
- return rv;
-}
-
-bool MultiprocessTestHelper::WaitForChildTestShutdown() {
- return WaitForChildShutdown() == 0;
-}
-
-// static
-void MultiprocessTestHelper::ChildSetup() {
- CHECK(base::CommandLine::InitializedForCurrentProcess());
- client_platform_handle =
- embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
- *base::CommandLine::ForCurrentProcess());
-}
-
-// static
-embedder::ScopedPlatformHandle MultiprocessTestHelper::client_platform_handle;
-
-} // namespace test
-} // namespace mojo
diff --git a/mojo/edk/test/multiprocess_test_helper.h b/mojo/edk/test/multiprocess_test_helper.h
deleted file mode 100644
index e40b309c..0000000
--- a/mojo/edk/test/multiprocess_test_helper.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 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_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_
-#define MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/process/process.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace mojo {
-
-namespace embedder {
-class PlatformChannelPair;
-}
-
-namespace test {
-
-class MultiprocessTestHelper {
- public:
- MultiprocessTestHelper();
- ~MultiprocessTestHelper();
-
- // Start a child process and run the "main" function "named" |test_child_name|
- // declared using |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| or
- // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()| (below).
- void StartChild(const std::string& test_child_name);
- // Wait for the child process to terminate.
- // Returns the exit code of the child process. Note that, though it's declared
- // to be an |int|, the exit code is subject to mangling by the OS. E.g., we
- // usually return -1 on error in the child (e.g., if |test_child_name| was not
- // found), but this is mangled to 255 on Linux. You should only rely on codes
- // 0-127 being preserved, and -1 being outside the range 0-127.
- int WaitForChildShutdown();
-
- // Like |WaitForChildShutdown()|, but returns true on success (exit code of 0)
- // and false otherwise. You probably want to do something like
- // |EXPECT_TRUE(WaitForChildTestShutdown());|. Mainly for use with
- // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()|.
- bool WaitForChildTestShutdown();
-
- // For use by |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| only:
- static void ChildSetup();
-
- // For use in the main process:
- embedder::ScopedPlatformHandle server_platform_handle;
-
- // For use (and only valid) in the child process:
- static embedder::ScopedPlatformHandle client_platform_handle;
-
- private:
- scoped_ptr<embedder::PlatformChannelPair> platform_channel_pair_;
-
- // Valid after |StartChild()| and before |WaitForChildShutdown()|.
- base::Process test_child_;
-
- DISALLOW_COPY_AND_ASSIGN(MultiprocessTestHelper);
-};
-
-// Use this to declare the child process's "main()" function for tests using
-// |MultiprocessTestHelper|. It returns an |int|, which will be the process's
-// exit code (but see the comment about |WaitForChildShutdown()|).
-#define MOJO_MULTIPROCESS_TEST_CHILD_MAIN(test_child_name) \
- MULTIPROCESS_TEST_MAIN_WITH_SETUP( \
- test_child_name##TestChildMain, \
- ::mojo::test::MultiprocessTestHelper::ChildSetup)
-
-// Use this (and |WaitForChildTestShutdown()|) for the child process's "main()",
-// if you want to use |EXPECT_...()| or |ASSERT_...()|; it has a |void| return
-// type. (Note that while an |ASSERT_...()| failure will abort the test in the
-// child, it will not abort the test in the parent.)
-#define MOJO_MULTIPROCESS_TEST_CHILD_TEST(test_child_name) \
- void test_child_name##TestChildTest(); \
- MOJO_MULTIPROCESS_TEST_CHILD_MAIN(test_child_name) { \
- test_child_name##TestChildTest(); \
- return (::testing::Test::HasFatalFailure() || \
- ::testing::Test::HasNonfatalFailure()) \
- ? 1 \
- : 0; \
- } \
- void test_child_name##TestChildTest()
-
-} // namespace test
-} // namespace mojo
-
-#endif // MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_
diff --git a/mojo/edk/test/multiprocess_test_helper_unittest.cc b/mojo/edk/test/multiprocess_test_helper_unittest.cc
deleted file mode 100644
index 93496fb..0000000
--- a/mojo/edk/test/multiprocess_test_helper_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2013 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/test/multiprocess_test_helper.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <fcntl.h>
-#endif
-
-namespace mojo {
-namespace test {
-namespace {
-
-bool IsNonBlocking(const embedder::PlatformHandle& handle) {
-#if defined(OS_WIN)
- // Haven't figured out a way to query whether a HANDLE was created with
- // FILE_FLAG_OVERLAPPED.
- return true;
-#else
- return fcntl(handle.fd, F_GETFL) & O_NONBLOCK;
-#endif
-}
-
-bool WriteByte(const embedder::PlatformHandle& handle, char c) {
- size_t bytes_written = 0;
- BlockingWrite(handle, &c, 1, &bytes_written);
- return bytes_written == 1;
-}
-
-bool ReadByte(const embedder::PlatformHandle& handle, char* c) {
- size_t bytes_read = 0;
- BlockingRead(handle, c, 1, &bytes_read);
- return bytes_read == 1;
-}
-
-typedef testing::Test MultiprocessTestHelperTest;
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_RunChild DISABLED_RunChild
-#else
-#define MAYBE_RunChild RunChild
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_RunChild) {
- MultiprocessTestHelper helper;
- EXPECT_TRUE(helper.server_platform_handle.is_valid());
-
- helper.StartChild("RunChild");
- EXPECT_EQ(123, helper.WaitForChildShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) {
- CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
- return 123;
-}
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_TestChildMainNotFound DISABLED_TestChildMainNotFound
-#else
-#define MAYBE_TestChildMainNotFound TestChildMainNotFound
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_TestChildMainNotFound) {
- MultiprocessTestHelper helper;
- helper.StartChild("NoSuchTestChildMain");
- int result = helper.WaitForChildShutdown();
- EXPECT_FALSE(result >= 0 && result <= 127);
-}
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_PassedChannel DISABLED_PassedChannel
-#else
-#define MAYBE_PassedChannel PassedChannel
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_PassedChannel) {
- MultiprocessTestHelper helper;
- EXPECT_TRUE(helper.server_platform_handle.is_valid());
- helper.StartChild("PassedChannel");
-
- // Take ownership of the handle.
- embedder::ScopedPlatformHandle handle = helper.server_platform_handle.Pass();
-
- // The handle should be non-blocking.
- EXPECT_TRUE(IsNonBlocking(handle.get()));
-
- // Write a byte.
- const char c = 'X';
- EXPECT_TRUE(WriteByte(handle.get(), c));
-
- // It'll echo it back to us, incremented.
- char d = 0;
- EXPECT_TRUE(ReadByte(handle.get(), &d));
- EXPECT_EQ(c + 1, d);
-
- // And return it, incremented again.
- EXPECT_EQ(c + 2, helper.WaitForChildShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) {
- CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
-
- // Take ownership of the handle.
- embedder::ScopedPlatformHandle handle =
- MultiprocessTestHelper::client_platform_handle.Pass();
-
- // The handle should be non-blocking.
- EXPECT_TRUE(IsNonBlocking(handle.get()));
-
- // Read a byte.
- char c = 0;
- EXPECT_TRUE(ReadByte(handle.get(), &c));
-
- // Write it back, incremented.
- c++;
- EXPECT_TRUE(WriteByte(handle.get(), c));
-
- // And return it, incremented again.
- c++;
- return static_cast<int>(c);
-}
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_ChildTestPasses DISABLED_ChildTestPasses
-#else
-#define MAYBE_ChildTestPasses ChildTestPasses
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestPasses) {
- MultiprocessTestHelper helper;
- EXPECT_TRUE(helper.server_platform_handle.is_valid());
- helper.StartChild("ChildTestPasses");
- EXPECT_TRUE(helper.WaitForChildTestShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses) {
- ASSERT_TRUE(MultiprocessTestHelper::client_platform_handle.is_valid());
- EXPECT_TRUE(
- IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()));
-}
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_ChildTestFailsAssert DISABLED_ChildTestFailsAssert
-#else
-#define MAYBE_ChildTestFailsAssert ChildTestFailsAssert
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestFailsAssert) {
- MultiprocessTestHelper helper;
- EXPECT_TRUE(helper.server_platform_handle.is_valid());
- helper.StartChild("ChildTestFailsAssert");
- EXPECT_FALSE(helper.WaitForChildTestShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert) {
- ASSERT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid())
- << "DISREGARD: Expected failure in child process";
- ASSERT_FALSE(
- IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()))
- << "Not reached";
- CHECK(false) << "Not reached";
-}
-
-#if defined(OS_ANDROID)
-// Android multi-process tests are not executing the new process. This is flaky.
-#define MAYBE_ChildTestFailsExpect DISABLED_ChildTestFailsExpect
-#else
-#define MAYBE_ChildTestFailsExpect ChildTestFailsExpect
-#endif // defined(OS_ANDROID)
-TEST_F(MultiprocessTestHelperTest, MAYBE_ChildTestFailsExpect) {
- MultiprocessTestHelper helper;
- EXPECT_TRUE(helper.server_platform_handle.is_valid());
- helper.StartChild("ChildTestFailsExpect");
- EXPECT_FALSE(helper.WaitForChildTestShutdown());
-}
-
-MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect) {
- EXPECT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid())
- << "DISREGARD: Expected failure #1 in child process";
- EXPECT_FALSE(
- IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()))
- << "DISREGARD: Expected failure #2 in child process";
-}
-
-} // namespace
-} // namespace test
-} // namespace mojo
diff --git a/mojo/edk/test/run_all_perftests.cc b/mojo/edk/test/run_all_perftests.cc
deleted file mode 100644
index f0eacc6..0000000
--- a/mojo/edk/test/run_all_perftests.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013 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 "base/test/perf_test_suite.h"
-#include "mojo/edk/embedder/test_embedder.h"
-#include "mojo/edk/test/test_support_impl.h"
-#include "mojo/public/tests/test_support_private.h"
-
-int main(int argc, char** argv) {
- mojo::embedder::test::InitWithSimplePlatformSupport();
- mojo::test::TestSupport::Init(new mojo::test::TestSupportImpl());
- return base::PerfTestSuite(argc, argv).Run();
-}
diff --git a/mojo/edk/test/run_all_unittests.cc b/mojo/edk/test/run_all_unittests.cc
deleted file mode 100644
index 166a73e..0000000
--- a/mojo/edk/test/run_all_unittests.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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 "base/bind.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#include "mojo/edk/embedder/test_embedder.h"
-#include "mojo/edk/test/test_support_impl.h"
-#include "mojo/public/tests/test_support_private.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-int main(int argc, char** argv) {
- // Silence death test thread warnings on Linux. We can afford to run our death
- // tests a little more slowly (< 10 ms per death test on a Z620).
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
-
- base::TestSuite test_suite(argc, argv);
-
- mojo::embedder::test::InitWithSimplePlatformSupport();
- mojo::test::TestSupport::Init(new mojo::test::TestSupportImpl());
-
- return base::LaunchUnitTests(
- argc, argv,
- base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
-}
diff --git a/mojo/edk/test/test_support_impl.cc b/mojo/edk/test/test_support_impl.cc
deleted file mode 100644
index 34b32ce..0000000
--- a/mojo/edk/test/test_support_impl.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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/test/test_support_impl.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <string>
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/perf_log.h"
-
-namespace mojo {
-namespace test {
-namespace {
-
-base::FilePath ResolveSourceRootRelativePath(const char* relative_path) {
- base::FilePath path;
- if (!PathService::Get(base::DIR_SOURCE_ROOT, &path))
- return base::FilePath();
-
- std::vector<std::string> components;
- base::SplitString(relative_path, '/', &components);
-
- for (size_t i = 0; i < components.size(); ++i) {
- if (!components[i].empty())
- path = path.AppendASCII(components[i]);
- }
-
- return path;
-}
-
-} // namespace
-
-TestSupportImpl::TestSupportImpl() {
-}
-
-TestSupportImpl::~TestSupportImpl() {
-}
-
-void TestSupportImpl::LogPerfResult(const char* test_name,
- const char* sub_test_name,
- double value,
- const char* units) {
- DCHECK(test_name);
- if (sub_test_name) {
- std::string name = base::StringPrintf("%s/%s", test_name, sub_test_name);
- base::LogPerfResult(name.c_str(), value, units);
- } else {
- base::LogPerfResult(test_name, value, units);
- }
-}
-
-FILE* TestSupportImpl::OpenSourceRootRelativeFile(const char* relative_path) {
- return base::OpenFile(ResolveSourceRootRelativePath(relative_path), "rb");
-}
-
-char** TestSupportImpl::EnumerateSourceRootRelativeDirectory(
- const char* relative_path) {
- std::vector<std::string> names;
- base::FileEnumerator e(ResolveSourceRootRelativePath(relative_path), false,
- base::FileEnumerator::FILES);
- for (base::FilePath name = e.Next(); !name.empty(); name = e.Next())
- names.push_back(name.BaseName().AsUTF8Unsafe());
-
- // |names.size() + 1| for null terminator.
- char** rv = static_cast<char**>(calloc(names.size() + 1, sizeof(char*)));
- for (size_t i = 0; i < names.size(); ++i)
- rv[i] = base::strdup(names[i].c_str());
- return rv;
-}
-
-} // namespace test
-} // namespace mojo
diff --git a/mojo/edk/test/test_support_impl.h b/mojo/edk/test/test_support_impl.h
deleted file mode 100644
index 533bfce..0000000
--- a/mojo/edk/test/test_support_impl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_
-#define MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_
-
-#include "base/macros.h"
-#include "mojo/public/tests/test_support_private.h"
-
-namespace mojo {
-namespace test {
-
-class TestSupportImpl : public TestSupport {
- public:
- TestSupportImpl();
- ~TestSupportImpl() override;
-
- void LogPerfResult(const char* test_name,
- const char* sub_test_name,
- double value,
- const char* units) override;
- FILE* OpenSourceRootRelativeFile(const char* relative_path) override;
- char** EnumerateSourceRootRelativeDirectory(
- const char* relative_path) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestSupportImpl);
-};
-
-} // namespace test
-} // namespace mojo
-
-#endif // MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_
diff --git a/mojo/edk/test/test_utils.h b/mojo/edk/test/test_utils.h
deleted file mode 100644
index 9287457..0000000
--- a/mojo/edk/test/test_utils.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.
-
-#ifndef MOJO_EDK_TEST_TEST_UTILS_H_
-#define MOJO_EDK_TEST_TEST_UTILS_H_
-
-#include <stddef.h>
-#include <stdio.h>
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/files/scoped_file.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-
-namespace mojo {
-namespace test {
-
-// On success, |bytes_written| is updated to the number of bytes written;
-// otherwise it is untouched.
-bool BlockingWrite(const embedder::PlatformHandle& handle,
- const void* buffer,
- size_t bytes_to_write,
- size_t* bytes_written);
-
-// On success, |bytes_read| is updated to the number of bytes read; otherwise it
-// is untouched.
-bool BlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read);
-
-// If the read is done successfully or would block, the function returns true
-// and updates |bytes_read| to the number of bytes read (0 if the read would
-// block); otherwise it returns false and leaves |bytes_read| untouched.
-// |handle| must already be in non-blocking mode.
-bool NonBlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read);
-
-// Gets a (scoped) |PlatformHandle| from the given (scoped) |FILE|.
-embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp);
-
-// Gets a (scoped) |FILE| from a (scoped) |PlatformHandle|.
-base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h,
- const char* mode);
-
-// Returns the path to the mojom js bindings file.
-base::FilePath GetFilePathForJSResource(const std::string& path);
-
-} // namespace test
-} // namespace mojo
-
-#endif // MOJO_EDK_TEST_TEST_UTILS_H_
diff --git a/mojo/edk/test/test_utils_posix.cc b/mojo/edk/test/test_utils_posix.cc
deleted file mode 100644
index 6491baf..0000000
--- a/mojo/edk/test/test_utils_posix.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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/test/test_utils.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "base/base_paths.h"
-#include "base/path_service.h"
-#include "base/posix/eintr_wrapper.h"
-
-namespace mojo {
-namespace test {
-
-bool BlockingWrite(const embedder::PlatformHandle& handle,
- const void* buffer,
- size_t bytes_to_write,
- size_t* bytes_written) {
- int original_flags = fcntl(handle.fd, F_GETFL);
- if (original_flags == -1 ||
- fcntl(handle.fd, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) {
- return false;
- }
-
- ssize_t result = HANDLE_EINTR(write(handle.fd, buffer, bytes_to_write));
-
- fcntl(handle.fd, F_SETFL, original_flags);
-
- if (result < 0)
- return false;
-
- *bytes_written = result;
- return true;
-}
-
-bool BlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read) {
- int original_flags = fcntl(handle.fd, F_GETFL);
- if (original_flags == -1 ||
- fcntl(handle.fd, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) {
- return false;
- }
-
- ssize_t result = HANDLE_EINTR(read(handle.fd, buffer, buffer_size));
-
- fcntl(handle.fd, F_SETFL, original_flags);
-
- if (result < 0)
- return false;
-
- *bytes_read = result;
- return true;
-}
-
-bool NonBlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read) {
- ssize_t result = HANDLE_EINTR(read(handle.fd, buffer, buffer_size));
-
- if (result < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK)
- return false;
-
- *bytes_read = 0;
- } else {
- *bytes_read = result;
- }
-
- return true;
-}
-
-embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) {
- CHECK(fp);
- int rv = dup(fileno(fp.get()));
- PCHECK(rv != -1) << "dup";
- return embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv));
-}
-
-base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h,
- const char* mode) {
- CHECK(h.is_valid());
- base::ScopedFILE rv(fdopen(h.release().fd, mode));
- PCHECK(rv) << "fdopen";
- return rv.Pass();
-}
-
-base::FilePath GetFilePathForJSResource(const std::string& path) {
- std::string binding_path = "gen/" + path + ".js";
- base::FilePath exe_dir;
- PathService::Get(base::DIR_EXE, &exe_dir);
- return exe_dir.AppendASCII(binding_path);
-}
-
-} // namespace test
-} // namespace mojo
diff --git a/mojo/edk/test/test_utils_win.cc b/mojo/edk/test/test_utils_win.cc
deleted file mode 100644
index 2387945..0000000
--- a/mojo/edk/test/test_utils_win.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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/test/test_utils.h"
-
-#include <windows.h>
-#include <fcntl.h>
-#include <io.h>
-#include <string.h>
-
-#include "base/base_paths.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-
-namespace mojo {
-namespace test {
-
-bool BlockingWrite(const embedder::PlatformHandle& handle,
- const void* buffer,
- size_t bytes_to_write,
- size_t* bytes_written) {
- OVERLAPPED overlapped = {0};
- DWORD bytes_written_dword = 0;
-
- if (!WriteFile(handle.handle, buffer, static_cast<DWORD>(bytes_to_write),
- &bytes_written_dword, &overlapped)) {
- if (GetLastError() != ERROR_IO_PENDING ||
- !GetOverlappedResult(handle.handle, &overlapped, &bytes_written_dword,
- TRUE)) {
- return false;
- }
- }
-
- *bytes_written = bytes_written_dword;
- return true;
-}
-
-bool BlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read) {
- OVERLAPPED overlapped = {0};
- DWORD bytes_read_dword = 0;
-
- if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size),
- &bytes_read_dword, &overlapped)) {
- if (GetLastError() != ERROR_IO_PENDING ||
- !GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword,
- TRUE)) {
- return false;
- }
- }
-
- *bytes_read = bytes_read_dword;
- return true;
-}
-
-bool NonBlockingRead(const embedder::PlatformHandle& handle,
- void* buffer,
- size_t buffer_size,
- size_t* bytes_read) {
- OVERLAPPED overlapped = {0};
- DWORD bytes_read_dword = 0;
-
- if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size),
- &bytes_read_dword, &overlapped)) {
- if (GetLastError() != ERROR_IO_PENDING)
- return false;
-
- CancelIo(handle.handle);
-
- if (!GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword,
- TRUE)) {
- *bytes_read = 0;
- return true;
- }
- }
-
- *bytes_read = bytes_read_dword;
- return true;
-}
-
-embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) {
- CHECK(fp);
-
- HANDLE rv = INVALID_HANDLE_VALUE;
- PCHECK(DuplicateHandle(
- GetCurrentProcess(),
- reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(fp.get()))),
- GetCurrentProcess(), &rv, 0, TRUE, DUPLICATE_SAME_ACCESS))
- << "DuplicateHandle";
- return embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv));
-}
-
-base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h,
- const char* mode) {
- CHECK(h.is_valid());
- // Microsoft's documentation for |_open_osfhandle()| only discusses these
- // flags (and |_O_WTEXT|). Hmmm.
- int flags = 0;
- if (strchr(mode, 'a'))
- flags |= _O_APPEND;
- if (strchr(mode, 'r'))
- flags |= _O_RDONLY;
- if (strchr(mode, 't'))
- flags |= _O_TEXT;
- base::ScopedFILE rv(_fdopen(
- _open_osfhandle(reinterpret_cast<intptr_t>(h.release().handle), flags),
- mode));
- PCHECK(rv) << "_fdopen";
- return rv.Pass();
-}
-
-base::FilePath GetFilePathForJSResource(const std::string& path) {
- std::string binding_path = "gen/" + path + ".js";
- base::ReplaceChars(binding_path, "//", "\\", &binding_path);
- base::FilePath exe_dir;
- PathService::Get(base::DIR_EXE, &exe_dir);
- return exe_dir.AppendASCII(binding_path);
-}
-
-} // namespace test
-} // namespace mojo