summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/mojo/services/media_renderer_apptest.cc3
-rw-r--r--mojo/cc/output_surface_mojo.cc3
-rw-r--r--mojo/edk/embedder/embedder_unittest.cc8
-rw-r--r--mojo/edk/js/core.cc2
-rw-r--r--mojo/edk/mojo_edk.gyp132
-rw-r--r--mojo/edk/mojo_edk_system_impl.gypi118
-rw-r--r--mojo/edk/system/BUILD.gn20
-rw-r--r--mojo/edk/system/channel.cc25
-rw-r--r--mojo/edk/system/channel.h2
-rw-r--r--mojo/edk/system/channel_endpoint.cc26
-rw-r--r--mojo/edk/system/channel_endpoint.h11
-rw-r--r--mojo/edk/system/channel_endpoint_client.h2
-rw-r--r--mojo/edk/system/channel_unittest.cc8
-rw-r--r--mojo/edk/system/core_unittest.cc100
-rw-r--r--mojo/edk/system/local_data_pipe.cc6
-rw-r--r--mojo/edk/system/local_data_pipe_unittest.cc171
-rw-r--r--mojo/edk/system/local_message_pipe_endpoint.cc3
-rw-r--r--mojo/edk/system/message_in_transit.cc8
-rw-r--r--mojo/edk/system/message_in_transit.h16
-rw-r--r--mojo/edk/system/message_pipe.cc27
-rw-r--r--mojo/edk/system/message_pipe.h7
-rw-r--r--mojo/edk/system/message_pipe_dispatcher_unittest.cc69
-rw-r--r--mojo/edk/system/message_pipe_perftest.cc8
-rw-r--r--mojo/edk/system/message_pipe_unittest.cc101
-rw-r--r--mojo/edk/system/multiprocess_message_pipe_unittest.cc53
-rw-r--r--mojo/edk/system/raw_channel_unittest.cc7
-rw-r--r--mojo/edk/system/remote_message_pipe_unittest.cc113
-rw-r--r--mojo/edk/system/run_all_unittests.cc8
-rw-r--r--mojo/edk/test/multiprocess_test_helper_unittest.cc48
-rw-r--r--mojo/public/VERSION2
-rw-r--r--mojo/public/c/system/types.h3
-rw-r--r--mojo/public/cpp/application/application_test_base.h19
-rw-r--r--mojo/public/cpp/application/lib/application_test_base.cc30
-rw-r--r--mojo/public/cpp/application/lib/application_test_main.cc5
-rw-r--r--mojo/public/dart/src/types.dart1
-rw-r--r--mojo/public/go/system/impl/mojo_types.go1
-rw-r--r--mojo/public/interfaces/bindings/tests/BUILD.gn1
-rw-r--r--mojo/public/interfaces/bindings/tests/regression_tests.mojom6
-rw-r--r--mojo/public/interfaces/bindings/tests/regression_tests_import.mojom11
-rw-r--r--mojo/public/java/system/src/org/chromium/mojo/system/Core.java11
-rw-r--r--mojo/public/js/core.js1
-rw-r--r--mojo/public/mojo_application.gni59
-rw-r--r--mojo/public/mojo_public.gyp3
-rw-r--r--mojo/public/python/mojo/bindings/descriptor.py98
-rw-r--r--mojo/public/python/mojo/bindings/reflection.py12
-rw-r--r--mojo/public/python/mojo/bindings/serialization.py79
-rw-r--r--mojo/public/python/mojo/c_core.pxd1
-rw-r--r--mojo/public/python/mojo/system.pyx1
-rw-r--r--mojo/public/tools/bindings/generators/mojom_java_generator.py11
-rw-r--r--mojo/public/tools/bindings/generators/mojom_python_generator.py6
-rwxr-xr-xmojo/public/tools/bindings/mojom_bindings_generator.py78
-rw-r--r--mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi17
-rwxr-xr-xmojo/public/tools/prepend.py37
-rw-r--r--mojo/services/public/cpp/geometry/BUILD.gn2
-rw-r--r--mojo/services/public/cpp/network/BUILD.gn19
-rw-r--r--mojo/services/public/interfaces/gpu/BUILD.gn1
-rw-r--r--mojo/services/public/interfaces/gpu/gpu.mojom6
-rw-r--r--mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom12
-rw-r--r--mojo/services/public/interfaces/surfaces/surfaces.mojom11
-rw-r--r--mojo/services/public/mojo_services_public.gyp1
60 files changed, 1121 insertions, 529 deletions
diff --git a/media/mojo/services/media_renderer_apptest.cc b/media/mojo/services/media_renderer_apptest.cc
index bdf5048..8813b38 100644
--- a/media/mojo/services/media_renderer_apptest.cc
+++ b/media/mojo/services/media_renderer_apptest.cc
@@ -99,8 +99,7 @@ namespace media {
class MojoRendererTest : public mojo::test::ApplicationTestBase {
public:
MojoRendererTest()
- : ApplicationTestBase(mojo::Array<mojo::String>()),
- service_provider_(NULL) {}
+ : service_provider_(NULL) {}
~MojoRendererTest() override {}
protected:
diff --git a/mojo/cc/output_surface_mojo.cc b/mojo/cc/output_surface_mojo.cc
index 193c7ac..e7a8def 100644
--- a/mojo/cc/output_surface_mojo.cc
+++ b/mojo/cc/output_surface_mojo.cc
@@ -49,7 +49,8 @@ void OutputSurfaceMojo::SwapBuffers(cc::CompositorFrame* frame) {
surface_size_ = frame_size;
}
- surface_->SubmitFrame(SurfaceId::From(surface_id_), Frame::From(*frame));
+ surface_->SubmitFrame(SurfaceId::From(surface_id_), Frame::From(*frame),
+ mojo::Closure());
client_->DidSwapBuffers();
client_->DidSwapBuffersComplete();
diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc
index 16a5ce2..b138a2d 100644
--- a/mojo/edk/embedder/embedder_unittest.cc
+++ b/mojo/edk/embedder/embedder_unittest.cc
@@ -282,7 +282,13 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) {
// 10. (close)
// 11. (wait/cl.)
// 12. (wait/cl.)
-TEST_F(EmbedderTest, MultiprocessChannels) {
+#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");
diff --git a/mojo/edk/js/core.cc b/mojo/edk/js/core.cc
index 232f0e3..e70931d 100644
--- a/mojo/edk/js/core.cc
+++ b/mojo/edk/js/core.cc
@@ -288,6 +288,8 @@ v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) {
.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)
diff --git a/mojo/edk/mojo_edk.gyp b/mojo/edk/mojo_edk.gyp
index 0959aac..b85cae7 100644
--- a/mojo/edk/mojo_edk.gyp
+++ b/mojo/edk/mojo_edk.gyp
@@ -15,115 +15,9 @@
'../../base/base.gyp:base',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
],
- 'defines': [
- 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
- 'MOJO_SYSTEM_IMPLEMENTATION',
- 'MOJO_USE_SYSTEM_IMPL',
+ 'includes': [
+ 'mojo_edk_system_impl.gypi',
],
- 'sources': [
- 'embedder/configuration.h',
- 'embedder/channel_info_forward.h',
- 'embedder/channel_init.cc',
- 'embedder/channel_init.h',
- 'embedder/embedder.cc',
- 'embedder/embedder.h',
- 'embedder/embedder_internal.h',
- 'embedder/entrypoints.cc',
- 'embedder/platform_channel_pair.cc',
- 'embedder/platform_channel_pair.h',
- 'embedder/platform_channel_pair_posix.cc',
- 'embedder/platform_channel_pair_win.cc',
- 'embedder/platform_channel_utils_posix.cc',
- 'embedder/platform_channel_utils_posix.h',
- 'embedder/platform_handle.cc',
- 'embedder/platform_handle.h',
- 'embedder/platform_handle_utils.h',
- 'embedder/platform_handle_utils_posix.cc',
- 'embedder/platform_handle_utils_win.cc',
- 'embedder/platform_handle_vector.h',
- 'embedder/platform_shared_buffer.h',
- 'embedder/platform_support.h',
- 'embedder/scoped_platform_handle.h',
- 'embedder/simple_platform_shared_buffer.cc',
- 'embedder/simple_platform_shared_buffer.h',
- 'embedder/simple_platform_shared_buffer_posix.cc',
- 'embedder/simple_platform_shared_buffer_win.cc',
- 'embedder/simple_platform_support.cc',
- 'embedder/simple_platform_support.h',
- 'system/channel.cc',
- 'system/channel.h',
- 'system/channel_endpoint.cc',
- 'system/channel_endpoint.h',
- 'system/channel_endpoint_client.h',
- 'system/channel_endpoint_id.cc',
- 'system/channel_endpoint_id.h',
- 'system/channel_info.cc',
- 'system/channel_info.h',
- 'system/channel_manager.cc',
- 'system/channel_manager.h',
- 'system/configuration.cc',
- 'system/configuration.h',
- 'system/core.cc',
- 'system/core.h',
- 'system/data_pipe.cc',
- 'system/data_pipe.h',
- 'system/data_pipe_consumer_dispatcher.cc',
- 'system/data_pipe_consumer_dispatcher.h',
- 'system/data_pipe_producer_dispatcher.cc',
- 'system/data_pipe_producer_dispatcher.h',
- 'system/dispatcher.cc',
- 'system/dispatcher.h',
- 'system/handle_signals_state.h',
- 'system/handle_table.cc',
- 'system/handle_table.h',
- 'system/local_data_pipe.cc',
- 'system/local_data_pipe.h',
- 'system/local_message_pipe_endpoint.cc',
- 'system/local_message_pipe_endpoint.h',
- 'system/mapping_table.cc',
- 'system/mapping_table.h',
- 'system/memory.cc',
- 'system/memory.h',
- 'system/message_in_transit.cc',
- 'system/message_in_transit.h',
- 'system/message_in_transit_queue.cc',
- 'system/message_in_transit_queue.h',
- 'system/message_pipe.cc',
- 'system/message_pipe.h',
- 'system/message_pipe_dispatcher.cc',
- 'system/message_pipe_dispatcher.h',
- 'system/message_pipe_endpoint.cc',
- 'system/message_pipe_endpoint.h',
- 'system/options_validation.h',
- 'system/platform_handle_dispatcher.cc',
- 'system/platform_handle_dispatcher.h',
- 'system/proxy_message_pipe_endpoint.cc',
- 'system/proxy_message_pipe_endpoint.h',
- 'system/raw_channel.cc',
- 'system/raw_channel.h',
- 'system/raw_channel_posix.cc',
- 'system/raw_channel_win.cc',
- 'system/shared_buffer_dispatcher.cc',
- 'system/shared_buffer_dispatcher.h',
- 'system/simple_dispatcher.cc',
- 'system/simple_dispatcher.h',
- 'system/transport_data.cc',
- 'system/transport_data.h',
- 'system/waiter.cc',
- 'system/waiter.h',
- 'system/waiter_list.cc',
- 'system/waiter_list.h',
- # 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.
- 'embedder/test_embedder.cc',
- 'embedder/test_embedder.h',
- ],
- 'all_dependent_settings': {
- # Ensures that dependent projects import the core functions on Windows.
- 'defines': ['MOJO_USE_SYSTEM_IMPL'],
- }
},
{
# GN version: //mojo/edk/js
@@ -225,4 +119,26 @@
],
},
],
+ 'conditions': [
+ ['OS=="win" and target_arch=="ia32"', {
+ 'targets': [
+ {
+ 'target_name': 'mojo_system_impl_win64',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../base/base.gyp:base_win64',
+ '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+ ],
+ 'includes': [
+ 'mojo_edk_system_impl.gypi',
+ ],
+ 'configurations': {
+ 'Common_Base': {
+ 'msvs_target_platform': 'x64',
+ },
+ },
+ },
+ ],
+ }],
+ ],
}
diff --git a/mojo/edk/mojo_edk_system_impl.gypi b/mojo/edk/mojo_edk_system_impl.gypi
new file mode 100644
index 0000000..a0af387
--- /dev/null
+++ b/mojo/edk/mojo_edk_system_impl.gypi
@@ -0,0 +1,118 @@
+# Copyright (c) 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.
+
+# The dictionary here is defined for use by the "mojo_system_impl" and
+# "mojo_system_impl_win64" targets in mojo/edk/mojo_edk.gyp. It's defined in
+# this .gypi file so the sections aren't duplicated.
+{
+ 'defines': [
+ 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
+ 'MOJO_SYSTEM_IMPLEMENTATION',
+ 'MOJO_USE_SYSTEM_IMPL',
+ ],
+ 'sources': [
+ 'embedder/configuration.h',
+ 'embedder/channel_info_forward.h',
+ 'embedder/channel_init.cc',
+ 'embedder/channel_init.h',
+ 'embedder/embedder.cc',
+ 'embedder/embedder.h',
+ 'embedder/embedder_internal.h',
+ 'embedder/entrypoints.cc',
+ 'embedder/platform_channel_pair.cc',
+ 'embedder/platform_channel_pair.h',
+ 'embedder/platform_channel_pair_posix.cc',
+ 'embedder/platform_channel_pair_win.cc',
+ 'embedder/platform_channel_utils_posix.cc',
+ 'embedder/platform_channel_utils_posix.h',
+ 'embedder/platform_handle.cc',
+ 'embedder/platform_handle.h',
+ 'embedder/platform_handle_utils.h',
+ 'embedder/platform_handle_utils_posix.cc',
+ 'embedder/platform_handle_utils_win.cc',
+ 'embedder/platform_handle_vector.h',
+ 'embedder/platform_shared_buffer.h',
+ 'embedder/platform_support.h',
+ 'embedder/scoped_platform_handle.h',
+ 'embedder/simple_platform_shared_buffer.cc',
+ 'embedder/simple_platform_shared_buffer.h',
+ 'embedder/simple_platform_shared_buffer_posix.cc',
+ 'embedder/simple_platform_shared_buffer_win.cc',
+ 'embedder/simple_platform_support.cc',
+ 'embedder/simple_platform_support.h',
+ 'system/channel.cc',
+ 'system/channel.h',
+ 'system/channel_endpoint.cc',
+ 'system/channel_endpoint.h',
+ 'system/channel_endpoint_client.h',
+ 'system/channel_endpoint_id.cc',
+ 'system/channel_endpoint_id.h',
+ 'system/channel_info.cc',
+ 'system/channel_info.h',
+ 'system/channel_manager.cc',
+ 'system/channel_manager.h',
+ 'system/configuration.cc',
+ 'system/configuration.h',
+ 'system/core.cc',
+ 'system/core.h',
+ 'system/data_pipe.cc',
+ 'system/data_pipe.h',
+ 'system/data_pipe_consumer_dispatcher.cc',
+ 'system/data_pipe_consumer_dispatcher.h',
+ 'system/data_pipe_producer_dispatcher.cc',
+ 'system/data_pipe_producer_dispatcher.h',
+ 'system/dispatcher.cc',
+ 'system/dispatcher.h',
+ 'system/handle_signals_state.h',
+ 'system/handle_table.cc',
+ 'system/handle_table.h',
+ 'system/local_data_pipe.cc',
+ 'system/local_data_pipe.h',
+ 'system/local_message_pipe_endpoint.cc',
+ 'system/local_message_pipe_endpoint.h',
+ 'system/mapping_table.cc',
+ 'system/mapping_table.h',
+ 'system/memory.cc',
+ 'system/memory.h',
+ 'system/message_in_transit.cc',
+ 'system/message_in_transit.h',
+ 'system/message_in_transit_queue.cc',
+ 'system/message_in_transit_queue.h',
+ 'system/message_pipe.cc',
+ 'system/message_pipe.h',
+ 'system/message_pipe_dispatcher.cc',
+ 'system/message_pipe_dispatcher.h',
+ 'system/message_pipe_endpoint.cc',
+ 'system/message_pipe_endpoint.h',
+ 'system/options_validation.h',
+ 'system/platform_handle_dispatcher.cc',
+ 'system/platform_handle_dispatcher.h',
+ 'system/proxy_message_pipe_endpoint.cc',
+ 'system/proxy_message_pipe_endpoint.h',
+ 'system/raw_channel.cc',
+ 'system/raw_channel.h',
+ 'system/raw_channel_posix.cc',
+ 'system/raw_channel_win.cc',
+ 'system/shared_buffer_dispatcher.cc',
+ 'system/shared_buffer_dispatcher.h',
+ 'system/simple_dispatcher.cc',
+ 'system/simple_dispatcher.h',
+ 'system/transport_data.cc',
+ 'system/transport_data.h',
+ 'system/waiter.cc',
+ 'system/waiter.h',
+ 'system/waiter_list.cc',
+ 'system/waiter_list.h',
+ # 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.
+ 'embedder/test_embedder.cc',
+ 'embedder/test_embedder.h',
+ ],
+ 'all_dependent_settings': {
+ # Ensures that dependent projects import the core functions on Windows.
+ 'defines': ['MOJO_USE_SYSTEM_IMPL'],
+ },
+}
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
index b87c76a..0701484 100644
--- a/mojo/edk/system/BUILD.gn
+++ b/mojo/edk/system/BUILD.gn
@@ -2,6 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+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.
@@ -143,6 +148,12 @@ test("mojo_system_unittests") {
"//testing/gtest",
]
+ if (is_android) {
+ deps += [
+ "//testing/android:native_test_native_code",
+ ]
+ }
+
allow_circular_includes_from = [ "//mojo/edk/embedder:embedder_unittests" ]
}
@@ -165,3 +176,12 @@ test("mojo_message_pipe_perftests") {
"//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/channel.cc b/mojo/edk/system/channel.cc
index 50d4b65..3d6c54f 100644
--- a/mojo/edk/system/channel.cc
+++ b/mojo/edk/system/channel.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include "base/bind.h"
-#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
@@ -237,9 +236,8 @@ void Channel::OnReadMessage(
DCHECK(creation_thread_checker_.CalledOnValidThread());
switch (message_view.type()) {
- case MessageInTransit::kTypeMessagePipeEndpoint:
- case MessageInTransit::kTypeMessagePipe:
- OnReadMessageForDownstream(message_view, platform_handles.Pass());
+ case MessageInTransit::kTypeEndpoint:
+ OnReadMessageForEndpoint(message_view, platform_handles.Pass());
break;
case MessageInTransit::kTypeChannel:
OnReadMessageForChannel(message_view, platform_handles.Pass());
@@ -283,12 +281,11 @@ void Channel::OnError(Error error) {
Shutdown();
}
-void Channel::OnReadMessageForDownstream(
+void Channel::OnReadMessageForEndpoint(
const MessageInTransit::View& message_view,
embedder::ScopedPlatformHandleVectorPtr platform_handles) {
DCHECK(creation_thread_checker_.CalledOnValidThread());
- DCHECK(message_view.type() == MessageInTransit::kTypeMessagePipeEndpoint ||
- message_view.type() == MessageInTransit::kTypeMessagePipe);
+ DCHECK(message_view.type() == MessageInTransit::kTypeEndpoint);
ChannelEndpointId local_id = message_view.destination_id();
if (!local_id.is_valid()) {
@@ -331,12 +328,16 @@ void Channel::OnReadMessageForDownstream(
return;
}
- if (!endpoint->OnReadMessage(message_view, platform_handles.Pass())) {
- HandleLocalError(
- base::StringPrintf("Failed to enqueue message to local ID %u",
- static_cast<unsigned>(local_id.value())));
- 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(
diff --git a/mojo/edk/system/channel.h b/mojo/edk/system/channel.h
index e0ecc3b..227d202 100644
--- a/mojo/edk/system/channel.h
+++ b/mojo/edk/system/channel.h
@@ -139,7 +139,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
void OnError(Error error) override;
// Helpers for |OnReadMessage| (only called on the creation thread):
- void OnReadMessageForDownstream(
+ void OnReadMessageForEndpoint(
const MessageInTransit::View& message_view,
embedder::ScopedPlatformHandleVectorPtr platform_handles);
void OnReadMessageForChannel(
diff --git a/mojo/edk/system/channel_endpoint.cc b/mojo/edk/system/channel_endpoint.cc
index ca86b5f..a8bbbb2 100644
--- a/mojo/edk/system/channel_endpoint.cc
+++ b/mojo/edk/system/channel_endpoint.cc
@@ -7,7 +7,6 @@
#include "base/logging.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_endpoint_client.h"
-#include "mojo/edk/system/transport_data.h"
namespace mojo {
namespace system {
@@ -19,7 +18,7 @@ ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client,
DCHECK(client_.get() || message_queue);
if (message_queue)
- paused_message_queue_.Swap(message_queue);
+ channel_message_queue_.Swap(message_queue);
}
bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) {
@@ -33,7 +32,7 @@ bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) {
// 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.
- paused_message_queue_.AddMessage(message.Pass());
+ channel_message_queue_.AddMessage(message.Pass());
return true;
}
@@ -72,8 +71,8 @@ void ChannelEndpoint::AttachAndRun(Channel* channel,
local_id_ = local_id;
remote_id_ = remote_id;
- while (!paused_message_queue_.IsEmpty()) {
- LOG_IF(WARNING, !WriteMessageNoLock(paused_message_queue_.GetMessage()))
+ while (!channel_message_queue_.IsEmpty()) {
+ LOG_IF(WARNING, !WriteMessageNoLock(channel_message_queue_.GetMessage()))
<< "Failed to write enqueue message to channel";
}
@@ -85,10 +84,7 @@ void ChannelEndpoint::AttachAndRun(Channel* channel,
}
}
-bool ChannelEndpoint::OnReadMessage(
- const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles) {
- scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view));
+void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) {
scoped_refptr<ChannelEndpointClient> client;
unsigned client_port;
{
@@ -97,15 +93,7 @@ bool ChannelEndpoint::OnReadMessage(
if (!client_.get()) {
// This isn't a failure per se. (It just means that, e.g., the other end
// of the message point closed first.)
- return true;
- }
-
- 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(),
- channel_));
+ return;
}
// Take a ref, and call |OnReadMessage()| outside the lock.
@@ -113,7 +101,7 @@ bool ChannelEndpoint::OnReadMessage(
client_port = client_port_;
}
- return client->OnReadMessage(client_port, message.Pass());
+ client->OnReadMessage(client_port, message.Pass());
}
void ChannelEndpoint::DetachFromChannel() {
diff --git a/mojo/edk/system/channel_endpoint.h b/mojo/edk/system/channel_endpoint.h
index 8de169b..71b6f9b 100644
--- a/mojo/edk/system/channel_endpoint.h
+++ b/mojo/edk/system/channel_endpoint.h
@@ -9,9 +9,7 @@
#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_id.h"
-#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/message_in_transit_queue.h"
#include "mojo/edk/system/system_impl_export.h"
@@ -139,15 +137,14 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint
// Methods called by |Channel|:
// Called when the |Channel| takes a reference to this object. This will send
- // all queue messages (in |paused_message_queue_|).
+ // 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|.
- bool OnReadMessage(const MessageInTransit::View& message_view,
- embedder::ScopedPlatformHandleVectorPtr platform_handles);
+ void OnReadMessage(scoped_ptr<MessageInTransit> message);
// Called before the |Channel| gives up its reference to this object.
void DetachFromChannel();
@@ -182,8 +179,8 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint
ChannelEndpointId remote_id_;
// This queue is used before we're running on a channel and ready to send
- // messages.
- MessageInTransitQueue paused_message_queue_;
+ // messages to the channel.
+ MessageInTransitQueue channel_message_queue_;
DISALLOW_COPY_AND_ASSIGN(ChannelEndpoint);
};
diff --git a/mojo/edk/system/channel_endpoint_client.h b/mojo/edk/system/channel_endpoint_client.h
index e14326f..7a7d5b8 100644
--- a/mojo/edk/system/channel_endpoint_client.h
+++ b/mojo/edk/system/channel_endpoint_client.h
@@ -38,7 +38,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointClient
// called by |Channel| when it receives a message for the |ChannelEndpoint|.
// (|port| is the value passed to |ChannelEndpoint|'s constructor as
// |client_port|.)
- virtual bool OnReadMessage(unsigned port,
+ virtual void OnReadMessage(unsigned port,
scoped_ptr<MessageInTransit> message) = 0;
// Called by |ChannelEndpoint| when the |Channel| is relinquishing its pointer
diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc
index 68b1315..e84ab5b 100644
--- a/mojo/edk/system/channel_unittest.cc
+++ b/mojo/edk/system/channel_unittest.cc
@@ -243,8 +243,8 @@ TEST_F(ChannelTest, ShutdownAfterAttach) {
waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr));
HandleSignalsState hss;
mp->RemoveWaiter(0, &waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -279,8 +279,8 @@ TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) {
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 96780f7..51a4022 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -18,6 +18,9 @@ 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;
@@ -545,11 +548,9 @@ TEST_F(CoreTest, MessagePipe) {
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(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Try to read anyway.
char buffer[1] = {'a'};
@@ -568,14 +569,12 @@ TEST_F(CoreTest, MessagePipe) {
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(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_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(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
// Also check that |h[1]| is writable using |WaitMany()|.
signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
@@ -590,11 +589,9 @@ TEST_F(CoreTest, MessagePipe) {
MakeUserPointer(hss)));
EXPECT_EQ(1u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Write to |h[1]|.
buffer[0] = 'b';
@@ -617,11 +614,9 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(0u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Read from |h[0]|.
// First, get only the size.
@@ -649,8 +644,7 @@ TEST_F(CoreTest, MessagePipe) {
core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
// Write to |h[0]|.
buffer[0] = 'd';
@@ -667,15 +661,19 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000,
MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
+ 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, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
+ 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,
@@ -688,8 +686,8 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
MakeUserPointer(&hss[0])));
- EXPECT_EQ(0u, hss[0].satisfied_signals);
- EXPECT_EQ(0u, hss[0].satisfiable_signals);
+ 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';
@@ -732,8 +730,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -773,8 +770,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -797,8 +793,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -833,8 +828,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -870,12 +864,14 @@ TEST_F(CoreTest, DataPipe) {
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, hss.satisfiable_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, hss.satisfiable_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;
@@ -883,16 +879,18 @@ TEST_F(CoreTest, DataPipe) {
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, hss.satisfiable_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, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write.
- char elements[2] = {'A', 'B'};
+ signed char elements[2] = {'A', 'B'};
uint32_t num_bytes = 2u;
EXPECT_EQ(MOJO_RESULT_OK,
core()->WriteData(ph, UserPointer<const void>(elements),
@@ -905,7 +903,8 @@ TEST_F(CoreTest, DataPipe) {
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, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one character.
elements[0] = -1;
@@ -1022,7 +1021,8 @@ TEST_F(CoreTest, DataPipe) {
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, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// TODO(vtl): More.
@@ -1034,8 +1034,8 @@ TEST_F(CoreTest, DataPipe) {
EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ 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));
}
@@ -1075,8 +1075,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1111,7 +1110,8 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
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, hss.satisfiable_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),
@@ -1131,8 +1131,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1167,7 +1166,8 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
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, hss.satisfiable_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),
@@ -1225,7 +1225,8 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
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, hss.satisfiable_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;
@@ -1251,8 +1252,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
diff --git a/mojo/edk/system/local_data_pipe.cc b/mojo/edk/system/local_data_pipe.cc
index 177b238..8b9f673 100644
--- a/mojo/edk/system/local_data_pipe.cc
+++ b/mojo/edk/system/local_data_pipe.cc
@@ -160,7 +160,10 @@ HandleSignalsState LocalDataPipe::ProducerGetHandleSignalsStateImplNoLock()
!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;
}
@@ -293,6 +296,9 @@ HandleSignalsState LocalDataPipe::ConsumerGetHandleSignalsStateImplNoLock()
} 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;
}
diff --git a/mojo/edk/system/local_data_pipe_unittest.cc b/mojo/edk/system/local_data_pipe_unittest.cc
index 9ba6b21..cea50a0 100644
--- a/mojo/edk/system/local_data_pipe_unittest.cc
+++ b/mojo/edk/system/local_data_pipe_unittest.cc
@@ -239,7 +239,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
MOJO_RESULT_FAILED_PRECONDITION,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Already writable.
waiter.Init();
@@ -266,7 +267,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one element.
elements[0] = -1;
@@ -289,7 +291,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Do it again.
waiter.Init();
@@ -314,7 +317,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_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;
@@ -357,7 +361,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write one element.
elements[0] = 123;
@@ -381,12 +386,75 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ 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->ProducerAddWaiter(&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->ProducerRemoveWaiter(&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->ConsumerAddWaiter(&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->ConsumerRemoveWaiter(&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|.
@@ -411,7 +479,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_FAILED_PRECONDITION,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, &hss));
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Not yet readable.
waiter.Init();
@@ -422,7 +491,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write two elements.
int32_t elements[2] = {123, 456};
@@ -438,7 +508,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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]));
@@ -453,7 +524,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one element.
elements[0] = -1;
@@ -473,7 +545,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read one element.
elements[0] = -1;
@@ -506,7 +579,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Close the producer.
dp->ProducerClose();
@@ -517,8 +591,10 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
EXPECT_EQ(
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ 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;
@@ -537,8 +613,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
dp->ConsumerClose();
}
@@ -574,7 +650,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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.
@@ -597,7 +674,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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.
@@ -627,8 +705,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
EXPECT_EQ(56u, context);
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
dp->ConsumerClose();
}
@@ -657,7 +735,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_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;
@@ -676,7 +755,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// It shouldn't be readable yet either.
waiter.Init();
@@ -687,7 +767,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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(
@@ -700,7 +781,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// And readable.
waiter.Init();
@@ -709,7 +791,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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.
@@ -728,7 +811,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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));
@@ -749,7 +833,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// But not readable.
waiter.Init();
@@ -760,7 +845,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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));
@@ -772,7 +858,8 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
dp->ProducerClose();
dp->ConsumerClose();
@@ -801,7 +888,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Not readable.
waiter.Init();
@@ -812,7 +900,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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;
@@ -828,7 +917,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Now readable.
waiter.Init();
@@ -837,7 +927,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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));
@@ -854,7 +945,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// And still readable.
waiter.Init();
@@ -863,7 +955,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_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));
@@ -881,7 +974,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// No longer readable.
waiter.Init();
@@ -892,7 +986,8 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
dp->ProducerClose();
dp->ConsumerClose();
diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc
index 124241e..86d241c 100644
--- a/mojo/edk/system/local_message_pipe_endpoint.cc
+++ b/mojo/edk/system/local_message_pipe_endpoint.cc
@@ -137,7 +137,10 @@ HandleSignalsState LocalMessagePipeEndpoint::GetHandleSignalsState() const {
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;
}
diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc
index 0f2ff5e..624a546 100644
--- a/mojo/edk/system/message_in_transit.cc
+++ b/mojo/edk/system/message_in_transit.cc
@@ -15,15 +15,13 @@ namespace mojo {
namespace system {
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
- MessageInTransit::kTypeMessagePipeEndpoint;
-STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
- MessageInTransit::kTypeMessagePipe;
+ 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::kSubtypeMessagePipeEndpointData;
+ MessageInTransit::kSubtypeEndpointData;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
MessageInTransit::kSubtypeChannelAttachAndRunEndpoint;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
@@ -110,6 +108,8 @@ MessageInTransit::MessageInTransit(Type type,
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)
diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h
index 2b9da6d..0f92b05 100644
--- a/mojo/edk/system/message_in_transit.h
+++ b/mojo/edk/system/message_in_transit.h
@@ -44,20 +44,16 @@ class TransportData;
class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
public:
typedef uint16_t Type;
- // Messages that are forwarded to |MessagePipeEndpoint|s.
- static const Type kTypeMessagePipeEndpoint = 0;
- // Messages that are forwarded to |MessagePipe|s.
- static const Type kTypeMessagePipe = 1;
+ // Messages that are forwarded to endpoints.
+ static const Type kTypeEndpoint = 0;
// Messages that are consumed by the |Channel|.
- static const Type kTypeChannel = 2;
+ static const Type kTypeChannel = 1;
// Messages that are consumed by the |RawChannel| (implementation).
- static const Type kTypeRawChannel = 3;
+ static const Type kTypeRawChannel = 2;
typedef uint16_t Subtype;
- // Subtypes for type |kTypeMessagePipeEndpoint|:
- static const Subtype kSubtypeMessagePipeEndpointData = 0;
- // Subtypes for type |kTypeMessagePipe|:
- // Nothing currently.
+ // Subtypes for type |kTypeEndpoint|:
+ static const Subtype kSubtypeEndpointData = 0;
// Subtypes for type |kTypeChannel|:
static const Subtype kSubtypeChannelAttachAndRunEndpoint = 0;
static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc
index 8e1be57..ee5036f 100644
--- a/mojo/edk/system/message_pipe.cc
+++ b/mojo/edk/system/message_pipe.cc
@@ -142,8 +142,8 @@ MojoResult MessagePipe::WriteMessage(
return EnqueueMessage(
GetPeerPort(port),
make_scoped_ptr(new MessageInTransit(
- MessageInTransit::kTypeMessagePipeEndpoint,
- MessageInTransit::kSubtypeMessagePipeEndpointData, num_bytes, bytes)),
+ MessageInTransit::kTypeEndpoint,
+ MessageInTransit::kSubtypeEndpointData, num_bytes, bytes)),
transports);
}
@@ -287,14 +287,16 @@ bool MessagePipe::EndSerialize(
return true;
}
-bool MessagePipe::OnReadMessage(unsigned port,
+void MessagePipe::OnReadMessage(unsigned port,
scoped_ptr<MessageInTransit> message) {
// 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|).
- return EnqueueMessage(GetPeerPort(port), message.Pass(), nullptr) ==
- MOJO_RESULT_OK;
+ MojoResult result =
+ EnqueueMessage(GetPeerPort(port), message.Pass(), nullptr);
+ DLOG_IF(WARNING, result != MOJO_RESULT_OK)
+ << "EnqueueMessage() failed (result = " << result << ")";
}
void MessagePipe::OnDetachFromChannel(unsigned port) {
@@ -319,12 +321,7 @@ MojoResult MessagePipe::EnqueueMessage(
DCHECK(port == 0 || port == 1);
DCHECK(message);
- if (message->type() == MessageInTransit::kTypeMessagePipe) {
- DCHECK(!transports);
- return HandleControlMessage(port, message.Pass());
- }
-
- DCHECK_EQ(message->type(), MessageInTransit::kTypeMessagePipeEndpoint);
+ DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpoint);
base::AutoLock locker(lock_);
DCHECK(endpoints_[GetPeerPort(port)]);
@@ -388,13 +385,5 @@ MojoResult MessagePipe::AttachTransportsNoLock(
return MOJO_RESULT_OK;
}
-MojoResult MessagePipe::HandleControlMessage(
- unsigned /*port*/,
- scoped_ptr<MessageInTransit> message) {
- LOG(WARNING) << "Unrecognized MessagePipe control message subtype "
- << message->subtype();
- return MOJO_RESULT_UNKNOWN;
-}
-
} // namespace system
} // namespace mojo
diff --git a/mojo/edk/system/message_pipe.h b/mojo/edk/system/message_pipe.h
index 1c1af1e..e8f97d0 100644
--- a/mojo/edk/system/message_pipe.h
+++ b/mojo/edk/system/message_pipe.h
@@ -107,7 +107,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient {
embedder::PlatformHandleVector* platform_handles);
// |ChannelEndpointClient| methods:
- bool OnReadMessage(unsigned port,
+ void OnReadMessage(unsigned port,
scoped_ptr<MessageInTransit> message) override;
void OnDetachFromChannel(unsigned port) override;
@@ -128,11 +128,6 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient {
MessageInTransit* message,
std::vector<DispatcherTransport>* transports);
- // Used by |EnqueueMessage()| to handle control messages that are actually
- // meant for us.
- MojoResult HandleControlMessage(unsigned port,
- scoped_ptr<MessageInTransit> message);
-
base::Lock lock_; // Protects the following members.
scoped_ptr<MessagePipeEndpoint> endpoints_[2];
diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc
index 8076a99..303ae6a 100644
--- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc
+++ b/mojo/edk/system/message_pipe_dispatcher_unittest.cc
@@ -29,6 +29,10 @@ 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];
@@ -57,8 +61,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_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
@@ -78,8 +81,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Try adding a readable waiter when already readable (from above).
w.Init();
@@ -88,8 +90,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_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).
@@ -112,8 +113,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
hss = HandleSignalsState();
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Wait for non-zero, finite time for readability on |d0| (will time out).
w.Init();
@@ -128,11 +128,25 @@ TEST(MessagePipeDispatcherTest, Basic) {
hss = HandleSignalsState();
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
- EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
+ // Check the peer closed signal.
+ w.Init();
+ ASSERT_EQ(MOJO_RESULT_OK,
+ d0->AddWaiter(&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->RemoveWaiter(&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());
}
}
@@ -238,8 +252,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) {
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Try reading from |d1|; should fail (nothing to read).
buffer[0] = 0;
@@ -257,8 +270,10 @@ TEST(MessagePipeDispatcherTest, BasicClosed) {
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ 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;
@@ -275,8 +290,10 @@ TEST(MessagePipeDispatcherTest, BasicClosed) {
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ 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;
@@ -293,16 +310,16 @@ TEST(MessagePipeDispatcherTest, BasicClosed) {
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ 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->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ 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).
@@ -374,8 +391,7 @@ TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) {
EXPECT_EQ(1u, context);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Now |d1| is already readable. Try waiting for it again.
{
@@ -390,8 +406,7 @@ TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) {
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Consume what we wrote to |d0|.
buffer[0] = 0;
@@ -420,8 +435,8 @@ TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) {
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);
+ 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());
}
diff --git a/mojo/edk/system/message_pipe_perftest.cc b/mojo/edk/system/message_pipe_perftest.cc
index 9f1ac5d..2387782 100644
--- a/mojo/edk/system/message_pipe_perftest.cc
+++ b/mojo/edk/system/message_pipe_perftest.cc
@@ -140,7 +140,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient) {
// 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.
-TEST_F(MultiprocessMessagePipePerfTest, PingPong) {
+#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;
diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc
index 030084b..c700891 100644
--- a/mojo/edk/system/message_pipe_unittest.cc
+++ b/mojo/edk/system/message_pipe_unittest.cc
@@ -15,6 +15,10 @@ 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
@@ -335,8 +339,7 @@ TEST(MessagePipeTest, BasicWaiting) {
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
@@ -344,8 +347,7 @@ TEST(MessagePipeTest, BasicWaiting) {
MOJO_HANDLE_SIGNAL_WRITABLE,
0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Not yet readable.
waiter.Init();
@@ -355,8 +357,18 @@ TEST(MessagePipeTest, BasicWaiting) {
hss = HandleSignalsState();
mp->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
+
+ // The peer is not closed.
+ waiter.Init();
+ ASSERT_EQ(
+ MOJO_RESULT_OK,
+ mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
+ hss = HandleSignalsState();
+ mp->RemoveWaiter(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;
@@ -368,11 +380,10 @@ TEST(MessagePipeTest, BasicWaiting) {
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
@@ -381,36 +392,48 @@ TEST(MessagePipeTest, BasicWaiting) {
0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// ... and still writable.
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Close port 0.
mp->Close(0);
- // Now port 1 should not be writable.
+ // Port 1 should be signaled with peer closed.
+ waiter.Init();
+ hss = HandleSignalsState();
+ EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
+ mp->AddWaiter(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->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ mp->AddWaiter(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->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ mp->AddWaiter(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;
@@ -425,7 +448,7 @@ TEST(MessagePipeTest, BasicWaiting) {
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 6, nullptr));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
@@ -460,8 +483,7 @@ TEST(MessagePipeTest, ThreadedWaiting) {
mp->RemoveWaiter(1, thread.waiter(), &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
mp->Close(0);
mp->Close(1);
@@ -493,6 +515,29 @@ TEST(MessagePipeTest, ThreadedWaiting) {
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->AddWaiter(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->CancelAllWaiters(1);
+ mp->Close(1);
+
+ // Port 1 is closed, so |Dispatcher::RemoveWaiter()| 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());
@@ -500,7 +545,7 @@ TEST(MessagePipeTest, ThreadedWaiting) {
thread.waiter()->Init();
ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3,
+ mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 4,
nullptr));
thread.Start();
@@ -511,14 +556,14 @@ TEST(MessagePipeTest, ThreadedWaiting) {
HandleSignalsState hss;
mp->RemoveWaiter(1, thread.waiter(), &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->CancelAllWaiters(1);
mp->Close(1);
} // Joins |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(3u, context);
+ EXPECT_EQ(4u, context);
}
} // namespace
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
index ab2e75c..f486152 100644
--- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -62,8 +62,8 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) {
if (result != MOJO_RESULT_OK) {
// It was closed, probably.
CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
- CHECK_EQ(hss.satisfied_signals, 0u);
- CHECK_EQ(hss.satisfiable_signals, 0u);
+ 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));
@@ -96,7 +96,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) {
}
// Sends "hello" to child, and expects "hellohello" back.
-TEST_F(MultiprocessMessagePipeTest, Basic) {
+#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;
@@ -136,7 +142,13 @@ TEST_F(MultiprocessMessagePipeTest, Basic) {
// Sends a bunch of messages to the child. Expects them "repeated" back. Waits
// for the child to close its end before quitting.
-TEST_F(MultiprocessMessagePipeTest, QueueMessages) {
+#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;
@@ -184,8 +196,8 @@ TEST_F(MultiprocessMessagePipeTest, QueueMessages) {
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -211,8 +223,9 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
// 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);
+ 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');
@@ -260,8 +273,9 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
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);
+ 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());
@@ -282,10 +296,11 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
return 0;
}
-#if defined(OS_POSIX)
+#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) {
@@ -364,8 +379,8 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -387,8 +402,9 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) {
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);
+ 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());
@@ -422,10 +438,11 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) {
return 0;
}
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
#define MAYBE_PlatformHandlePassing PlatformHandlePassing
#else
// Not yet implemented (on Windows).
+// Android multi-process tests are not executing the new process. This is flaky.
#define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing
#endif
TEST_F(MultiprocessMessagePipeTest, MAYBE_PlatformHandlePassing) {
@@ -471,8 +488,8 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_PlatformHandlePassing) {
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
diff --git a/mojo/edk/system/raw_channel_unittest.cc b/mojo/edk/system/raw_channel_unittest.cc
index 7717f49..1c39010 100644
--- a/mojo/edk/system/raw_channel_unittest.cc
+++ b/mojo/edk/system/raw_channel_unittest.cc
@@ -38,10 +38,9 @@ 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::kTypeMessagePipeEndpoint,
- MessageInTransit::kSubtypeMessagePipeEndpointData,
- num_bytes, bytes.empty() ? nullptr : &bytes[0]));
+ 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) {
diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc
index e3a320e..926ca0b 100644
--- a/mojo/edk/system/remote_message_pipe_unittest.cc
+++ b/mojo/edk/system/remote_message_pipe_unittest.cc
@@ -41,6 +41,10 @@ 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) {}
@@ -204,8 +208,7 @@ TEST_F(RemoteMessagePipeTest, Basic) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
EXPECT_EQ(MOJO_RESULT_OK,
@@ -233,8 +236,7 @@ TEST_F(RemoteMessagePipeTest, Basic) {
mp0->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_OK,
@@ -261,8 +263,44 @@ TEST_F(RemoteMessagePipeTest, Basic) {
hss = HandleSignalsState();
mp1->RemoveWaiter(1, &waiter, &hss);
}
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ 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->AddWaiter(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->RemoveWaiter(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);
@@ -314,8 +352,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
ChannelEndpointId received_id;
buffer_size = static_cast<uint32_t>(sizeof(received_id));
@@ -349,8 +386,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
mp3->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_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));
@@ -396,7 +432,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+ EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss.satisfiable_signals);
// Make sure there's nothing on the other ports.
@@ -606,8 +642,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -651,8 +686,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
dispatcher->RemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from the dispatcher.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -682,8 +716,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
local_mp->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from "local_mp", port 1.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -721,8 +754,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_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,
@@ -731,8 +763,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Then the second message....
EXPECT_EQ(
MOJO_RESULT_OK,
@@ -741,8 +772,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Then close it.
local_mp->Close(1);
@@ -786,8 +816,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -811,8 +840,10 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
// |dispatcher| should already be readable and not writable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ 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));
@@ -824,8 +855,10 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
EXPECT_STREQ(kHello, read_buffer);
// It should still be readable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ 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));
@@ -837,8 +870,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) {
EXPECT_STREQ(kWorld, read_buffer);
// Now it should no longer be readable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfiable_signals);
+ 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);
@@ -917,8 +950,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1037,8 +1069,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1175,8 +1206,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) {
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1235,8 +1265,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) {
mp0->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 0, port 0.
read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
@@ -1276,8 +1305,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) {
dispatcher->RemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from the dispatcher.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -1307,8 +1335,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) {
local_mp->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from "local_mp", port 1.
memset(read_buffer, 0, sizeof(read_buffer));
diff --git a/mojo/edk/system/run_all_unittests.cc b/mojo/edk/system/run_all_unittests.cc
index 3ea1682..cd61337 100644
--- a/mojo/edk/system/run_all_unittests.cc
+++ b/mojo/edk/system/run_all_unittests.cc
@@ -8,9 +8,13 @@
#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).
+// 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);
diff --git a/mojo/edk/test/multiprocess_test_helper_unittest.cc b/mojo/edk/test/multiprocess_test_helper_unittest.cc
index 2961a74..93496fb 100644
--- a/mojo/edk/test/multiprocess_test_helper_unittest.cc
+++ b/mojo/edk/test/multiprocess_test_helper_unittest.cc
@@ -42,7 +42,13 @@ bool ReadByte(const embedder::PlatformHandle& handle, char* c) {
typedef testing::Test MultiprocessTestHelperTest;
-TEST_F(MultiprocessTestHelperTest, RunChild) {
+#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());
@@ -55,14 +61,26 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) {
return 123;
}
-TEST_F(MultiprocessTestHelperTest, TestChildMainNotFound) {
+#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);
}
-TEST_F(MultiprocessTestHelperTest, PassedChannel) {
+#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");
@@ -109,7 +127,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) {
return static_cast<int>(c);
}
-TEST_F(MultiprocessTestHelperTest, ChildTestPasses) {
+#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");
@@ -122,7 +146,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses) {
IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()));
}
-TEST_F(MultiprocessTestHelperTest, ChildTestFailsAssert) {
+#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");
@@ -138,7 +168,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert) {
CHECK(false) << "Not reached";
}
-TEST_F(MultiprocessTestHelperTest, ChildTestFailsExpect) {
+#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");
diff --git a/mojo/public/VERSION b/mojo/public/VERSION
index 282b862..eca68d9 100644
--- a/mojo/public/VERSION
+++ b/mojo/public/VERSION
@@ -1 +1 @@
-5aa6dbdccf1950daf0cd3014bf763f35899bccf9 \ No newline at end of file
+98d8236f7eea383e5214254c8d045df6c7a6297a \ No newline at end of file
diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h
index 96441dc..9b1eedc 100644
--- a/mojo/public/c/system/types.h
+++ b/mojo/public/c/system/types.h
@@ -149,6 +149,7 @@ const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1);
// |MOJO_RESULT_FAILED_PRECONDITION| if you attempt to wait on this.
// |MOJO_HANDLE_SIGNAL_READABLE| - Can read (e.g., a message) from the handle.
// |MOJO_HANDLE_SIGNAL_WRITABLE| - Can write (e.g., a message) to the handle.
+// |MOJO_HANDLE_SIGNAL_PEER_CLOSED| - The peer handle is closed.
typedef uint32_t MojoHandleSignals;
@@ -156,10 +157,12 @@ typedef uint32_t MojoHandleSignals;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE = 0;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE = 1 << 0;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1;
+const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2;
#else
#define MOJO_HANDLE_SIGNAL_NONE ((MojoHandleSignals)0)
#define MOJO_HANDLE_SIGNAL_READABLE ((MojoHandleSignals)1 << 0)
#define MOJO_HANDLE_SIGNAL_WRITABLE ((MojoHandleSignals)1 << 1)
+#define MOJO_HANDLE_SIGNAL_PEER_CLOSED ((MojoHandleSignals)1 << 2)
#endif
// TODO(vtl): Add out parameters with this to MojoWait/MojoWaitMany.
diff --git a/mojo/public/cpp/application/application_test_base.h b/mojo/public/cpp/application/application_test_base.h
index 2f400a4..04580c7 100644
--- a/mojo/public/cpp/application/application_test_base.h
+++ b/mojo/public/cpp/application/application_test_base.h
@@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_TEST_BASE_H_
#define MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_TEST_BASE_H_
+#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/system/macros.h"
@@ -12,7 +13,6 @@
namespace mojo {
-class ApplicationDelegate;
class ApplicationImpl;
namespace test {
@@ -21,28 +21,35 @@ namespace test {
ScopedMessagePipeHandle PassShellHandle();
void SetShellHandle(ScopedMessagePipeHandle handle);
+// Access the command line arguments passed to the application test.
+const Array<String>& Args();
+void InitializeArgs(int argc, std::vector<const char*> argv);
+
// A GTEST base class for application testing executed in mojo_shell.
class ApplicationTestBase : public testing::Test {
public:
- explicit ApplicationTestBase(Array<String> args);
+ ApplicationTestBase();
~ApplicationTestBase() override;
protected:
ApplicationImpl* application_impl() { return application_impl_; }
// Get the ApplicationDelegate for the application to be tested.
- virtual ApplicationDelegate* GetApplicationDelegate() = 0;
+ virtual ApplicationDelegate* GetApplicationDelegate();
+
+ // A testing::Test::SetUp helper to override the application command
+ // line arguments.
+ void SetUpWithArgs(const Array<String>& args);
// testing::Test:
void SetUp() override;
void TearDown() override;
private:
- // The command line arguments supplied to each test application instance.
- Array<String> args_;
-
// The application implementation instance, reconstructed for each test.
ApplicationImpl* application_impl_;
+ // The application delegate used if GetApplicationDelegate is not overridden.
+ ApplicationDelegate default_application_delegate_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationTestBase);
};
diff --git a/mojo/public/cpp/application/lib/application_test_base.cc b/mojo/public/cpp/application/lib/application_test_base.cc
index 42dbda5..93eb3d0 100644
--- a/mojo/public/cpp/application/lib/application_test_base.cc
+++ b/mojo/public/cpp/application/lib/application_test_base.cc
@@ -7,7 +7,6 @@
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
@@ -17,6 +16,8 @@ namespace {
// This shell handle is shared by multiple test application instances.
MessagePipeHandle g_shell_handle;
+// Share the application command-line arguments with multiple application tests.
+Array<String> g_args;
} // namespace
@@ -33,14 +34,29 @@ void SetShellHandle(ScopedMessagePipeHandle handle) {
g_shell_handle = handle.release();
}
-ApplicationTestBase::ApplicationTestBase(Array<String> args)
- : args_(args.Pass()), application_impl_(nullptr) {
+const Array<String>& Args() {
+ return g_args;
+}
+
+void InitializeArgs(int argc, std::vector<const char*> argv) {
+ MOJO_CHECK(g_args.is_null());
+ for (const char* arg : argv) {
+ if (arg)
+ g_args.push_back(arg);
+ }
+}
+
+ApplicationTestBase::ApplicationTestBase() : application_impl_(nullptr) {
}
ApplicationTestBase::~ApplicationTestBase() {
}
-void ApplicationTestBase::SetUp() {
+ApplicationDelegate* ApplicationTestBase::GetApplicationDelegate() {
+ return &default_application_delegate_;
+}
+
+void ApplicationTestBase::SetUpWithArgs(const Array<String>& args) {
// A run loop is needed for ApplicationImpl initialization and communication.
Environment::InstantiateDefaultRunLoop();
@@ -49,7 +65,11 @@ void ApplicationTestBase::SetUp() {
PassShellHandle());
// Fake application initialization with the given command line arguments.
- application_impl_->Initialize(args_.Clone());
+ application_impl_->Initialize(args.Clone());
+}
+
+void ApplicationTestBase::SetUp() {
+ SetUpWithArgs(Args());
}
void ApplicationTestBase::TearDown() {
diff --git a/mojo/public/cpp/application/lib/application_test_main.cc b/mojo/public/cpp/application/lib/application_test_main.cc
index 6cdfb0d..1c1395c 100644
--- a/mojo/public/cpp/application/lib/application_test_main.cc
+++ b/mojo/public/cpp/application/lib/application_test_main.cc
@@ -21,14 +21,14 @@ MojoResult MojoMain(MojoHandle shell_handle) {
// Construct an ApplicationImpl just for the GTEST commandline arguments.
// GTEST command line arguments are supported amid application arguments:
- // $ mojo_shell 'mojo:example_apptests arg1 --gtest_filter=foo arg2'
+ // $ mojo_shell mojo:example_apptests
+ // --args-for='mojo:example_apptests arg1 --gtest_filter=foo arg2'
mojo::ApplicationDelegate dummy_application_delegate;
mojo::ApplicationImpl app(&dummy_application_delegate, shell_handle);
MOJO_CHECK(app.WaitForInitialize());
// InitGoogleTest expects (argc + 1) elements, including a terminating NULL.
// It also removes GTEST arguments from |argv| and updates the |argc| count.
- // TODO(msw): Provide tests access to these actual command line arguments.
const std::vector<std::string>& args = app.args();
MOJO_CHECK(args.size() <
static_cast<size_t>(std::numeric_limits<int>::max()));
@@ -40,6 +40,7 @@ MojoResult MojoMain(MojoHandle shell_handle) {
testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0])));
mojo::test::SetShellHandle(app.UnbindShell());
+ mojo::test::InitializeArgs(argc, argv);
}
int result = RUN_ALL_TESTS();
diff --git a/mojo/public/dart/src/types.dart b/mojo/public/dart/src/types.dart
index 4353d74..1dc3572 100644
--- a/mojo/public/dart/src/types.dart
+++ b/mojo/public/dart/src/types.dart
@@ -122,6 +122,7 @@ class MojoHandleSignals {
static const int NONE = 0;
static const int READABLE = 1 << 0;
static const int WRITABLE = 1 << 1;
+ static const int PEER_CLOSED = 1 << 2;
static const int READWRITE = READABLE | WRITABLE;
static bool isNone(int mask) => mask == NONE;
diff --git a/mojo/public/go/system/impl/mojo_types.go b/mojo/public/go/system/impl/mojo_types.go
index 01d518e..bd82898 100644
--- a/mojo/public/go/system/impl/mojo_types.go
+++ b/mojo/public/go/system/impl/mojo_types.go
@@ -57,6 +57,7 @@ const (
MOJO_HANDLE_SIGNAL_NONE MojoHandleSignals = 0
MOJO_HANDLE_SIGNAL_READABLE = 1 << 0
MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2
MOJO_WRITE_MESSAGE_FLAG_NONE MojoWriteMessageFlags = 0
MOJO_READ_MESSAGE_FLAG_NONE MojoReadMessageFlags = 0
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index e56f9b5..70aa60e 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -11,6 +11,7 @@ mojom("test_interfaces") {
"no_module.mojom",
"rect.mojom",
"regression_tests.mojom",
+ "regression_tests_import.mojom",
"sample_factory.mojom",
"sample_import.mojom",
"sample_import2.mojom",
diff --git a/mojo/public/interfaces/bindings/tests/regression_tests.mojom b/mojo/public/interfaces/bindings/tests/regression_tests.mojom
index 313f1f4..4a85b0a 100644
--- a/mojo/public/interfaces/bindings/tests/regression_tests.mojom
+++ b/mojo/public/interfaces/bindings/tests/regression_tests.mojom
@@ -7,6 +7,8 @@
[JavaPackage="org.chromium.mojo.bindings.test.mojom.regression_tests"]
module regression_tests;
+import "regression_tests_import.mojom";
+
interface CheckMethodWithEmptyResponse {
WithouParameterAndEmptyResponse() => ();
WithParameterAndEmptyResponse(bool b) => ();
@@ -52,3 +54,7 @@ struct A {
struct B {
A? a;
};
+
+[Client=InterfaceWithClientImportedClient]
+interface InterfaceWithClientImported {
+};
diff --git a/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom b/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom
new file mode 100644
index 0000000..fbed983
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom
@@ -0,0 +1,11 @@
+// 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.
+
+// Module containing entities for regression tests of the generator. Entities
+// must never be modified, instead new entity must be added to add new tests.
+[JavaPackage="org.chromium.mojo.bindings.test.mojom.regression_tests_import"]
+module regression_tests_import;
+
+interface InterfaceWithClientImportedClient {
+};
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/Core.java b/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
index d6c8e7d..caf619a 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
@@ -33,6 +33,7 @@ public interface Core {
private static final int FLAG_NONE = 0;
private static final int FLAG_READABLE = 1 << 0;
private static final int FLAG_WRITABLE = 1 << 1;
+ private static final int FLAG_PEER_CLOSED = 1 << 2;
/**
* Immutable signals.
@@ -64,6 +65,16 @@ public interface Core {
}
/**
+ * Change the peer closed bit of this signal.
+ *
+ * @param peerClosed the new value of the peer closed bit.
+ * @return this.
+ */
+ public HandleSignals setPeerClosed(boolean peerClosed) {
+ return setFlag(FLAG_PEER_CLOSED, peerClosed);
+ }
+
+ /**
* @return a signal with no bit set.
*/
public static HandleSignals none() {
diff --git a/mojo/public/js/core.js b/mojo/public/js/core.js
index 9dcb20f..4a67567 100644
--- a/mojo/public/js/core.js
+++ b/mojo/public/js/core.js
@@ -55,6 +55,7 @@ var DEADLINE_INDEFINITE;
var HANDLE_SIGNAL_NONE;
var HANDLE_SIGNAL_READABLE;
var HANDLE_SIGNAL_WRITABLE;
+var HANDLE_SIGNAL_PEER_CLOSED;
/**
* MojoCreateDataMessageOptions: Used to specify creation parameters for a data
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni
index 83b96a2..05ec369 100644
--- a/mojo/public/mojo_application.gni
+++ b/mojo/public/mojo_application.gni
@@ -125,3 +125,62 @@ template("mojo_native_application") {
outputs = [ "${root_out_dir}/${output}" ]
}
}
+
+if (is_android) {
+ # Declares an Android Mojo application consisting of an .so file and a
+ # corresponding .dex.jar file.
+ #
+ # Variables:
+ # input_so: the .so file to bundle
+ # input_dex_jar: the .dex.jar file to bundle
+ # output_name (optional): override for the output file name
+ template("mojo_android_application") {
+ assert(defined(invoker.input_so))
+ assert(defined(invoker.input_dex_jar))
+
+ zip_action_name = "${target_name}_zip"
+ zip_action_output = "$target_gen_dir/${target_name}.zip"
+ action(zip_action_name) {
+ script = "//build/android/gn/zip.py"
+
+ inputs = [
+ invoker.input_so,
+ invoker.input_dex_jar,
+ ]
+
+ output = zip_action_output
+ outputs = [ output ]
+
+ rebase_inputs = rebase_path(inputs, root_build_dir)
+ rebase_output = rebase_path(output, root_build_dir)
+ args = [
+ "--inputs=$rebase_inputs",
+ "--output=$rebase_output",
+ ]
+ }
+
+ if (defined(invoker.output_name)) {
+ mojo_output = "$target_out_dir/" + invoker.output_name + ".mojo"
+ } else {
+ mojo_output = "$target_out_dir/" + target_name + ".mojo"
+ }
+
+ action(target_name) {
+ script = "//mojo/public/tools/prepend.py"
+
+ input = zip_action_output
+ inputs = [ input ]
+
+ output = mojo_output
+ outputs = [ output ]
+
+ rebase_input = rebase_path(input, root_build_dir)
+ rebase_output = rebase_path(output, root_build_dir)
+ args = [
+ "--input=$rebase_input",
+ "--output=$rebase_output",
+ "--line=#!mojo:android_handler",
+ ]
+ }
+ }
+}
diff --git a/mojo/public/mojo_public.gyp b/mojo/public/mojo_public.gyp
index f19e263..83e27d8 100644
--- a/mojo/public/mojo_public.gyp
+++ b/mojo/public/mojo_public.gyp
@@ -237,11 +237,9 @@
],
'dependencies': [
'mojo_application_bindings',
- 'mojo_application_bindings_mojom',
],
'export_dependent_settings': [
'mojo_application_bindings',
- 'mojo_application_bindings_mojom',
],
},
{
@@ -331,6 +329,7 @@
'interfaces/bindings/tests/no_module.mojom',
'interfaces/bindings/tests/rect.mojom',
'interfaces/bindings/tests/regression_tests.mojom',
+ 'interfaces/bindings/tests/regression_tests_import.mojom',
'interfaces/bindings/tests/sample_factory.mojom',
'interfaces/bindings/tests/sample_import.mojom',
'interfaces/bindings/tests/sample_import2.mojom',
diff --git a/mojo/public/python/mojo/bindings/descriptor.py b/mojo/public/python/mojo/bindings/descriptor.py
index f190d2b..0df0bd6 100644
--- a/mojo/public/python/mojo/bindings/descriptor.py
+++ b/mojo/public/python/mojo/bindings/descriptor.py
@@ -72,7 +72,7 @@ class SerializableType(Type):
"""
raise NotImplementedError()
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
"""
Deserialize a value of this type.
@@ -106,7 +106,7 @@ class NumericType(SerializableType):
def Serialize(self, value, data_offset, data, handle_offset):
return (value, [])
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
return value
@@ -161,21 +161,31 @@ class PointerType(SerializableType):
return (0, [])
return self.SerializePointer(value, data_offset, data, handle_offset)
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
if value == 0:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return None
- pointed_data = buffer(data, value)
- (size, nb_elements) = serialization.HEADER_STRUCT.unpack_from(pointed_data)
- return self.DeserializePointer(size, nb_elements, pointed_data, handles)
+ if value % 8 != 0:
+ raise serialization.DeserializationException(
+ 'Pointer alignment is incorrect.')
+ sub_context = context.GetSubContext(value)
+ if len(sub_context.data) < serialization.HEADER_STRUCT.size:
+ raise serialization.DeserializationException(
+ 'Available data too short to contain header.')
+ (size, nb_elements) = serialization.HEADER_STRUCT.unpack_from(
+ sub_context.data)
+ if len(sub_context.data) < size or size < serialization.HEADER_STRUCT.size:
+ raise serialization.DeserializationException('Header size is incorrect.')
+ sub_context.ClaimMemory(0, size)
+ return self.DeserializePointer(size, nb_elements, sub_context)
def SerializePointer(self, value, data_offset, data, handle_offset):
"""Serialize the not null value."""
raise NotImplementedError()
- def DeserializePointer(self, size, nb_elements, data, handles):
+ def DeserializePointer(self, size, nb_elements, context):
raise NotImplementedError()
@@ -204,9 +214,8 @@ class StringType(PointerType):
return self._array_type.SerializeArray(
string_array, data_offset, data, handle_offset)
- def DeserializePointer(self, size, nb_elements, data, handles):
- string_array = self._array_type.DeserializeArray(
- size, nb_elements, data, handles)
+ def DeserializePointer(self, size, nb_elements, context):
+ string_array = self._array_type.DeserializeArray(size, nb_elements, context)
return unicode(string_array.tostring(), 'utf8')
@@ -226,14 +235,13 @@ class BaseHandleType(SerializableType):
return (-1, [])
return (handle_offset, [handle])
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
if value == -1:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return self.FromHandle(mojo.system.Handle())
- # TODO(qsr) validate handle order
- return self.FromHandle(handles[value])
+ return self.FromHandle(context.ClaimHandle(value))
def FromHandle(self, handle):
raise NotImplementedError()
@@ -326,12 +334,18 @@ class BaseArrayType(PointerType):
"""Serialize the not null array."""
raise NotImplementedError()
- def DeserializePointer(self, size, nb_elements, data, handles):
- if self.length != 0 and size != self.length:
+ def DeserializePointer(self, size, nb_elements, context):
+ if self.length != 0 and nb_elements != self.length:
raise serialization.DeserializationException('Incorrect array size')
- return self.DeserializeArray(size, nb_elements, data, handles)
+ if (size <
+ serialization.HEADER_STRUCT.size + self.SizeForLength(nb_elements)):
+ raise serialization.DeserializationException('Incorrect array size')
+ return self.DeserializeArray(size, nb_elements, context)
+
+ def DeserializeArray(self, size, nb_elements, context):
+ raise NotImplementedError()
- def DeserializeArray(self, size, nb_elements, data, handles):
+ def SizeForLength(self, nb_elements):
raise NotImplementedError()
@@ -351,9 +365,8 @@ class BooleanArrayType(BaseArrayType):
converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups])
return _SerializeNativeArray(converted, data_offset, data, len(value))
- def DeserializeArray(self, size, nb_elements, data, handles):
- converted = self._array_type.DeserializeArray(
- size, nb_elements, data, handles)
+ def DeserializeArray(self, size, nb_elements, context):
+ converted = self._array_type.DeserializeArray(size, nb_elements, context)
elements = list(itertools.islice(
itertools.chain.from_iterable(
[_ConvertByteToBooleans(x, 8) for x in converted]),
@@ -361,6 +374,9 @@ class BooleanArrayType(BaseArrayType):
nb_elements))
return elements
+ def SizeForLength(self, nb_elements):
+ return (nb_elements + 7) // 8
+
class GenericArrayType(BaseArrayType):
"""Type object for arrays of pointers."""
@@ -400,18 +416,22 @@ class GenericArrayType(BaseArrayType):
*to_pack)
return (data_offset, returned_handles)
- def DeserializeArray(self, size, nb_elements, data, handles):
+ def DeserializeArray(self, size, nb_elements, context):
values = struct.unpack_from(
'%d%s' % (nb_elements, self.sub_type.GetTypeCode()),
- buffer(data, serialization.HEADER_STRUCT.size))
+ buffer(context.data, serialization.HEADER_STRUCT.size))
result = []
- position = serialization.HEADER_STRUCT.size
+ sub_context = context.GetSubContext(serialization.HEADER_STRUCT.size)
for value in values:
- result.append(
- self.sub_type.Deserialize(value, buffer(data, position), handles))
- position += self.sub_type.GetByteSize()
+ result.append(self.sub_type.Deserialize(
+ value,
+ sub_context))
+ sub_context = sub_context.GetSubContext(self.sub_type.GetByteSize())
return result
+ def SizeForLength(self, nb_elements):
+ return nb_elements * self.sub_type.GetByteSize();
+
class NativeArrayType(BaseArrayType):
"""Type object for arrays of native types."""
@@ -419,6 +439,7 @@ class NativeArrayType(BaseArrayType):
def __init__(self, typecode, nullable=False, length=0):
BaseArrayType.__init__(self, nullable, length)
self.array_typecode = typecode
+ self.element_size = struct.calcsize('<%s' % self.array_typecode)
def Convert(self, value):
if value is None:
@@ -431,13 +452,16 @@ class NativeArrayType(BaseArrayType):
def SerializeArray(self, value, data_offset, data, handle_offset):
return _SerializeNativeArray(value, data_offset, data, len(value))
- def DeserializeArray(self, size, nb_elements, data, handles):
+ def DeserializeArray(self, size, nb_elements, context):
result = array.array(self.array_typecode)
- result.fromstring(buffer(data,
+ result.fromstring(buffer(context.data,
serialization.HEADER_STRUCT.size,
size - serialization.HEADER_STRUCT.size))
return result
+ def SizeForLength(self, nb_elements):
+ return nb_elements * self.element_size
+
class StructType(PointerType):
"""Type object for structs."""
@@ -469,8 +493,8 @@ class StructType(PointerType):
data.extend(new_data)
return (data_offset, new_handles)
- def DeserializePointer(self, size, nb_elements, data, handles):
- return self.struct_type.Deserialize(data, handles)
+ def DeserializePointer(self, size, nb_elements, context):
+ return self.struct_type.Deserialize(context)
class MapType(SerializableType):
@@ -511,8 +535,8 @@ class MapType(SerializableType):
s = self.struct(keys=keys, values=values)
return self.struct_type.Serialize(s, data_offset, data, handle_offset)
- def Deserialize(self, value, data, handles):
- s = self.struct_type.Deserialize(value, data, handles)
+ def Deserialize(self, value, context):
+ s = self.struct_type.Deserialize(value, context)
if s:
if len(s.keys) != len(s.values):
raise serialization.DeserializationException(
@@ -590,7 +614,7 @@ class FieldGroup(object):
def Serialize(self, obj, data_offset, data, handle_offset):
raise NotImplementedError()
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
raise NotImplementedError()
@@ -615,8 +639,8 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor):
value = getattr(obj, self.name)
return self.field_type.Serialize(value, data_offset, data, handle_offset)
- def Deserialize(self, value, data, handles):
- entity = self.field_type.Deserialize(value, data, handles)
+ def Deserialize(self, value, context):
+ entity = self.field_type.Deserialize(value, context)
return { self.name: entity }
@@ -640,7 +664,7 @@ class BooleanGroup(FieldGroup):
[getattr(obj, field.name) for field in self.GetDescriptors()])
return (value, [])
- def Deserialize(self, value, data, handles):
+ def Deserialize(self, value, context):
values = itertools.izip_longest([x.name for x in self.descriptors],
_ConvertByteToBooleans(value),
fillvalue=False)
@@ -663,7 +687,7 @@ def _ConvertBooleansToByte(booleans):
def _ConvertByteToBooleans(value, min_size=0):
- "Unpack an integer into a list of booleans."""
+ """Unpack an integer into a list of booleans."""
res = []
while value:
res.append(bool(value&1))
diff --git a/mojo/public/python/mojo/bindings/reflection.py b/mojo/public/python/mojo/bindings/reflection.py
index 5ca38bf..9668c2a3 100644
--- a/mojo/public/python/mojo/bindings/reflection.py
+++ b/mojo/public/python/mojo/bindings/reflection.py
@@ -117,10 +117,10 @@ class MojoStructType(type):
return self._fields
dictionary['AsDict'] = AsDict
- def Deserialize(cls, data, handles):
+ def Deserialize(cls, context):
result = cls.__new__(cls)
fields = {}
- serialization_object.Deserialize(fields, data, handles)
+ serialization_object.Deserialize(fields, context)
result._fields = fields
return result
dictionary['Deserialize'] = classmethod(Deserialize)
@@ -476,8 +476,9 @@ def _ProxyMethodCall(method):
try:
assert message.header.message_type == method.ordinal
payload = message.payload
- response = method.response_struct.Deserialize(payload.data,
- payload.handles)
+ response = method.response_struct.Deserialize(
+ serialization.RootDeserializationContext(payload.data,
+ payload.handles))
as_dict = response.AsDict()
if len(as_dict) == 1:
value = as_dict.values()[0]
@@ -533,7 +534,8 @@ def _StubAccept(methods):
method = methods_by_ordinal[header.message_type]
payload = message.payload
parameters = method.parameters_struct.Deserialize(
- payload.data, payload.handles).AsDict()
+ serialization.RootDeserializationContext(
+ payload.data, payload.handles)).AsDict()
response = getattr(self.impl, method.name)(**parameters)
if header.expects_response:
def SendResponse(response):
diff --git a/mojo/public/python/mojo/bindings/serialization.py b/mojo/public/python/mojo/bindings/serialization.py
index 2c0478f..b5ea1bd 100644
--- a/mojo/public/python/mojo/bindings/serialization.py
+++ b/mojo/public/python/mojo/bindings/serialization.py
@@ -21,6 +21,68 @@ class DeserializationException(Exception):
pass
+class DeserializationContext(object):
+
+ def ClaimHandle(self, handle):
+ raise NotImplementedError()
+
+ def ClaimMemory(self, start, size):
+ raise NotImplementedError()
+
+ def GetSubContext(self, offset):
+ raise NotImplementedError()
+
+ def IsInitialContext(self):
+ raise NotImplementedError()
+
+
+class RootDeserializationContext(DeserializationContext):
+ def __init__(self, data, handles):
+ if isinstance(data, buffer):
+ self.data = data
+ else:
+ self.data = buffer(data)
+ self._handles = handles
+ self._next_handle = 0;
+ self._next_memory = 0;
+
+ def ClaimHandle(self, handle):
+ if handle < self._next_handle:
+ raise DeserializationException('Accessing handles out of order.')
+ self._next_handle = handle + 1
+ return self._handles[handle]
+
+ def ClaimMemory(self, start, size):
+ if start < self._next_memory:
+ raise DeserializationException('Accessing buffer out of order.')
+ self._next_memory = start + size
+
+ def GetSubContext(self, offset):
+ return _ChildDeserializationContext(self, offset)
+
+ def IsInitialContext(self):
+ return True
+
+
+class _ChildDeserializationContext(DeserializationContext):
+ def __init__(self, parent, offset):
+ self._parent = parent
+ self._offset = offset
+ self.data = buffer(parent.data, offset)
+
+ def ClaimHandle(self, handle):
+ return self._parent.ClaimHandle(handle)
+
+ def ClaimMemory(self, start, size):
+ return self._parent.ClaimMemory(self._offset + start, size)
+
+ def GetSubContext(self, offset):
+ return self._parent.GetSubContext(self._offset + offset)
+
+ def IsInitialContext(self):
+ return False
+
+
class Serialization(object):
"""
Helper class to serialize/deserialize a struct.
@@ -78,18 +140,23 @@ class Serialization(object):
self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack)
return (data, handles)
- def Deserialize(self, fields, data, handles):
- if not isinstance(data, buffer):
- data = buffer(data)
- (_, version) = HEADER_STRUCT.unpack_from(data)
+ def Deserialize(self, fields, context):
+ if len(context.data) < HEADER_STRUCT.size:
+ raise DeserializationException(
+ 'Available data too short to contain header.')
+ (size, version) = HEADER_STRUCT.unpack_from(context.data)
+ if len(context.data) < size or size < HEADER_STRUCT.size:
+ raise DeserializationException('Header size is incorrect.')
+ if context.IsInitialContext():
+ context.ClaimMemory(0, size)
version_struct = self._GetStruct(version)
- entitities = version_struct.unpack_from(data, HEADER_STRUCT.size)
+ entitities = version_struct.unpack_from(context.data, HEADER_STRUCT.size)
filtered_groups = self._GetGroups(version)
position = HEADER_STRUCT.size
for (group, value) in zip(filtered_groups, entitities):
position = position + NeededPaddingForAlignment(position,
group.GetByteSize())
- fields.update(group.Deserialize(value, buffer(data, position), handles))
+ fields.update(group.Deserialize(value, context.GetSubContext(position)))
position += group.GetByteSize()
diff --git a/mojo/public/python/mojo/c_core.pxd b/mojo/public/python/mojo/c_core.pxd
index 1526dfe..fe10fff 100644
--- a/mojo/public/python/mojo/c_core.pxd
+++ b/mojo/public/python/mojo/c_core.pxd
@@ -56,6 +56,7 @@ cdef extern from "mojo/public/c/system/core.h" nogil:
const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE
const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE
const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE
+ const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED
# functions.h
MojoTimeTicks MojoGetTimeTicksNow()
diff --git a/mojo/public/python/mojo/system.pyx b/mojo/public/python/mojo/system.pyx
index 4507d4d..f0a814a 100644
--- a/mojo/public/python/mojo/system.pyx
+++ b/mojo/public/python/mojo/system.pyx
@@ -53,6 +53,7 @@ DEADLINE_INDEFINITE = c_core.MOJO_DEADLINE_INDEFINITE
HANDLE_SIGNAL_NONE = c_core.MOJO_HANDLE_SIGNAL_NONE
HANDLE_SIGNAL_READABLE = c_core.MOJO_HANDLE_SIGNAL_READABLE
HANDLE_SIGNAL_WRITABLE = c_core.MOJO_HANDLE_SIGNAL_WRITABLE
+HANDLE_SIGNAL_PEER_CLOSED = c_core.MOJO_HANDLE_SIGNAL_PEER_CLOSED
WRITE_MESSAGE_FLAG_NONE = c_core.MOJO_WRITE_MESSAGE_FLAG_NONE
READ_MESSAGE_FLAG_NONE = c_core.MOJO_READ_MESSAGE_FLAG_NONE
READ_MESSAGE_FLAG_MAY_DISCARD = c_core.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD
diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 4bede9a..19f4631 100644
--- a/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -429,9 +429,14 @@ class Generator(generator.Generator):
exports = self.GetJinjaExports()
exports.update({'interface': interface})
if interface.client:
- for client in self.module.interfaces:
- if client.name == interface.client:
- exports.update({'client': client})
+ all_interfaces = [] + self.module.interfaces
+ for each in self.module.imports:
+ all_interfaces += each['module'].interfaces
+ interfaces_by_name = dict((x.name, x) for x in all_interfaces)
+ assert interface.client in interfaces_by_name, (
+ 'Unable to find interface %s declared as client of %s.' %
+ (interface.client, interface.name))
+ exports.update({'client': interfaces_by_name[interface.client]})
return exports
@UseJinja('java_templates/enum.java.tmpl', filters=java_filters)
diff --git a/mojo/public/tools/bindings/generators/mojom_python_generator.py b/mojo/public/tools/bindings/generators/mojom_python_generator.py
index f93da09..33bfdd5 100644
--- a/mojo/public/tools/bindings/generators/mojom_python_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_python_generator.py
@@ -8,6 +8,7 @@ import re
from itertools import ifilter
import mojom.generate.generator as generator
+import mojom.generate.data as data
import mojom.generate.module as mojom
from mojom.generate.template_expander import UseJinja
@@ -318,8 +319,9 @@ class Generator(generator.Generator):
"""
interfaces = self.module.interfaces
all_interfaces = [] + interfaces
- for each in self.module.imports:
- all_interfaces += each['module'].interfaces
+ for each in self.GetImports():
+ all_interfaces += [data.KindFromImport(x, each) for x in
+ each['module'].interfaces];
interfaces_by_name = dict((x.name, x) for x in all_interfaces)
for interface in interfaces:
if interface.client:
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py
index 7dc9067..cb3b1d1 100755
--- a/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -93,36 +93,19 @@ class MojomProcessor(object):
def __init__(self, should_generate):
self._should_generate = should_generate
self._processed_files = {}
+ self._parsed_files = {}
- def ProcessFile(self, args, remaining_args, generator_modules, filename,
- _imported_filename_stack=None):
- # Memoized results.
- if filename in self._processed_files:
- return self._processed_files[filename]
-
- if _imported_filename_stack is None:
- _imported_filename_stack = []
-
- # Ensure we only visit each file once.
- if filename in _imported_filename_stack:
- print "%s: Error: Circular dependency" % filename + \
- MakeImportStackMessage(_imported_filename_stack + [filename])
- sys.exit(1)
+ def ProcessFile(self, args, remaining_args, generator_modules, filename):
+ self._ParseFileAndImports(filename, args.import_directories, [])
- try:
- with open(filename) as f:
- source = f.read()
- except IOError as e:
- print "%s: Error: %s" % (e.filename, e.strerror) + \
- MakeImportStackMessage(_imported_filename_stack + [filename])
- sys.exit(1)
+ return self._GenerateModule(args, remaining_args, generator_modules,
+ filename)
- try:
- tree = Parse(source, filename)
- except Error as e:
- full_stack = _imported_filename_stack + [filename]
- print str(e) + MakeImportStackMessage(full_stack)
- sys.exit(1)
+ def _GenerateModule(self, args, remaining_args, generator_modules, filename):
+ # Return the already-generated module.
+ if filename in self._processed_files:
+ return self._processed_files[filename]
+ tree = self._parsed_files[filename]
dirname, name = os.path.split(filename)
mojom = Translate(tree, name)
@@ -135,9 +118,8 @@ class MojomProcessor(object):
import_filename = FindImportFile(dirname,
import_data['filename'],
args.import_directories)
- import_data['module'] = self.ProcessFile(
- args, remaining_args, generator_modules, import_filename,
- _imported_filename_stack=_imported_filename_stack + [filename])
+ import_data['module'] = self._GenerateModule(
+ args, remaining_args, generator_modules, import_filename)
module = OrderedModuleFromData(mojom)
@@ -162,6 +144,42 @@ class MojomProcessor(object):
self._processed_files[filename] = module
return module
+ def _ParseFileAndImports(self, filename, import_directories,
+ imported_filename_stack):
+ # Ignore already-parsed files.
+ if filename in self._parsed_files:
+ return
+
+ if filename in imported_filename_stack:
+ print "%s: Error: Circular dependency" % filename + \
+ MakeImportStackMessage(imported_filename_stack + [filename])
+ sys.exit(1)
+
+ try:
+ with open(filename) as f:
+ source = f.read()
+ except IOError as e:
+ print "%s: Error: %s" % (e.filename, e.strerror) + \
+ MakeImportStackMessage(imported_filename_stack + [filename])
+ sys.exit(1)
+
+ try:
+ tree = Parse(source, filename)
+ except Error as e:
+ full_stack = imported_filename_stack + [filename]
+ print str(e) + MakeImportStackMessage(full_stack)
+ sys.exit(1)
+
+ dirname = os.path.split(filename)[0]
+ for imp_entry in tree.import_list:
+ import_filename = FindImportFile(dirname,
+ imp_entry.import_filename, import_directories)
+ self._ParseFileAndImports(import_filename, import_directories,
+ imported_filename_stack + [filename])
+
+ self._parsed_files[filename] = tree
+
+
def main():
parser = argparse.ArgumentParser(
description="Generate bindings from mojom files.")
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi b/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi
index 68348fb..512e22f 100644
--- a/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi
+++ b/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi
@@ -13,6 +13,10 @@
'<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_list_outputs.py --basedir <(mojom_base_output_dir) <@(mojom_files))',
],
},
+ # Given mojom files as inputs, generate sources. These sources will be
+ # exported to another target (via dependent_settings) to be compiled. This
+ # keeps code generation separate from compilation, allowing the same sources
+ # to be compiled with multiple toolchains - target, NaCl, etc.
'actions': [
{
'action_name': '<(_target_name)_mojom_bindings_generator',
@@ -39,10 +43,11 @@
'--java_output_directory=<(java_out_dir)',
],
'message': 'Generating Mojo bindings from <@(mojom_files)',
- 'process_outputs_as_sources': 1,
}
],
'direct_dependent_settings': {
+ # A target directly depending on this action will compile the generated
+ # sources.
'sources': [
'<@(mojom_generated_outputs)',
],
@@ -51,6 +56,9 @@
'<(DEPTH)',
'<(SHARED_INTERMEDIATE_DIR)',
],
+ # Make sure the generated header files are available for any static library
+ # that depends on a static library that depends on this generator.
+ 'hard_dependency': 1,
'direct_dependent_settings': {
# Include paths needed to find the generated header files and their
# transitive dependancies when using the library.
@@ -59,11 +67,10 @@
'<(SHARED_INTERMEDIATE_DIR)',
],
'variables': {
- 'generated_src_dirs': [
- '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- ],
+ 'generated_src_dirs': [
+ '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
+ ],
},
}
},
- 'hard_dependency': 1,
}
diff --git a/mojo/public/tools/prepend.py b/mojo/public/tools/prepend.py
new file mode 100755
index 0000000..de70a82
--- /dev/null
+++ b/mojo/public/tools/prepend.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Prepends a given file with a given line. This can be used to add a shebang line
+to a generated file.
+"""
+
+import optparse
+import os
+import shutil
+import sys
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('--input', help='The file to prepend the line to.')
+ parser.add_option('--line', help='The line to be prepended.')
+ parser.add_option('--output', help='The output file.')
+
+ options, _ = parser.parse_args()
+ input_path = options.input
+ output_path = options.output
+ line = options.line
+
+ # Warning - this reads all of the input file into memory.
+ with open(output_path, 'w') as output_file:
+ output_file.write(line + '\n')
+ with open(input_path, 'r') as input_file:
+ shutil.copyfileobj(input_file, output_file)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/mojo/services/public/cpp/geometry/BUILD.gn b/mojo/services/public/cpp/geometry/BUILD.gn
index 1556d06..bf2b577 100644
--- a/mojo/services/public/cpp/geometry/BUILD.gn
+++ b/mojo/services/public/cpp/geometry/BUILD.gn
@@ -6,4 +6,6 @@ source_set("geometry") {
sources = [
"geometry_util.h",
]
+
+ deps = [ "//mojo/services/public/interfaces/geometry" ]
}
diff --git a/mojo/services/public/cpp/network/BUILD.gn b/mojo/services/public/cpp/network/BUILD.gn
index 045c0b7..f8db162 100644
--- a/mojo/services/public/cpp/network/BUILD.gn
+++ b/mojo/services/public/cpp/network/BUILD.gn
@@ -3,15 +3,6 @@
# found in the LICENSE file.
source_set("network") {
- deps = [
- "//base",
- "//mojo/application",
- "//mojo/common",
- "//mojo/environment:chromium",
- "//mojo/public/c/system:for_component",
- "//mojo/services/public/interfaces/network",
- ]
-
sources = [
"udp_socket_wrapper.cc",
"udp_socket_wrapper.h",
@@ -20,4 +11,14 @@ source_set("network") {
"web_socket_write_queue.cc",
"web_socket_write_queue.h",
]
+
+ deps = [
+ "//base",
+ "//mojo/application",
+ "//mojo/common",
+ "//mojo/environment:chromium",
+ "//mojo/public/c/system:for_component",
+ "//mojo/public/cpp/system",
+ "//mojo/services/public/interfaces/network",
+ ]
}
diff --git a/mojo/services/public/interfaces/gpu/BUILD.gn b/mojo/services/public/interfaces/gpu/BUILD.gn
index efb72a5..8fe2f9c 100644
--- a/mojo/services/public/interfaces/gpu/BUILD.gn
+++ b/mojo/services/public/interfaces/gpu/BUILD.gn
@@ -9,6 +9,7 @@ mojom("gpu") {
"command_buffer.mojom",
"gpu.mojom",
"gpu_capabilities.mojom",
+ "viewport_parameter_listener.mojom",
]
deps = [
diff --git a/mojo/services/public/interfaces/gpu/gpu.mojom b/mojo/services/public/interfaces/gpu/gpu.mojom
index c3d473d..a765c1c 100644
--- a/mojo/services/public/interfaces/gpu/gpu.mojom
+++ b/mojo/services/public/interfaces/gpu/gpu.mojom
@@ -6,8 +6,12 @@ module mojo;
import "mojo/services/public/interfaces/geometry/geometry.mojom";
import "mojo/services/public/interfaces/gpu/command_buffer.mojom";
+import "mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom";
interface Gpu {
- CreateOnscreenGLES2Context(uint64 native_viewport_id, Size? size, CommandBuffer&? gles2_client);
+ CreateOnscreenGLES2Context(uint64 native_viewport_id,
+ Size? size,
+ CommandBuffer&? gles2_client,
+ ViewportParameterListener? listener);
CreateOffscreenGLES2Context(CommandBuffer&? gles2_client);
};
diff --git a/mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom b/mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom
new file mode 100644
index 0000000..5afa931
--- /dev/null
+++ b/mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom
@@ -0,0 +1,12 @@
+// 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.
+
+module mojo;
+
+interface ViewportParameterListener {
+ // These parameters describe the refresh rate of the viewport. The viewport
+ // refreshes every |interval| time ticks. The phase of the refresh is
+ // indicated by |timebase|, which is synchronized with MojoGetTimeTicksNow.
+ OnVSyncParametersUpdated(int64 timebase, int64 interval);
+};
diff --git a/mojo/services/public/interfaces/surfaces/surfaces.mojom b/mojo/services/public/interfaces/surfaces/surfaces.mojom
index 21149ab..0df7ea4c 100644
--- a/mojo/services/public/interfaces/surfaces/surfaces.mojom
+++ b/mojo/services/public/interfaces/surfaces/surfaces.mojom
@@ -6,6 +6,7 @@ module mojo;
import "mojo/services/public/interfaces/geometry/geometry.mojom";
import "mojo/services/public/interfaces/gpu/command_buffer.mojom";
+import "mojo/services/public/interfaces/gpu/viewport_parameter_listener.mojom";
import "mojo/services/public/interfaces/surfaces/quads.mojom";
import "mojo/services/public/interfaces/surfaces/surface_id.mojom";
@@ -61,11 +62,15 @@ interface Surface {
// connection's namespace in the upper 32 bits.
CreateSurface(SurfaceId id, Size size);
- // The client can only submit frames to surfaces created with this connection.
- SubmitFrame(SurfaceId id, Frame frame);
+ // The client can only submit frames to surfaces created with this
+ // connection. After the submitted frame is drawn for the first time, the
+ // surface will respond to the SubmitFrame message. Clients should use this
+ // acknowledgement to ratelimit frame submissions.
+ SubmitFrame(SurfaceId id, Frame frame) => ();
DestroySurface(SurfaceId id);
CreateGLES2BoundSurface(CommandBuffer gles2_client,
SurfaceId id,
- Size size);
+ Size size,
+ ViewportParameterListener& listener);
};
diff --git a/mojo/services/public/mojo_services_public.gyp b/mojo/services/public/mojo_services_public.gyp
index 701d7e5..aab34f97 100644
--- a/mojo/services/public/mojo_services_public.gyp
+++ b/mojo/services/public/mojo_services_public.gyp
@@ -83,6 +83,7 @@
'interfaces/gpu/command_buffer.mojom',
'interfaces/gpu/gpu.mojom',
'interfaces/gpu/gpu_capabilities.mojom',
+ 'interfaces/gpu/viewport_parameter_listener.mojom',
],
'includes': [ '../../public/tools/bindings/mojom_bindings_generator.gypi' ],
'dependencies': [