diff options
author | rockot <rockot@chromium.org> | 2015-06-02 14:47:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-02 21:48:19 +0000 |
commit | ed24ea1ba4ef7fbc0d1a207d2f63b8512cf3b639 (patch) | |
tree | 33648733e9b6e61b7d137ccf4eb58c02597fbbf2 | |
parent | d601ddc554ca0e22fe7b91b93395a421e329ef83 (diff) | |
download | chromium_src-ed24ea1ba4ef7fbc0d1a207d2f63b8512cf3b639.zip chromium_src-ed24ea1ba4ef7fbc0d1a207d2f63b8512cf3b639.tar.gz chromium_src-ed24ea1ba4ef7fbc0d1a207d2f63b8512cf3b639.tar.bz2 |
Update mojo sdk to rev c2ace8a3e256e2f78e2ec1f7e1001ef47e2f5983
BUG=None
TBR=jam@chromium.org
Review URL: https://codereview.chromium.org/1143253010
Cr-Commit-Position: refs/heads/master@{#332468}
99 files changed, 1550 insertions, 504 deletions
diff --git a/mojo/tools/rev_sdk.py b/mojo/tools/rev_sdk.py index 06241ee..0ca317fb 100755 --- a/mojo/tools/rev_sdk.py +++ b/mojo/tools/rev_sdk.py @@ -23,6 +23,7 @@ sdk_dirs_to_clone = [ sdk_dirs_to_not_clone = [ "mojo/public/cpp/application", "mojo/public/interfaces/application", + "mojo/public/interfaces/network", "mojo/public/java/application", ] diff --git a/third_party/mojo/mojo_edk_system_impl.gypi b/third_party/mojo/mojo_edk_system_impl.gypi index 53e904b..069a53f 100644 --- a/third_party/mojo/mojo_edk_system_impl.gypi +++ b/third_party/mojo/mojo_edk_system_impl.gypi @@ -58,6 +58,7 @@ 'src/mojo/edk/system/channel_manager.h', 'src/mojo/edk/system/configuration.cc', 'src/mojo/edk/system/configuration.h', + 'src/mojo/edk/system/connection_identifier.h', 'src/mojo/edk/system/connection_manager.cc', 'src/mojo/edk/system/connection_manager.h', 'src/mojo/edk/system/core.cc', diff --git a/third_party/mojo/mojo_edk_tests.gyp b/third_party/mojo/mojo_edk_tests.gyp index dc552e2..613d847 100644 --- a/third_party/mojo/mojo_edk_tests.gyp +++ b/third_party/mojo/mojo_edk_tests.gyp @@ -153,7 +153,10 @@ 'src/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc', 'src/mojo/edk/system/awakable_list_unittest.cc', 'src/mojo/edk/system/channel_endpoint_id_unittest.cc', + 'src/mojo/edk/system/channel_endpoint_unittest.cc', 'src/mojo/edk/system/channel_manager_unittest.cc', + 'src/mojo/edk/system/channel_test_base.cc', + 'src/mojo/edk/system/channel_test_base.h', 'src/mojo/edk/system/channel_unittest.cc', 'src/mojo/edk/system/core_unittest.cc', 'src/mojo/edk/system/core_test_base.cc', @@ -161,7 +164,11 @@ 'src/mojo/edk/system/data_pipe_impl_unittest.cc', 'src/mojo/edk/system/data_pipe_unittest.cc', 'src/mojo/edk/system/dispatcher_unittest.cc', + 'src/mojo/edk/system/endpoint_relayer_unittest.cc', 'src/mojo/edk/system/memory_unittest.cc', + 'src/mojo/edk/system/message_in_transit_queue_unittest.cc', + 'src/mojo/edk/system/message_in_transit_test_utils.cc', + 'src/mojo/edk/system/message_in_transit_test_utils.h', 'src/mojo/edk/system/message_pipe_dispatcher_unittest.cc', 'src/mojo/edk/system/message_pipe_test_utils.cc', 'src/mojo/edk/system/message_pipe_test_utils.h', @@ -175,6 +182,8 @@ 'src/mojo/edk/system/run_all_unittests.cc', 'src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc', 'src/mojo/edk/system/simple_dispatcher_unittest.cc', + 'src/mojo/edk/system/test_channel_endpoint_client.cc', + 'src/mojo/edk/system/test_channel_endpoint_client.h', 'src/mojo/edk/system/test_utils.cc', 'src/mojo/edk/system/test_utils.h', 'src/mojo/edk/system/unique_identifier_unittest.cc', diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc index 29c5217..e6c2720 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc +++ b/third_party/mojo/src/mojo/edk/embedder/embedder.cc @@ -148,7 +148,7 @@ MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; - if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle) + if (dispatcher->GetType() != system::Dispatcher::Type::PLATFORM_HANDLE) return MOJO_RESULT_INVALID_ARGUMENT; *platform_handle = diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h index 50ec184..2e43475 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.h +++ b/third_party/mojo/src/mojo/edk/embedder/embedder.h @@ -23,7 +23,7 @@ namespace embedder { struct Configuration; class PlatformSupport; class ProcessDelegate; -typedef void* SlaveInfo; +using SlaveInfo = void*; // Basic configuration/initialization ------------------------------------------ @@ -191,7 +191,7 @@ MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle CreateChannelOnIOThread(ScopedPlatformHandle platform_handle, ChannelInfo** channel_info); -typedef base::Callback<void(ChannelInfo*)> DidCreateChannelCallback; +using DidCreateChannelCallback = base::Callback<void(ChannelInfo*)>; // Creates a channel asynchronously; may be called from any thread. // |platform_handle| should be a handle to a connected OS "pipe". // |io_thread_task_runner| should be the |TaskRunner| for the I/O thread. @@ -214,7 +214,7 @@ CreateChannel(ScopedPlatformHandle platform_handle, MOJO_SYSTEM_IMPL_EXPORT void DestroyChannelOnIOThread( ChannelInfo* channel_info); -typedef base::Closure DidDestroyChannelCallback; +using DidDestroyChannelCallback = base::Closure; // Like |DestroyChannelOnIOThread()|, but asynchronous and may be called from // any thread. The callback will be called using |callback_thread_task_runner| // if that is non-null, or otherwise it will be called on the "channel thread". diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h index 833e66b..752d366 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h +++ b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h @@ -24,8 +24,8 @@ namespace system { class ChannelManager; class Core; -// Repeat a typedef in mojo/edk/system/channel_manager.h, to avoid including it. -typedef uint64_t ChannelId; +// Duplicate from mojo/edk/system/channel_manager.h, to avoid including it. +using ChannelId = uint64_t; } // namespace system diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc index 5dc34b1e..e0bcd88 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc +++ b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc @@ -383,7 +383,7 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { EXPECT_TRUE(client_channel.channel_info()); } -#if defined(OS_ANDROID) || defined(OS_WIN) +#if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. // TODO(vtl): I'm guessing this is true of this test too? #define MAYBE_MultiprocessMasterSlave DISABLED_MultiprocessMasterSlave diff --git a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h index bc3c909..22ac435 100644 --- a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h +++ b/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h @@ -13,7 +13,7 @@ namespace mojo { namespace embedder { -typedef void* SlaveInfo; +using SlaveInfo = void*; // An interface for the master process delegate (which lives in the master // process). diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h index d77c100..ff8aabd 100644 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h +++ b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h @@ -22,9 +22,9 @@ namespace embedder { // It would be nice to refactor base/process/launch.h to have a more platform- // independent way of representing handles that are passed to child processes. #if defined(OS_WIN) -typedef base::HandlesToInheritVector HandlePassingInformation; +using HandlePassingInformation = base::HandlesToInheritVector; #elif defined(OS_POSIX) -typedef base::FileHandleMappingVector HandlePassingInformation; +using HandlePassingInformation = base::FileHandleMappingVector; #else #error "Unsupported." #endif diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc index 945ab89..107406e 100644 --- a/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc +++ b/third_party/mojo/src/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc @@ -127,14 +127,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveData) { } } -#if defined(OS_MACOSX) -// http://crbug.com/488258 -#define MAYBE_SendReceiveFDs DISABLED_SendReceiveFDs -#else -#define MAYBE_SendReceiveFDs SendReceiveFDs -#endif - -TEST_F(PlatformChannelPairPosixTest, MAYBE_SendReceiveFDs) { +TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); @@ -144,7 +137,14 @@ TEST_F(PlatformChannelPairPosixTest, MAYBE_SendReceiveFDs) { ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass(); ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass(); - for (size_t i = 1; i < kPlatformChannelMaxNumHandles; i++) { +// Reduce the number of FDs opened on OS X to avoid test flake. +#if defined(OS_MACOSX) + const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles / 2; +#else + const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles; +#endif + + for (size_t i = 1; i < kNumHandlesToSend; i++) { // Make |i| files, with the j-th file consisting of j copies of the digit // |c|. const char c = '0' + (i % 10); @@ -185,7 +185,7 @@ TEST_F(PlatformChannelPairPosixTest, MAYBE_SendReceiveFDs) { received_handles.pop_front(); ASSERT_TRUE(fp); rewind(fp.get()); - char read_buf[kPlatformChannelMaxNumHandles]; + char read_buf[kNumHandlesToSend]; size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get()); EXPECT_EQ(j + 1, bytes_read); EXPECT_EQ(std::string(j + 1, c), std::string(read_buf, bytes_read)); diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h b/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h index 96356b7..771df4f 100644 --- a/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h +++ b/third_party/mojo/src/mojo/edk/embedder/platform_handle_vector.h @@ -15,7 +15,7 @@ namespace mojo { namespace embedder { -typedef std::vector<PlatformHandle> PlatformHandleVector; +using PlatformHandleVector = std::vector<PlatformHandle>; // A deleter (for use with |scoped_ptr|) which closes all handles and then // |delete|s the |PlatformHandleVector|. @@ -26,8 +26,8 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { } }; -typedef scoped_ptr<PlatformHandleVector, PlatformHandleVectorDeleter> - ScopedPlatformHandleVectorPtr; +using ScopedPlatformHandleVectorPtr = + scoped_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>; } // namespace embedder } // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/js/drain_data.h b/third_party/mojo/src/mojo/edk/js/drain_data.h index 48f1de2..3c066dc 100644 --- a/third_party/mojo/src/mojo/edk/js/drain_data.h +++ b/third_party/mojo/src/mojo/edk/js/drain_data.h @@ -48,7 +48,7 @@ class DrainData { // all of the buffered data to the JS Promise and then delete this. void DeliverData(MojoResult result); - typedef std::vector<char> DataBuffer; + using DataBuffer = std::vector<char>; v8::Isolate* isolate_; ScopedDataPipeConsumerHandle handle_; diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn index f5e486f..bf42e40 100644 --- a/third_party/mojo/src/mojo/edk/system/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/system/BUILD.gn @@ -39,6 +39,7 @@ component("system") { "channel_manager.h", "configuration.cc", "configuration.h", + "connection_identifier.h", "connection_manager.cc", "connection_manager.h", "core.cc", @@ -158,7 +159,10 @@ test("mojo_system_unittests") { "../test/multiprocess_test_helper_unittest.cc", "awakable_list_unittest.cc", "channel_endpoint_id_unittest.cc", + "channel_endpoint_unittest.cc", "channel_manager_unittest.cc", + "channel_test_base.cc", + "channel_test_base.h", "channel_unittest.cc", "connection_manager_unittest.cc", "core_test_base.cc", @@ -167,7 +171,11 @@ test("mojo_system_unittests") { "data_pipe_impl_unittest.cc", "data_pipe_unittest.cc", "dispatcher_unittest.cc", + "endpoint_relayer_unittest.cc", "memory_unittest.cc", + "message_in_transit_queue_unittest.cc", + "message_in_transit_test_utils.cc", + "message_in_transit_test_utils.h", "message_pipe_dispatcher_unittest.cc", "message_pipe_test_utils.cc", "message_pipe_test_utils.h", @@ -181,6 +189,8 @@ test("mojo_system_unittests") { "run_all_unittests.cc", "shared_buffer_dispatcher_unittest.cc", "simple_dispatcher_unittest.cc", + "test_channel_endpoint_client.cc", + "test_channel_endpoint_client.h", "unique_identifier_unittest.cc", "waiter_test_utils.cc", "waiter_test_utils.h", diff --git a/third_party/mojo/src/mojo/edk/system/async_waiter.h b/third_party/mojo/src/mojo/edk/system/async_waiter.h index df3b482..be228e5 100644 --- a/third_party/mojo/src/mojo/edk/system/async_waiter.h +++ b/third_party/mojo/src/mojo/edk/system/async_waiter.h @@ -17,7 +17,7 @@ namespace system { // An |Awakable| implementation that just calls a given callback object. class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable { public: - typedef base::Callback<void(MojoResult)> AwakeCallback; + using AwakeCallback = base::Callback<void(MojoResult)>; // |callback| must satisfy the same contract as |Awakable::Awake()|. explicit AsyncWaiter(const AwakeCallback& callback); diff --git a/third_party/mojo/src/mojo/edk/system/awakable_list.cc b/third_party/mojo/src/mojo/edk/system/awakable_list.cc index e74e2c0..82fd19a 100644 --- a/third_party/mojo/src/mojo/edk/system/awakable_list.cc +++ b/third_party/mojo/src/mojo/edk/system/awakable_list.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/awakable_list.h" +#include <algorithm> + #include "base/logging.h" #include "mojo/edk/system/awakable.h" #include "mojo/edk/system/handle_signals_state.h" @@ -19,19 +21,24 @@ AwakableList::~AwakableList() { } void AwakableList::AwakeForStateChange(const HandleSignalsState& state) { - for (AwakeInfoList::iterator it = awakables_.begin(); - it != awakables_.end();) { + // Instead of deleting elements in-place, swap them with the last element and + // erase the elements from the end. + auto last = awakables_.end(); + for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { bool keep = true; if (state.satisfies(it->signals)) keep = it->awakable->Awake(MOJO_RESULT_OK, it->context); else if (!state.can_satisfy(it->signals)) keep = it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context); - AwakeInfoList::iterator maybe_delete = it; - ++it; - if (!keep) - awakables_.erase(maybe_delete); + if (!keep) { + --last; + std::swap(*it, *last); + } else { + ++it; + } } + awakables_.erase(last, awakables_.end()); } void AwakableList::CancelAll() { @@ -51,13 +58,16 @@ void AwakableList::Add(Awakable* awakable, void AwakableList::Remove(Awakable* awakable) { // We allow a thread to wait on the same handle multiple times simultaneously, // so we need to scan the entire list and remove all occurrences of |waiter|. - for (AwakeInfoList::iterator it = awakables_.begin(); - it != awakables_.end();) { - AwakeInfoList::iterator maybe_delete = it; - ++it; - if (maybe_delete->awakable == awakable) - awakables_.erase(maybe_delete); + auto last = awakables_.end(); + for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { + if (it->awakable == awakable) { + --last; + std::swap(*it, *last); + } else { + ++it; + } } + awakables_.erase(last, awakables_.end()); } } // namespace system diff --git a/third_party/mojo/src/mojo/edk/system/awakable_list.h b/third_party/mojo/src/mojo/edk/system/awakable_list.h index 19c03c8..2c307f4 100644 --- a/third_party/mojo/src/mojo/edk/system/awakable_list.h +++ b/third_party/mojo/src/mojo/edk/system/awakable_list.h @@ -7,7 +7,7 @@ #include <stdint.h> -#include <list> +#include <vector> #include "base/macros.h" #include "mojo/edk/system/system_impl_export.h" @@ -45,7 +45,7 @@ class MOJO_SYSTEM_IMPL_EXPORT AwakableList { MojoHandleSignals signals; uint32_t context; }; - typedef std::list<AwakeInfo> AwakeInfoList; + using AwakeInfoList = std::vector<AwakeInfo>; AwakeInfoList awakables_; diff --git a/third_party/mojo/src/mojo/edk/system/channel.cc b/third_party/mojo/src/mojo/edk/system/channel.cc index a7da3bf..0eab8cc 100644 --- a/third_party/mojo/src/mojo/edk/system/channel.cc +++ b/third_party/mojo/src/mojo/edk/system/channel.cc @@ -98,10 +98,16 @@ void Channel::WillShutdownSoon() { } void Channel::SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint) { - DCHECK(endpoint); - // Used for both local and remote IDs. ChannelEndpointId bootstrap_id = ChannelEndpointId::GetBootstrap(); + SetBootstrapEndpointWithIds(endpoint.Pass(), bootstrap_id, bootstrap_id); +} + +void Channel::SetBootstrapEndpointWithIds( + scoped_refptr<ChannelEndpoint> endpoint, + ChannelEndpointId local_id, + ChannelEndpointId remote_id) { + DCHECK(endpoint); { base::AutoLock locker(lock_); @@ -109,13 +115,14 @@ void Channel::SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint) { DLOG_IF(WARNING, is_shutting_down_) << "SetBootstrapEndpoint() while shutting down"; - // Bootstrap endpoint should be the first. - DCHECK(local_id_to_endpoint_map_.empty()); + // There must not be an endpoint with that ID already. + DCHECK(local_id_to_endpoint_map_.find(local_id) == + local_id_to_endpoint_map_.end()); - local_id_to_endpoint_map_[bootstrap_id] = endpoint; + local_id_to_endpoint_map_[local_id] = endpoint; } - endpoint->AttachAndRun(this, bootstrap_id, bootstrap_id); + endpoint->AttachAndRun(this, local_id, remote_id); } bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { @@ -166,7 +173,7 @@ void Channel::DetachEndpoint(ChannelEndpoint* endpoint, // Send a remove message outside the lock. } - if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpoint, + if (!SendControlMessage(MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT, local_id, remote_id)) { HandleLocalError(base::StringPrintf( "Failed to send message to remove remote endpoint (local ID %u, remote " @@ -272,11 +279,11 @@ void Channel::OnReadMessage( DCHECK(creation_thread_checker_.CalledOnValidThread()); switch (message_view.type()) { - case MessageInTransit::kTypeEndpointClient: - case MessageInTransit::kTypeEndpoint: + case MessageInTransit::Type::ENDPOINT_CLIENT: + case MessageInTransit::Type::ENDPOINT: OnReadMessageForEndpoint(message_view, platform_handles.Pass()); break; - case MessageInTransit::kTypeChannel: + case MessageInTransit::Type::CHANNEL: OnReadMessageForChannel(message_view, platform_handles.Pass()); break; default: @@ -322,8 +329,8 @@ void Channel::OnReadMessageForEndpoint( const MessageInTransit::View& message_view, embedder::ScopedPlatformHandleVectorPtr platform_handles) { DCHECK(creation_thread_checker_.CalledOnValidThread()); - DCHECK(message_view.type() == MessageInTransit::kTypeEndpointClient || - message_view.type() == MessageInTransit::kTypeEndpoint); + DCHECK(message_view.type() == MessageInTransit::Type::ENDPOINT_CLIENT || + message_view.type() == MessageInTransit::Type::ENDPOINT); ChannelEndpointId local_id = message_view.destination_id(); if (!local_id.is_valid()) { @@ -382,7 +389,7 @@ void Channel::OnReadMessageForChannel( const MessageInTransit::View& message_view, embedder::ScopedPlatformHandleVectorPtr platform_handles) { DCHECK(creation_thread_checker_.CalledOnValidThread()); - DCHECK_EQ(message_view.type(), MessageInTransit::kTypeChannel); + DCHECK_EQ(message_view.type(), MessageInTransit::Type::CHANNEL); // Currently, no channel messages take platform handles. if (platform_handles) { @@ -393,7 +400,7 @@ void Channel::OnReadMessageForChannel( } switch (message_view.subtype()) { - case MessageInTransit::kSubtypeChannelAttachAndRunEndpoint: + case MessageInTransit::Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT: DVLOG(2) << "Handling channel message to attach and run endpoint (local " "ID " << message_view.destination_id() << ", remote ID " << message_view.source_id() << ")"; @@ -403,7 +410,7 @@ void Channel::OnReadMessageForChannel( "Received invalid channel message to attach and run endpoint"); } break; - case MessageInTransit::kSubtypeChannelRemoveEndpoint: + case MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT: DVLOG(2) << "Handling channel message to remove endpoint (local ID " << message_view.destination_id() << ", remote ID " << message_view.source_id() << ")"; @@ -413,7 +420,7 @@ void Channel::OnReadMessageForChannel( "Received invalid channel message to remove endpoint"); } break; - case MessageInTransit::kSubtypeChannelRemoveEndpointAck: + case MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT_ACK: DVLOG(2) << "Handling channel message to ack remove endpoint (local ID " << message_view.destination_id() << ", remote ID " << message_view.source_id() << ")"; @@ -502,8 +509,9 @@ bool Channel::OnRemoveEndpoint(ChannelEndpointId local_id, endpoint->DetachFromChannel(); - if (!SendControlMessage(MessageInTransit::kSubtypeChannelRemoveEndpointAck, - local_id, remote_id)) { + if (!SendControlMessage( + MessageInTransit::Subtype::CHANNEL_REMOVE_ENDPOINT_ACK, local_id, + remote_id)) { HandleLocalError(base::StringPrintf( "Failed to send message to ack remove remote endpoint (local ID %u, " "remote ID %u)", @@ -576,8 +584,9 @@ ChannelEndpointId Channel::AttachAndRunEndpoint( local_id_to_endpoint_map_[local_id] = endpoint; } - if (!SendControlMessage(MessageInTransit::kSubtypeChannelAttachAndRunEndpoint, - local_id, remote_id)) { + if (!SendControlMessage( + MessageInTransit::Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT, local_id, + remote_id)) { HandleLocalError(base::StringPrintf( "Failed to send message to run remote endpoint (local ID %u, remote ID " "%u)", @@ -596,7 +605,7 @@ bool Channel::SendControlMessage(MessageInTransit::Subtype subtype, DVLOG(2) << "Sending channel control message: subtype " << subtype << ", local ID " << local_id << ", remote ID " << remote_id; scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeChannel, subtype, 0, nullptr)); + MessageInTransit::Type::CHANNEL, subtype, 0, nullptr)); message->set_source_id(local_id); message->set_destination_id(remote_id); return WriteMessage(message.Pass()); diff --git a/third_party/mojo/src/mojo/edk/system/channel.h b/third_party/mojo/src/mojo/edk/system/channel.h index 93ba87a..d39676a 100644 --- a/third_party/mojo/src/mojo/edk/system/channel.h +++ b/third_party/mojo/src/mojo/edk/system/channel.h @@ -89,6 +89,16 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel // first connection across a channel.) void SetBootstrapEndpoint(scoped_refptr<ChannelEndpoint> endpoint); + // Like |SetBootstrapEndpoint()|, but with explicitly-specified local and + // remote IDs. + // + // (Bootstrapping is still symmetric, though the sides should obviously + // interchange local and remote IDs. This can be used to allow multiple + // "bootstrap" endpoints, though this is really most useful for testing.) + void SetBootstrapEndpointWithIds(scoped_refptr<ChannelEndpoint> endpoint, + ChannelEndpointId local_id, + ChannelEndpointId remote_id); + // This forwards |message| verbatim to |raw_channel_|. bool WriteMessage(scoped_ptr<MessageInTransit> message); @@ -202,9 +212,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel // Helper for |SerializeEndpoint...()|: Attaches the given (non-bootstrap) // endpoint to this channel and runs it. This assigns the endpoint both local - // and remote IDs. This will also send a |kSubtypeChannelAttachAndRunEndpoint| - // message to the remote side to tell it to create an endpoint as well. This - // returns the *remote* ID (one for which |is_remote()| returns true). + // and remote IDs. This will also send a + // |Subtype::CHANNEL_ATTACH_AND_RUN_ENDPOINT| message to the remote side to + // tell it to create an endpoint as well. This returns the *remote* ID (one + // for which |is_remote()| returns true). // // TODO(vtl): Maybe limit the number of attached message pipes. ChannelEndpointId AttachAndRunEndpoint( @@ -235,16 +246,16 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel // Has a reference to us. ChannelManager* channel_manager_; - typedef base::hash_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>> - IdToEndpointMap; + using IdToEndpointMap = + base::hash_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>>; // Map from local IDs to endpoints. If the endpoint is null, this means that // we're just waiting for the remove ack before removing the entry. IdToEndpointMap local_id_to_endpoint_map_; // Note: The IDs generated by this should be checked for existence before use. LocalChannelEndpointIdGenerator local_id_generator_; - typedef base::hash_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>> - IdToIncomingEndpointMap; + using IdToIncomingEndpointMap = + base::hash_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>>; // Map from local IDs to incoming endpoints (i.e., those received inside other // messages, but not yet claimed via |DeserializeEndpoint()|). IdToIncomingEndpointMap incoming_endpoints_; diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc index 72d9e28..30974c5 100644 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc +++ b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc @@ -93,12 +93,12 @@ void ChannelEndpoint::AttachAndRun(Channel* channel, } void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) { - if (message->type() == MessageInTransit::kTypeEndpointClient) { + if (message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) { OnReadMessageForClient(message.Pass()); return; } - DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpoint); + DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT); // TODO(vtl) // Note that this won't crash on Release builds, which is important (since the @@ -161,7 +161,7 @@ bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> message) { void ChannelEndpoint::OnReadMessageForClient( scoped_ptr<MessageInTransit> message) { - DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpointClient); + DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); scoped_refptr<ChannelEndpointClient> client; unsigned client_port = 0; diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h b/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h index c673258..afacb4e 100644 --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h +++ b/third_party/mojo/src/mojo/edk/system/channel_endpoint_id.h @@ -81,8 +81,9 @@ static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t), "ChannelEndpointId has incorrect size"); // So logging macros and |DCHECK_EQ()|, etc. work. -inline std::ostream& operator<<(std::ostream& out, - const ChannelEndpointId& channel_endpoint_id) { +MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( + std::ostream& out, + const ChannelEndpointId& channel_endpoint_id) { return out << channel_endpoint_id.value(); } diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc new file mode 100644 index 0000000..78ba489 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/channel_endpoint_unittest.cc @@ -0,0 +1,137 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/channel_endpoint.h" + +#include "base/macros.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/test_timeouts.h" +#include "mojo/edk/system/channel_test_base.h" +#include "mojo/edk/system/message_in_transit_queue.h" +#include "mojo/edk/system/message_in_transit_test_utils.h" +#include "mojo/edk/system/test_channel_endpoint_client.h" + +namespace mojo { +namespace system { +namespace { + +class ChannelEndpointTest : public test::ChannelTestBase { + public: + ChannelEndpointTest() {} + ~ChannelEndpointTest() override {} + + void SetUp() override { + test::ChannelTestBase::SetUp(); + + PostMethodToIOThreadAndWait( + FROM_HERE, &ChannelEndpointTest::CreateAndInitChannelOnIOThread, 0); + PostMethodToIOThreadAndWait( + FROM_HERE, &ChannelEndpointTest::CreateAndInitChannelOnIOThread, 1); + } + + void TearDown() override { + PostMethodToIOThreadAndWait( + FROM_HERE, &ChannelEndpointTest::ShutdownChannelOnIOThread, 0); + PostMethodToIOThreadAndWait( + FROM_HERE, &ChannelEndpointTest::ShutdownChannelOnIOThread, 1); + + test::ChannelTestBase::TearDown(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ChannelEndpointTest); +}; + +TEST_F(ChannelEndpointTest, Basic) { + scoped_refptr<test::TestChannelEndpointClient> client0( + new test::TestChannelEndpointClient()); + scoped_refptr<ChannelEndpoint> endpoint0( + new ChannelEndpoint(client0.get(), 0)); + client0->Init(0, endpoint0.get()); + channel(0)->SetBootstrapEndpoint(endpoint0); + + scoped_refptr<test::TestChannelEndpointClient> client1( + new test::TestChannelEndpointClient()); + scoped_refptr<ChannelEndpoint> endpoint1( + new ChannelEndpoint(client1.get(), 1)); + client1->Init(1, endpoint1.get()); + channel(1)->SetBootstrapEndpoint(endpoint1); + + // We'll receive a message on channel/client 0. + base::WaitableEvent read_event(true, false); + client0->SetReadEvent(&read_event); + + // Make a test message. + unsigned message_id = 0x12345678; + scoped_ptr<MessageInTransit> send_message = test::MakeTestMessage(message_id); + // Check that our test utility works (at least in one direction). + test::VerifyTestMessage(send_message.get(), message_id); + + // Event shouldn't be signalled yet. + EXPECT_FALSE(read_event.IsSignaled()); + + // Send it through channel/endpoint 1. + EXPECT_TRUE(endpoint1->EnqueueMessage(send_message.Pass())); + + // Wait to receive it. + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + client0->SetReadEvent(nullptr); + + // Check the received message. + ASSERT_EQ(1u, client0->NumMessages()); + scoped_ptr<MessageInTransit> read_message = client0->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), message_id); +} + +// Checks that prequeued messages and messages sent at various stages later on +// are all sent/received (and in the correct order). (Note: Due to the way +// bootstrap endpoints work, the receiving side has to be set up first.) +TEST_F(ChannelEndpointTest, Prequeued) { + scoped_refptr<test::TestChannelEndpointClient> client0( + new test::TestChannelEndpointClient()); + scoped_refptr<ChannelEndpoint> endpoint0( + new ChannelEndpoint(client0.get(), 0)); + client0->Init(0, endpoint0.get()); + + channel(0)->SetBootstrapEndpoint(endpoint0); + MessageInTransitQueue prequeued_messages; + prequeued_messages.AddMessage(test::MakeTestMessage(1)); + prequeued_messages.AddMessage(test::MakeTestMessage(2)); + + scoped_refptr<test::TestChannelEndpointClient> client1( + new test::TestChannelEndpointClient()); + scoped_refptr<ChannelEndpoint> endpoint1( + new ChannelEndpoint(client1.get(), 1, &prequeued_messages)); + client1->Init(1, endpoint1.get()); + + EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(3))); + EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(4))); + + channel(1)->SetBootstrapEndpoint(endpoint1); + + EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(5))); + EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(6))); + + // Wait for the messages. + base::WaitableEvent read_event(true, false); + client0->SetReadEvent(&read_event); + for (size_t i = 0; client0->NumMessages() < 6 && i < 6; i++) { + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + read_event.Reset(); + } + client0->SetReadEvent(nullptr); + + // Check the received messages. + ASSERT_EQ(6u, client0->NumMessages()); + for (unsigned message_id = 1; message_id <= 6; message_id++) { + scoped_ptr<MessageInTransit> read_message = client0->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), message_id); + } +} + +} // namespace +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.h b/third_party/mojo/src/mojo/edk/system/channel_manager.h index 77ff953..19c3b42 100644 --- a/third_party/mojo/src/mojo/edk/system/channel_manager.h +++ b/third_party/mojo/src/mojo/edk/system/channel_manager.h @@ -34,7 +34,7 @@ class MessagePipeDispatcher; // IDs for |Channel|s managed by a |ChannelManager|. (IDs should be thought of // as specific to a given |ChannelManager|.) 0 is never a valid ID. -typedef uint64_t ChannelId; +using ChannelId = uint64_t; const ChannelId kInvalidChannelId = 0; diff --git a/third_party/mojo/src/mojo/edk/system/channel_test_base.cc b/third_party/mojo/src/mojo/edk/system/channel_test_base.cc new file mode 100644 index 0000000..15bc607 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/channel_test_base.cc @@ -0,0 +1,64 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/channel_test_base.h" + +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/system/raw_channel.h" + +namespace mojo { +namespace system { +namespace test { + +ChannelTestBase::ChannelTestBase() + : io_thread_(base::TestIOThread::kAutoStart) { +} + +ChannelTestBase::~ChannelTestBase() { +} + +void ChannelTestBase::SetUp() { + PostMethodToIOThreadAndWait(FROM_HERE, &ChannelTestBase::SetUpOnIOThread); +} + +void ChannelTestBase::CreateChannelOnIOThread(unsigned i) { + CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); + + CHECK(!channels_[i]); + channels_[i] = new Channel(&platform_support_); +} + +void ChannelTestBase::InitChannelOnIOThread(unsigned i) { + CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); + + CHECK(raw_channels_[i]); + CHECK(channels_[i]); + channels_[i]->Init(raw_channels_[i].Pass()); +} + +void ChannelTestBase::CreateAndInitChannelOnIOThread(unsigned i) { + CreateChannelOnIOThread(i); + InitChannelOnIOThread(i); +} + +void ChannelTestBase::ShutdownChannelOnIOThread(unsigned i) { + CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); + + CHECK(channels_[i]); + channels_[i]->Shutdown(); +} + +void ChannelTestBase::SetUpOnIOThread() { + CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); + + embedder::PlatformChannelPair channel_pair; + raw_channels_[0] = RawChannel::Create(channel_pair.PassServerHandle()); + raw_channels_[1] = RawChannel::Create(channel_pair.PassClientHandle()); +} + +} // namespace test +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/channel_test_base.h b/third_party/mojo/src/mojo/edk/system/channel_test_base.h new file mode 100644 index 0000000..81ef27f --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/channel_test_base.h @@ -0,0 +1,66 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ +#define MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ + +#include "base/bind.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/test/test_io_thread.h" +#include "mojo/edk/embedder/simple_platform_support.h" +#include "mojo/edk/system/channel.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace system { + +class RawChannel; + +namespace test { + +// A base class for tests that need a |Channel| set up in a simple way. +class ChannelTestBase : public testing::Test { + public: + ChannelTestBase(); + ~ChannelTestBase() override; + + void SetUp() override; + + template <typename Functor, typename... Args> + void PostMethodToIOThreadAndWait(const tracked_objects::Location& from_here, + Functor functor, + const Args&... args) { + io_thread_.PostTaskAndWait( + from_here, base::Bind(functor, base::Unretained(this), args...)); + } + + // These should only be called from |io_thread()|: + void CreateChannelOnIOThread(unsigned i); + void InitChannelOnIOThread(unsigned i); + void CreateAndInitChannelOnIOThread(unsigned i); + void ShutdownChannelOnIOThread(unsigned i); + + base::TestIOThread* io_thread() { return &io_thread_; } + Channel* channel(unsigned i) { return channels_[i].get(); } + scoped_refptr<Channel>* mutable_channel(unsigned i) { return &channels_[i]; } + + private: + void SetUpOnIOThread(); + + embedder::SimplePlatformSupport platform_support_; + base::TestIOThread io_thread_; + scoped_ptr<RawChannel> raw_channels_[2]; + scoped_refptr<Channel> channels_[2]; + + DISALLOW_COPY_AND_ASSIGN(ChannelTestBase); +}; + +} // namespace test +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ diff --git a/third_party/mojo/src/mojo/edk/system/channel_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_unittest.cc index e82b321..5f2f6eb 100644 --- a/third_party/mojo/src/mojo/edk/system/channel_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/channel_unittest.cc @@ -4,111 +4,37 @@ #include "mojo/edk/system/channel.h" -#include "base/bind.h" -#include "base/location.h" -#include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/channel_endpoint_id.h" +#include "mojo/edk/system/channel_test_base.h" #include "mojo/edk/system/message_pipe.h" -#include "mojo/edk/system/raw_channel.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/waiter.h" -#include "testing/gtest/include/gtest/gtest.h" namespace mojo { namespace system { namespace { -class ChannelTest : public testing::Test { - public: - ChannelTest() : io_thread_(base::TestIOThread::kAutoStart) {} - ~ChannelTest() override {} - - void SetUp() override { - io_thread_.PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelTest::SetUpOnIOThread, base::Unretained(this))); - } - - void CreateChannelOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - channel_ = new Channel(&platform_support_); - } - - void InitChannelOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - CHECK(raw_channel_); - CHECK(channel_); - channel_->Init(raw_channel_.Pass()); - } - - void ShutdownChannelOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - CHECK(channel_); - channel_->Shutdown(); - } - - base::TestIOThread* io_thread() { return &io_thread_; } - RawChannel* raw_channel() { return raw_channel_.get(); } - scoped_ptr<RawChannel>* mutable_raw_channel() { return &raw_channel_; } - Channel* channel() { return channel_.get(); } - scoped_refptr<Channel>* mutable_channel() { return &channel_; } - - private: - void SetUpOnIOThread() { - CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - - embedder::PlatformChannelPair channel_pair; - raw_channel_ = RawChannel::Create(channel_pair.PassServerHandle()).Pass(); - other_platform_handle_ = channel_pair.PassClientHandle(); - } - - embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - scoped_ptr<RawChannel> raw_channel_; - embedder::ScopedPlatformHandle other_platform_handle_; - scoped_refptr<Channel> channel_; - - DISALLOW_COPY_AND_ASSIGN(ChannelTest); -}; +using ChannelTest = test::ChannelTestBase; // ChannelTest.InitShutdown ---------------------------------------------------- TEST_F(ChannelTest, InitShutdown) { - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&ChannelTest::CreateChannelOnIOThread, - base::Unretained(this))); - ASSERT_TRUE(channel()); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this))); - - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread, - base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::CreateAndInitChannelOnIOThread, 0); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::ShutdownChannelOnIOThread, 0); // Okay to destroy |Channel| on not-the-I/O-thread. - EXPECT_TRUE(channel()->HasOneRef()); - *mutable_channel() = nullptr; + EXPECT_TRUE(channel(0)->HasOneRef()); + *mutable_channel(0) = nullptr; } // ChannelTest.CloseBeforeAttachAndRun ----------------------------------------- TEST_F(ChannelTest, CloseBeforeRun) { - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&ChannelTest::CreateChannelOnIOThread, - base::Unretained(this))); - ASSERT_TRUE(channel()); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::CreateAndInitChannelOnIOThread, 0); scoped_refptr<ChannelEndpoint> channel_endpoint; scoped_refptr<MessagePipe> mp( @@ -116,32 +42,25 @@ TEST_F(ChannelTest, CloseBeforeRun) { mp->Close(0); - channel()->SetBootstrapEndpoint(channel_endpoint); + channel(0)->SetBootstrapEndpoint(channel_endpoint); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread, - base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::ShutdownChannelOnIOThread, 0); - EXPECT_TRUE(channel()->HasOneRef()); + EXPECT_TRUE(channel(0)->HasOneRef()); } // ChannelTest.ShutdownAfterAttachAndRun --------------------------------------- TEST_F(ChannelTest, ShutdownAfterAttach) { - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&ChannelTest::CreateChannelOnIOThread, - base::Unretained(this))); - ASSERT_TRUE(channel()); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::CreateAndInitChannelOnIOThread, 0); scoped_refptr<ChannelEndpoint> channel_endpoint; scoped_refptr<MessagePipe> mp( MessagePipe::CreateLocalProxy(&channel_endpoint)); - channel()->SetBootstrapEndpoint(channel_endpoint); + channel(0)->SetBootstrapEndpoint(channel_endpoint); Waiter waiter; waiter.Init(); @@ -150,9 +69,8 @@ TEST_F(ChannelTest, ShutdownAfterAttach) { mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Don't wait for the shutdown to run ... - io_thread()->PostTask(FROM_HERE, - base::Bind(&ChannelTest::ShutdownChannelOnIOThread, - base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::ShutdownChannelOnIOThread, 0); // ... since this |Wait()| should fail once the channel is shut down. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, @@ -164,30 +82,23 @@ TEST_F(ChannelTest, ShutdownAfterAttach) { mp->Close(0); - EXPECT_TRUE(channel()->HasOneRef()); + EXPECT_TRUE(channel(0)->HasOneRef()); } // ChannelTest.WaitAfterAttachRunAndShutdown ----------------------------------- TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) { - io_thread()->PostTaskAndWait(FROM_HERE, - base::Bind(&ChannelTest::CreateChannelOnIOThread, - base::Unretained(this))); - ASSERT_TRUE(channel()); - - io_thread()->PostTaskAndWait( - FROM_HERE, - base::Bind(&ChannelTest::InitChannelOnIOThread, base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::CreateAndInitChannelOnIOThread, 0); scoped_refptr<ChannelEndpoint> channel_endpoint; scoped_refptr<MessagePipe> mp( MessagePipe::CreateLocalProxy(&channel_endpoint)); - channel()->SetBootstrapEndpoint(channel_endpoint); + channel(0)->SetBootstrapEndpoint(channel_endpoint); - io_thread()->PostTaskAndWait( - FROM_HERE, base::Bind(&ChannelTest::ShutdownChannelOnIOThread, - base::Unretained(this))); + PostMethodToIOThreadAndWait(FROM_HERE, + &ChannelTest::ShutdownChannelOnIOThread, 0); Waiter waiter; waiter.Init(); @@ -200,7 +111,7 @@ TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) { mp->Close(0); - EXPECT_TRUE(channel()->HasOneRef()); + EXPECT_TRUE(channel(0)->HasOneRef()); } // TODO(vtl): More. ------------------------------------------------------------ diff --git a/third_party/mojo/src/mojo/edk/system/connection_identifier.h b/third_party/mojo/src/mojo/edk/system/connection_identifier.h new file mode 100644 index 0000000..86ae37d --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/connection_identifier.h @@ -0,0 +1,20 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ +#define MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ + +#include "mojo/edk/system/unique_identifier.h" + +namespace mojo { +namespace system { + +// (Temporary, unique) identifiers for connections (for used with +// |ConnectionManager|s), used as they are being brought up: +using ConnectionIdentifier = UniqueIdentifier; + +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_CONNECTION_IDENTIFIER_H_ diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager.h b/third_party/mojo/src/mojo/edk/system/connection_manager.h index 8820dd5..9aeaa26 100644 --- a/third_party/mojo/src/mojo/edk/system/connection_manager.h +++ b/third_party/mojo/src/mojo/edk/system/connection_manager.h @@ -6,8 +6,8 @@ #define MOJO_EDK_SYSTEM_CONNECTION_MANAGER_H_ #include "base/macros.h" +#include "mojo/edk/system/connection_identifier.h" #include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/unique_identifier.h" namespace mojo { @@ -18,12 +18,8 @@ class ScopedPlatformHandle; namespace system { -// (Temporary, unique) identifiers for connections, used as they are being -// brought up: -typedef UniqueIdentifier ConnectionIdentifier; - // Identifiers for processes (note that these are not OS process IDs): -typedef uint64_t ProcessIdentifier; +using ProcessIdentifier = uint64_t; const ProcessIdentifier kInvalidProcessIdentifier = 0; // |ConnectionManager| is an interface for the system that allows "connections" diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.cc b/third_party/mojo/src/mojo/edk/system/core_test_base.cc index 7196886d..0e58363 100644 --- a/third_party/mojo/src/mojo/edk/system/core_test_base.cc +++ b/third_party/mojo/src/mojo/edk/system/core_test_base.cc @@ -30,7 +30,7 @@ class MockDispatcher : public Dispatcher { } // |Dispatcher| private methods: - Type GetType() const override { return kTypeUnknown; } + Type GetType() const override { return Type::UNKNOWN; } private: ~MockDispatcher() override { info_->IncrementDtorCallCount(); } diff --git a/third_party/mojo/src/mojo/edk/system/core_test_base.h b/third_party/mojo/src/mojo/edk/system/core_test_base.h index 26b7925..3eb2364 100644 --- a/third_party/mojo/src/mojo/edk/system/core_test_base.h +++ b/third_party/mojo/src/mojo/edk/system/core_test_base.h @@ -23,7 +23,7 @@ class CoreTestBase_MockHandleInfo; class CoreTestBase : public testing::Test { public: - typedef CoreTestBase_MockHandleInfo MockHandleInfo; + using MockHandleInfo = CoreTestBase_MockHandleInfo; CoreTestBase(); ~CoreTestBase() override; diff --git a/third_party/mojo/src/mojo/edk/system/core_unittest.cc b/third_party/mojo/src/mojo/edk/system/core_unittest.cc index b789301..c562097 100644 --- a/third_party/mojo/src/mojo/edk/system/core_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/core_unittest.cc @@ -24,7 +24,7 @@ const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED; -typedef test::CoreTestBase CoreTest; +using CoreTest = test::CoreTestBase; TEST_F(CoreTest, GetTimeTicksNow) { const MojoTimeTicks start = core()->GetTimeTicksNow(); diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc index bee4b23..076b724 100644 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc @@ -20,7 +20,7 @@ void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { } Dispatcher::Type DataPipeConsumerDispatcher::GetType() const { - return kTypeDataPipeConsumer; + return Type::DATA_PIPE_CONSUMER; } // static diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc index 74ba55a..6c19297 100644 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc +++ b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.cc @@ -35,8 +35,8 @@ void DataPipeImpl::ConvertDataToMessages(const char* buffer, // Note: |message_num_bytes| fits in a |uint32_t| since the capacity does. scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, static_cast<uint32_t>(message_num_bytes), buffer + *start_index)); message_queue->AddMessage(message.Pass()); diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc index 17021f3..1688e3d 100644 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/data_pipe_impl_unittest.cc @@ -376,7 +376,7 @@ class RemoteProducerDataPipeImplTestHelper EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeProducer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); producer_dispatcher_ = static_cast<DataPipeProducerDispatcher*>(to_receive.get()); } @@ -426,7 +426,7 @@ class RemoteConsumerDataPipeImplTestHelper EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeConsumer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); consumer_dispatcher_ = static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); } @@ -480,7 +480,7 @@ class RemoteProducerDataPipeImplTestHelper2 // destroyed. EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeProducer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); to_send = static_cast<DataPipeProducerDispatcher*>(to_receive.get()); to_receive = nullptr; @@ -491,7 +491,7 @@ class RemoteProducerDataPipeImplTestHelper2 EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeProducer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType()); producer_dispatcher_ = static_cast<DataPipeProducerDispatcher*>(to_receive.get()); } @@ -527,7 +527,7 @@ class RemoteConsumerDataPipeImplTestHelper2 // destroyed. EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeConsumer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); to_send = static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); to_receive = nullptr; @@ -538,7 +538,7 @@ class RemoteConsumerDataPipeImplTestHelper2 EXPECT_TRUE(to_send->HasOneRef()); to_send = nullptr; - ASSERT_EQ(Dispatcher::kTypeDataPipeConsumer, to_receive->GetType()); + ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType()); consumer_dispatcher_ = static_cast<DataPipeConsumerDispatcher*>(to_receive.get()); } @@ -549,11 +549,11 @@ class RemoteConsumerDataPipeImplTestHelper2 // Test case instantiation ----------------------------------------------------- -typedef testing::Types<LocalDataPipeImplTestHelper, - RemoteProducerDataPipeImplTestHelper, - RemoteConsumerDataPipeImplTestHelper, - RemoteProducerDataPipeImplTestHelper2, - RemoteConsumerDataPipeImplTestHelper2> HelperTypes; +using HelperTypes = testing::Types<LocalDataPipeImplTestHelper, + RemoteProducerDataPipeImplTestHelper, + RemoteConsumerDataPipeImplTestHelper, + RemoteProducerDataPipeImplTestHelper2, + RemoteConsumerDataPipeImplTestHelper2>; TYPED_TEST_CASE(DataPipeImplTest, HelperTypes); diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc index 2480097..ccd0291 100644 --- a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc @@ -20,7 +20,7 @@ void DataPipeProducerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { } Dispatcher::Type DataPipeProducerDispatcher::GetType() const { - return kTypeDataPipeProducer; + return Type::DATA_PIPE_PRODUCER; } // static diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.cc b/third_party/mojo/src/mojo/edk/system/dispatcher.cc index e8695e8..24f2c26 100644 --- a/third_party/mojo/src/mojo/edk/system/dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/dispatcher.cc @@ -71,23 +71,23 @@ scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( const void* source, size_t size, embedder::PlatformHandleVector* platform_handles) { - switch (static_cast<int32_t>(type)) { - case kTypeUnknown: + switch (static_cast<Dispatcher::Type>(type)) { + case Type::UNKNOWN: DVLOG(2) << "Deserializing invalid handle"; return nullptr; - case kTypeMessagePipe: + case Type::MESSAGE_PIPE: return scoped_refptr<Dispatcher>( MessagePipeDispatcher::Deserialize(channel, source, size)); - case kTypeDataPipeProducer: + case Type::DATA_PIPE_PRODUCER: return scoped_refptr<Dispatcher>( DataPipeProducerDispatcher::Deserialize(channel, source, size)); - case kTypeDataPipeConsumer: + case Type::DATA_PIPE_CONSUMER: return scoped_refptr<Dispatcher>( DataPipeConsumerDispatcher::Deserialize(channel, source, size)); - case kTypeSharedBuffer: + case Type::SHARED_BUFFER: return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize( channel, source, size, platform_handles)); - case kTypePlatformHandle: + case Type::PLATFORM_HANDLE: return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize( channel, source, size, platform_handles)); } diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.h b/third_party/mojo/src/mojo/edk/system/dispatcher.h index 4bbc5ed..d7b7780 100644 --- a/third_party/mojo/src/mojo/edk/system/dispatcher.h +++ b/third_party/mojo/src/mojo/edk/system/dispatcher.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <ostream> #include <vector> #include "base/macros.h" @@ -41,7 +42,7 @@ class ProxyMessagePipeEndpoint; class TransportData; class Awakable; -typedef std::vector<scoped_refptr<Dispatcher>> DispatcherVector; +using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; namespace test { @@ -59,15 +60,15 @@ DispatcherTryStartTransport(Dispatcher* dispatcher); class MOJO_SYSTEM_IMPL_EXPORT Dispatcher : public base::RefCountedThreadSafe<Dispatcher> { public: - enum Type { - kTypeUnknown = 0, - kTypeMessagePipe, - kTypeDataPipeProducer, - kTypeDataPipeConsumer, - kTypeSharedBuffer, + enum class Type { + UNKNOWN = 0, + MESSAGE_PIPE, + DATA_PIPE_PRODUCER, + DATA_PIPE_CONSUMER, + SHARED_BUFFER, // "Private" types (not exposed via the public interface): - kTypePlatformHandle = -1 + PLATFORM_HANDLE = -1 }; virtual Type GetType() const = 0; @@ -399,6 +400,12 @@ class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { // Copy and assign allowed. }; +// So logging macros and |DCHECK_EQ()|, etc. work. +MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, + Dispatcher::Type type) { + return out << static_cast<int>(type); +} + } // namespace system } // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc index 97e2eed..2b853d2 100644 --- a/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/dispatcher_unittest.cc @@ -23,7 +23,7 @@ class TrivialDispatcher : public Dispatcher { public: TrivialDispatcher() {} - Type GetType() const override { return kTypeUnknown; } + Type GetType() const override { return Type::UNKNOWN; } private: friend class base::RefCountedThreadSafe<TrivialDispatcher>; @@ -41,7 +41,7 @@ class TrivialDispatcher : public Dispatcher { TEST(DispatcherTest, Basic) { scoped_refptr<Dispatcher> d(new TrivialDispatcher()); - EXPECT_EQ(Dispatcher::kTypeUnknown, d->GetType()); + EXPECT_EQ(Dispatcher::Type::UNKNOWN, d->GetType()); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->WriteMessage(NullUserPointer(), 0, nullptr, diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc index 52faefa..9630216 100644 --- a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc +++ b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.cc @@ -30,6 +30,11 @@ void EndpointRelayer::Init(ChannelEndpoint* endpoint0, endpoints_[1] = endpoint1; } +void EndpointRelayer::SetFilter(scoped_ptr<Filter> filter) { + base::AutoLock locker(lock_); + filter_ = filter.Pass(); +} + bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { DCHECK(message); @@ -39,8 +44,15 @@ bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { if (!endpoints_[port]) return false; - // Otherwise, consume it even if the peer port is closed. unsigned peer_port = GetPeerPort(port); + + if (filter_ && message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) { + if (filter_->OnReadMessage(endpoints_[port].get(), + endpoints_[peer_port].get(), message)) + return true; + } + + // Otherwise, consume it even if the peer port is closed. if (endpoints_[peer_port]) endpoints_[peer_port]->EnqueueMessage(make_scoped_ptr(message)); return true; diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h index a0a93a4..dba4367 100644 --- a/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h +++ b/third_party/mojo/src/mojo/edk/system/endpoint_relayer.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/system_impl_export.h" @@ -20,6 +21,46 @@ class ChannelEndpoint; // two |ChannelEndpoint|s (without the overhead of |MessagePipe|). class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer : public ChannelEndpointClient { public: + // A class that can inspect and optionally handle messages of type + // |Type::ENDPOINT_CLIENT| received from either |ChannelEndpoint|. + // + // Instances of implementations of this class will be owned by + // |EndpointRelayer|s. + // + // Destructors may not call methods of the |EndpointRelayer| (nor of the + // |ChannelEndpoint|s). + class MOJO_SYSTEM_IMPL_EXPORT Filter { + public: + virtual ~Filter() {} + + // Called by |EndpointRelayer::OnReadMessage()| for messages of type + // |Type::ENDPOINT_CLIENT|. This is only called by the |EndpointRelayer| if + // it is still the client of the sending endpoint. + // + // |endpoint| (which will not be null) is the |ChannelEndpoint| + // corresponding to |port| (i.e., the endpoint the message was received + // from), whereas |peer_endpoint| (which may be null) is that corresponding + // to the peer port (i.e., the endpoint to which the message would be + // relayed). + // + // This should return true if the message is consumed (in which case + // ownership is transferred), and false if not (in which case the message + // will be relayed as usual). + // + // This will always be called under |EndpointRelayer|'s lock. This may call + // |ChannelEndpoint| methods. However, it may not call any of + // |EndpointRelayer|'s methods. + virtual bool OnReadMessage(ChannelEndpoint* endpoint, + ChannelEndpoint* peer_endpoint, + MessageInTransit* message) = 0; + + protected: + Filter() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Filter); + }; + EndpointRelayer(); // Gets the other port number (i.e., 0 -> 1, 1 -> 0). @@ -28,6 +69,10 @@ class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer : public ChannelEndpointClient { // Initialize this object. This must be called before any other method. void Init(ChannelEndpoint* endpoint0, ChannelEndpoint* endpoint1); + // Sets (or resets) the filter, which can (optionally) handle/filter + // |Type::ENDPOINT_CLIENT| messages (see |Filter| above). + void SetFilter(scoped_ptr<Filter> filter); + // |ChannelEndpointClient| methods: bool OnReadMessage(unsigned port, MessageInTransit* message) override; void OnDetachFromChannel(unsigned port) override; @@ -39,6 +84,7 @@ class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer : public ChannelEndpointClient { // thread-safe |scoped_refptr|. base::Lock lock_; // Protects the following members. scoped_refptr<ChannelEndpoint> endpoints_[2]; + scoped_ptr<Filter> filter_; DISALLOW_COPY_AND_ASSIGN(EndpointRelayer); }; diff --git a/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc b/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc new file mode 100644 index 0000000..88001c0 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/endpoint_relayer_unittest.cc @@ -0,0 +1,231 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/endpoint_relayer.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/test_timeouts.h" +#include "mojo/edk/system/channel_endpoint_id.h" +#include "mojo/edk/system/channel_test_base.h" +#include "mojo/edk/system/message_in_transit_queue.h" +#include "mojo/edk/system/message_in_transit_test_utils.h" +#include "mojo/edk/system/test_channel_endpoint_client.h" + +namespace mojo { +namespace system { +namespace { + +class EndpointRelayerTest : public test::ChannelTestBase { + public: + EndpointRelayerTest() {} + ~EndpointRelayerTest() override {} + + void SetUp() override { + test::ChannelTestBase::SetUp(); + + PostMethodToIOThreadAndWait( + FROM_HERE, &EndpointRelayerTest::CreateAndInitChannelOnIOThread, 0); + PostMethodToIOThreadAndWait( + FROM_HERE, &EndpointRelayerTest::CreateAndInitChannelOnIOThread, 1); + + // The set up: + // * Across the pair of channels, we'll have a pair of connections (call + // them "a" and "b"). + // * On channel 0, we'll have a pair of endpoints ("0a" and "0b") hooked up + // to an |EndpointRelayer|. + // * On channel 1, we'll have a pair of endpoints hooked up to test endpoint + // clients ("1a" and "1b"). + LocalChannelEndpointIdGenerator id_generator; + ChannelEndpointId ida = id_generator.GetNext(); + ChannelEndpointId idb = id_generator.GetNext(); + + relayer_ = new EndpointRelayer(); + endpoint0a_ = new ChannelEndpoint(relayer_.get(), 0); + endpoint0b_ = new ChannelEndpoint(relayer_.get(), 1); + relayer_->Init(endpoint0a_.get(), endpoint0b_.get()); + channel(0)->SetBootstrapEndpointWithIds(endpoint0a_, ida, ida); + channel(0)->SetBootstrapEndpointWithIds(endpoint0b_, idb, idb); + + client1a_ = new test::TestChannelEndpointClient(); + client1b_ = new test::TestChannelEndpointClient(); + endpoint1a_ = new ChannelEndpoint(client1a_.get(), 0); + endpoint1b_ = new ChannelEndpoint(client1b_.get(), 0); + client1a_->Init(0, endpoint1a_.get()); + client1b_->Init(0, endpoint1b_.get()); + channel(1)->SetBootstrapEndpointWithIds(endpoint1a_, ida, ida); + channel(1)->SetBootstrapEndpointWithIds(endpoint1b_, idb, idb); + } + + void TearDown() override { + PostMethodToIOThreadAndWait( + FROM_HERE, &EndpointRelayerTest::ShutdownChannelOnIOThread, 0); + PostMethodToIOThreadAndWait( + FROM_HERE, &EndpointRelayerTest::ShutdownChannelOnIOThread, 1); + + test::ChannelTestBase::TearDown(); + } + + protected: + EndpointRelayer* relayer() { return relayer_.get(); } + test::TestChannelEndpointClient* client1a() { return client1a_.get(); } + test::TestChannelEndpointClient* client1b() { return client1b_.get(); } + ChannelEndpoint* endpoint1a() { return endpoint1a_.get(); } + ChannelEndpoint* endpoint1b() { return endpoint1b_.get(); } + + private: + scoped_refptr<EndpointRelayer> relayer_; + scoped_refptr<ChannelEndpoint> endpoint0a_; + scoped_refptr<ChannelEndpoint> endpoint0b_; + scoped_refptr<test::TestChannelEndpointClient> client1a_; + scoped_refptr<test::TestChannelEndpointClient> client1b_; + scoped_refptr<ChannelEndpoint> endpoint1a_; + scoped_refptr<ChannelEndpoint> endpoint1b_; + + DISALLOW_COPY_AND_ASSIGN(EndpointRelayerTest); +}; + +TEST_F(EndpointRelayerTest, Basic) { + base::WaitableEvent read_event(true, false); + client1b()->SetReadEvent(&read_event); + EXPECT_EQ(0u, client1b()->NumMessages()); + + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(12345))); + + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + client1b()->SetReadEvent(nullptr); + + ASSERT_EQ(1u, client1b()->NumMessages()); + scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), 12345); + + // Now do the same thing in the opposite direction. + read_event.Reset(); + client1a()->SetReadEvent(&read_event); + EXPECT_EQ(0u, client1a()->NumMessages()); + + EXPECT_TRUE(endpoint1b()->EnqueueMessage(test::MakeTestMessage(67890))); + + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + client1a()->SetReadEvent(nullptr); + + ASSERT_EQ(1u, client1a()->NumMessages()); + read_message = client1a()->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), 67890); +} + +TEST_F(EndpointRelayerTest, MultipleMessages) { + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(2))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(3))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(4))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5))); + + base::WaitableEvent read_event(true, false); + client1b()->SetReadEvent(&read_event); + for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) { + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + read_event.Reset(); + } + client1b()->SetReadEvent(nullptr); + + // Check the received messages. + ASSERT_EQ(5u, client1b()->NumMessages()); + for (unsigned message_id = 1; message_id <= 5; message_id++) { + scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), message_id); + } +} + +// A simple test filter. It will filter test messages made with +// |test::MakeTestMessage()| with |id >= 1000|, and not filter other messages. +class TestFilter : public EndpointRelayer::Filter { + public: + // |filtered_messages| will receive (and own) filtered messages; it will be + // accessed under the owning |EndpointRelayer|'s lock, and must outlive this + // filter. + // + // (Outside this class, you should only access |filtered_messages| once this + // filter is no longer the |EndpointRelayer|'s filter.) + explicit TestFilter(MessageInTransitQueue* filtered_messages) + : filtered_messages_(filtered_messages) { + CHECK(filtered_messages_); + } + + ~TestFilter() override {} + + // Note: Recall that this is called under the |EndpointRelayer|'s lock. + bool OnReadMessage(ChannelEndpoint* endpoint, + ChannelEndpoint* peer_endpoint, + MessageInTransit* message) override { + CHECK(endpoint); + CHECK(peer_endpoint); + CHECK(message); + + unsigned id = 0; + if (test::IsTestMessage(message, &id) && id >= 1000) { + filtered_messages_->AddMessage(make_scoped_ptr(message)); + return true; + } + + return false; + } + + private: + MessageInTransitQueue* const filtered_messages_; + + DISALLOW_COPY_AND_ASSIGN(TestFilter); +}; + +TEST_F(EndpointRelayerTest, Filter) { + MessageInTransitQueue filtered_messages; + relayer()->SetFilter(make_scoped_ptr(new TestFilter(&filtered_messages))); + + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(2))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1001))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(3))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(4))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1002))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1003))); + EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5))); + + base::WaitableEvent read_event(true, false); + client1b()->SetReadEvent(&read_event); + for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) { + EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); + read_event.Reset(); + } + client1b()->SetReadEvent(nullptr); + + // Check the received messages: We should get "1"-"5". + ASSERT_EQ(5u, client1b()->NumMessages()); + for (unsigned message_id = 1; message_id <= 5; message_id++) { + scoped_ptr<MessageInTransit> read_message = client1b()->PopMessage(); + ASSERT_TRUE(read_message); + test::VerifyTestMessage(read_message.get(), message_id); + } + + // Reset the filter, so we can safely examine |filtered_messages|. + relayer()->SetFilter(nullptr); + + // Note that since "5" was sent after "1003" and it the former was received, + // the latter must have also been "received"/filtered. + ASSERT_EQ(3u, filtered_messages.Size()); + for (unsigned message_id = 1001; message_id <= 1003; message_id++) { + scoped_ptr<MessageInTransit> message = filtered_messages.GetMessage(); + ASSERT_TRUE(message); + test::VerifyTestMessage(message.get(), message_id); + } +} + +// TODO(vtl): Add some "shutdown" tests. + +} // namespace +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/handle_table.h b/third_party/mojo/src/mojo/edk/system/handle_table.h index 9385643..64ad183 100644 --- a/third_party/mojo/src/mojo/edk/system/handle_table.h +++ b/third_party/mojo/src/mojo/edk/system/handle_table.h @@ -21,7 +21,7 @@ class Core; class Dispatcher; class DispatcherTransport; -typedef std::vector<scoped_refptr<Dispatcher>> DispatcherVector; +using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; // Test-only function (defined/used in embedder/test_embedder.cc). Declared here // so it can be friended. @@ -126,7 +126,7 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable { scoped_refptr<Dispatcher> dispatcher; bool busy; }; - typedef base::hash_map<MojoHandle, Entry> HandleToEntryMap; + using HandleToEntryMap = base::hash_map<MojoHandle, Entry>; // Adds the given dispatcher to the handle table, not doing any size checks. MojoHandle AddDispatcherNoSizeCheck( diff --git a/third_party/mojo/src/mojo/edk/system/mapping_table.h b/third_party/mojo/src/mojo/edk/system/mapping_table.h index d2812d8..ed1732d 100644 --- a/third_party/mojo/src/mojo/edk/system/mapping_table.h +++ b/third_party/mojo/src/mojo/edk/system/mapping_table.h @@ -49,8 +49,8 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable { private: friend bool internal::ShutdownCheckNoLeaks(Core*); - typedef base::hash_map<uintptr_t, embedder::PlatformSharedBufferMapping*> - AddressToMappingMap; + using AddressToMappingMap = + base::hash_map<uintptr_t, embedder::PlatformSharedBufferMapping*>; AddressToMappingMap address_to_mapping_map_; DISALLOW_COPY_AND_ASSIGN(MappingTable); diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc index afd7f07..5a81011 100644 --- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc +++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc @@ -92,7 +92,7 @@ embedder::SlaveInfo MasterConnectionManager::Helper::Shutdown() { void MasterConnectionManager::Helper::OnReadMessage( const MessageInTransit::View& message_view, embedder::ScopedPlatformHandleVectorPtr platform_handles) { - if (message_view.type() != MessageInTransit::kTypeConnectionManager) { + if (message_view.type() != MessageInTransit::Type::CONNECTION_MANAGER) { LOG(ERROR) << "Invalid message type " << message_view.type(); FatalError(); // WARNING: This destroys us. return; @@ -120,13 +120,13 @@ void MasterConnectionManager::Helper::OnReadMessage( uint32_t num_bytes = 0; const void* bytes = nullptr; switch (message_view.subtype()) { - case MessageInTransit::kSubtypeConnectionManagerAllowConnect: + case MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT: result = owner_->AllowConnectImpl(process_identifier_, *connection_id); break; - case MessageInTransit::kSubtypeConnectionManagerCancelConnect: + case MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT: result = owner_->CancelConnectImpl(process_identifier_, *connection_id); break; - case MessageInTransit::kSubtypeConnectionManagerConnect: + case MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT: result = owner_->ConnectImpl(process_identifier_, *connection_id, &peer_process_identifier, &platform_handle); // Success acks for "connect" have the peer process identifier as data @@ -143,22 +143,23 @@ void MasterConnectionManager::Helper::OnReadMessage( } scoped_ptr<MessageInTransit> response(new MessageInTransit( - MessageInTransit::kTypeConnectionManagerAck, - result ? MessageInTransit::kSubtypeConnectionManagerAckSuccess - : MessageInTransit::kSubtypeConnectionManagerAckFailure, + MessageInTransit::Type::CONNECTION_MANAGER_ACK, + result ? MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_SUCCESS + : MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE, num_bytes, bytes)); if (platform_handle.is_valid()) { // Only success acks for "connect" *may* have a platform handle attached. DCHECK(result); DCHECK_EQ(message_view.subtype(), - MessageInTransit::kSubtypeConnectionManagerConnect); + MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT); embedder::ScopedPlatformHandleVectorPtr platform_handles( new embedder::PlatformHandleVector()); platform_handles->push_back(platform_handle.release()); - response->SetTransportData( - make_scoped_ptr(new TransportData(platform_handles.Pass()))); + response->SetTransportData(make_scoped_ptr( + new TransportData(platform_handles.Pass(), + raw_channel_->GetSerializedPlatformHandleSize()))); } if (!raw_channel_->WriteMessage(response.Pass())) { diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h index 3210361..d7f06b5 100644 --- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h +++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h @@ -25,7 +25,7 @@ namespace mojo { namespace embedder { class MasterProcessDelegate; -typedef void* SlaveInfo; +using SlaveInfo = void*; } namespace system { diff --git a/third_party/mojo/src/mojo/edk/system/memory.h b/third_party/mojo/src/mojo/edk/system/memory.h index 96cf219..2f1bde4 100644 --- a/third_party/mojo/src/mojo/edk/system/memory.h +++ b/third_party/mojo/src/mojo/edk/system/memory.h @@ -23,25 +23,25 @@ namespace internal { // TODO(vtl): Remove these once we have the C++11 |remove_const|. template <typename T> struct remove_const { - typedef T type; + using type = T; }; template <typename T> struct remove_const<const T> { - typedef T type; + using type = T; }; // Yields |(const) char| if |T| is |(const) void|, else |T|: template <typename T> struct VoidToChar { - typedef T type; + using type = T; }; template <> struct VoidToChar<void> { - typedef char type; + using type = char; }; template <> struct VoidToChar<const void> { - typedef const char type; + using type = const char; }; // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to @@ -84,7 +84,7 @@ struct NullUserPointer {}; template <typename Type> class UserPointer { private: - typedef typename internal::VoidToChar<Type>::type NonVoidType; + using NonVoidType = typename internal::VoidToChar<Type>::type; public: // Instead of explicitly using these constructors, you can often use @@ -243,9 +243,9 @@ class UserPointer { // // TODO(vtl): Possibly, since we're not really being safe, we should just not // copy for Release builds. - typedef UserPointerReader<Type> Reader; - typedef UserPointerWriter<Type> Writer; - typedef UserPointerReaderWriter<Type> ReaderWriter; + using Reader = UserPointerReader<Type>; + using Writer = UserPointerWriter<Type>; + using ReaderWriter = UserPointerReaderWriter<Type>; private: friend class UserPointerReader<Type>; @@ -269,7 +269,7 @@ inline UserPointer<Type> MakeUserPointer(Type* pointer) { template <typename Type> class UserPointerReader { private: - typedef typename internal::remove_const<Type>::type TypeNoConst; + using TypeNoConst = typename internal::remove_const<Type>::type; public: // Note: If |count| is zero, |GetPointer()| will always return null. diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit.cc index 450fc97..4909336 100644 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit.cc +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit.cc @@ -6,6 +6,8 @@ #include <string.h> +#include <ostream> + #include "base/compiler_specific.h" #include "base/logging.h" #include "mojo/edk/system/configuration.h" @@ -14,42 +16,6 @@ namespace mojo { namespace system { -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeEndpointClient; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeEndpoint; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeChannel; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeRawChannel; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeConnectionManager; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type - MessageInTransit::kTypeConnectionManagerAck; - -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeEndpointClientData; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeEndpointClientDataPipeAck; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeChannelAttachAndRunEndpoint; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeChannelRemoveEndpoint; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeChannelRemoveEndpointAck; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeConnectionManagerAllowConnect; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeConnectionManagerCancelConnect; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeConnectionManagerConnect; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeConnectionManagerAckFailure; -STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype - MessageInTransit::kSubtypeConnectionManagerAckSuccess; - STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment; struct MessageInTransit::PrivateStructForCompileAsserts { diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit.h b/third_party/mojo/src/mojo/edk/system/message_in_transit.h index 038a292..7e79c48 100644 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit.h +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <ostream> #include <vector> #include "base/macros.h" @@ -43,46 +44,48 @@ class TransportData; // buffer. class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { public: - typedef uint16_t Type; - // Messages that are forwarded to endpoint clients. - static const Type kTypeEndpointClient = 0; - // Messages that are consumed by the |ChannelEndpoint|. - static const Type kTypeEndpoint = 1; - // Messages that are consumed by the |Channel|. - static const Type kTypeChannel = 2; - // Messages that are consumed by the |RawChannel| (implementation). - static const Type kTypeRawChannel = 3; - // |ConnectionManager| implementations also use |RawChannel|s. - // Messages sent to a |MasterConnectionManager|. - static const Type kTypeConnectionManager = 4; - // Messages sent by a |MasterConnectionManager| (all responses). - static const Type kTypeConnectionManagerAck = 5; - - typedef uint16_t Subtype; - // Subtypes for type |kTypeEndpointClient|: - // Message pipe or data pipe data (etc.). - static const Subtype kSubtypeEndpointClientData = 0; - // Data pipe: consumer -> producer message that data was consumed. Payload is - // |RemoteDataPipeAck|. - static const Subtype kSubtypeEndpointClientDataPipeAck = 1; - // Subtypes for type |kTypeEndpoint|: - // TODO(vtl): Nothing yet. - // Subtypes for type |kTypeChannel|: - static const Subtype kSubtypeChannelAttachAndRunEndpoint = 0; - static const Subtype kSubtypeChannelRemoveEndpoint = 1; - static const Subtype kSubtypeChannelRemoveEndpointAck = 2; - // Subtypes for type |kTypeRawChannel|: - static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0; - // Subtypes for type |kTypeConnectionManager| (the message data is always a - // buffer containing the connection ID): - static const Subtype kSubtypeConnectionManagerAllowConnect = 0; - static const Subtype kSubtypeConnectionManagerCancelConnect = 1; - static const Subtype kSubtypeConnectionManagerConnect = 2; - // Subtypes for type |kTypeConnectionManagerAck| (failure acks never have any - // message contents; success acks for "connect" always have a - // |ProcessIdentifier| as data and *may* have a platform handle attached): - static const Subtype kSubtypeConnectionManagerAckFailure = 0; - static const Subtype kSubtypeConnectionManagerAckSuccess = 1; + enum class Type : uint16_t { + // Messages that are forwarded to endpoint clients. + ENDPOINT_CLIENT = 0, + // Messages that are consumed by the |ChannelEndpoint|. + ENDPOINT = 1, + // Messages that are consumed by the |Channel|. + CHANNEL = 2, + // Messages that are consumed by the |RawChannel| (implementation). + RAW_CHANNEL = 3, + // |ConnectionManager| implementations also use |RawChannel|s. + // Messages sent to a |MasterConnectionManager|. + CONNECTION_MANAGER = 4, + // Messages sent by a |MasterConnectionManager| (all responses). + CONNECTION_MANAGER_ACK = 5, + }; + + enum class Subtype : uint16_t { + // Subtypes for type |Type::ENDPOINT_CLIENT|: + // Message pipe or data pipe data (etc.). + ENDPOINT_CLIENT_DATA = 0, + // Data pipe: consumer -> producer message that data was consumed. Payload + // is |RemoteDataPipeAck|. + ENDPOINT_CLIENT_DATA_PIPE_ACK = 1, + // Subtypes for type |Type::ENDPOINT|: + // TODO(vtl): Nothing yet. + // Subtypes for type |Type::CHANNEL|: + CHANNEL_ATTACH_AND_RUN_ENDPOINT = 0, + CHANNEL_REMOVE_ENDPOINT = 1, + CHANNEL_REMOVE_ENDPOINT_ACK = 2, + // Subtypes for type |Type::RAW_CHANNEL|: + RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES = 0, + // Subtypes for type |Type::CONNECTION_MANAGER| (the message data is always + // a buffer containing the connection ID): + CONNECTION_MANAGER_ALLOW_CONNECT = 0, + CONNECTION_MANAGER_CANCEL_CONNECT = 1, + CONNECTION_MANAGER_CONNECT = 2, + // Subtypes for type |Type::CONNECTION_MANAGER_ACK| (failure acks never have + // any message contents; success acks for "connect" always have a + // |ProcessIdentifier| as data and *may* have a platform handle attached): + CONNECTION_MANAGER_ACK_FAILURE = 0, + CONNECTION_MANAGER_ACK_SUCCESS = 1, + }; // Messages (the header and data) must always be aligned to a multiple of this // quantity (which must be a power of 2). @@ -281,6 +284,20 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { DISALLOW_COPY_AND_ASSIGN(MessageInTransit); }; +// So logging macros and |DCHECK_EQ()|, etc. work. +MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( + std::ostream& out, + MessageInTransit::Type type) { + return out << static_cast<uint16_t>(type); +} + +// So logging macros and |DCHECK_EQ()|, etc. work. +MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( + std::ostream& out, + MessageInTransit::Subtype subtype) { + return out << static_cast<uint16_t>(subtype); +} + } // namespace system } // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h index d81bd2b..f636aef 100644 --- a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue.h @@ -17,13 +17,13 @@ namespace system { // A simple queue for |MessageInTransit|s (that owns its messages). // This class is not thread-safe. -// TODO(vtl): Write tests. class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue { public: MessageInTransitQueue(); ~MessageInTransitQueue(); bool IsEmpty() const { return queue_.empty(); } + size_t Size() const { return queue_.size(); } void AddMessage(scoped_ptr<MessageInTransit> message) { queue_.push_back(message.release()); diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc new file mode 100644 index 0000000..74c7d57 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit_queue_unittest.cc @@ -0,0 +1,91 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/message_in_transit_queue.h" + +#include "mojo/edk/system/message_in_transit_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace system { +namespace { + +TEST(MessageInTransitQueueTest, Basic) { + MessageInTransitQueue queue; + EXPECT_TRUE(queue.IsEmpty()); + + queue.AddMessage(test::MakeTestMessage(1)); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(1u, queue.Size()); + + test::VerifyTestMessage(queue.PeekMessage(), 1); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(1u, queue.Size()); + + queue.AddMessage(test::MakeTestMessage(2)); + queue.AddMessage(test::MakeTestMessage(3)); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(3u, queue.Size()); + + test::VerifyTestMessage(queue.GetMessage().get(), 1); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(2u, queue.Size()); + + test::VerifyTestMessage(queue.PeekMessage(), 2); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(2u, queue.Size()); + + queue.DiscardMessage(); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(1u, queue.Size()); + + test::VerifyTestMessage(queue.GetMessage().get(), 3); + EXPECT_TRUE(queue.IsEmpty()); + EXPECT_EQ(0u, queue.Size()); + + queue.AddMessage(test::MakeTestMessage(4)); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(1u, queue.Size()); + + test::VerifyTestMessage(queue.PeekMessage(), 4); + ASSERT_FALSE(queue.IsEmpty()); + EXPECT_EQ(1u, queue.Size()); + + queue.Clear(); + EXPECT_TRUE(queue.IsEmpty()); + EXPECT_EQ(0u, queue.Size()); +} + +TEST(MessageInTransitQueueTest, Swap) { + MessageInTransitQueue queue1; + MessageInTransitQueue queue2; + + queue1.AddMessage(test::MakeTestMessage(1)); + queue1.AddMessage(test::MakeTestMessage(2)); + queue1.AddMessage(test::MakeTestMessage(3)); + EXPECT_EQ(3u, queue1.Size()); + + queue2.AddMessage(test::MakeTestMessage(4)); + queue2.AddMessage(test::MakeTestMessage(5)); + EXPECT_EQ(2u, queue2.Size()); + + queue1.Swap(&queue2); + EXPECT_EQ(2u, queue1.Size()); + EXPECT_EQ(3u, queue2.Size()); + test::VerifyTestMessage(queue1.GetMessage().get(), 4); + test::VerifyTestMessage(queue1.GetMessage().get(), 5); + EXPECT_TRUE(queue1.IsEmpty()); + + queue1.Swap(&queue2); + EXPECT_TRUE(queue2.IsEmpty()); + + test::VerifyTestMessage(queue1.GetMessage().get(), 1); + test::VerifyTestMessage(queue1.GetMessage().get(), 2); + test::VerifyTestMessage(queue1.GetMessage().get(), 3); + EXPECT_TRUE(queue1.IsEmpty()); +} + +} // namespace +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc new file mode 100644 index 0000000..a8717d6 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.cc @@ -0,0 +1,41 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/message_in_transit_test_utils.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace system { +namespace test { + +scoped_ptr<MessageInTransit> MakeTestMessage(unsigned id) { + return make_scoped_ptr( + new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, + static_cast<uint32_t>(sizeof(id)), &id)); +} + +void VerifyTestMessage(MessageInTransit* message, unsigned id) { + ASSERT_TRUE(message); + EXPECT_EQ(MessageInTransit::Type::ENDPOINT_CLIENT, message->type()); + EXPECT_EQ(MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, + message->subtype()); + EXPECT_EQ(sizeof(id), message->num_bytes()); + EXPECT_EQ(id, *static_cast<const unsigned*>(message->bytes())); +} + +bool IsTestMessage(MessageInTransit* message, unsigned* id) { + if (message->type() != MessageInTransit::Type::ENDPOINT_CLIENT || + message->subtype() != MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA || + message->num_bytes() != sizeof(*id)) + return false; + + *id = *static_cast<const unsigned*>(message->bytes()); + return true; +} + +} // namespace test +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h new file mode 100644 index 0000000..cfcc8cf --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/message_in_transit_test_utils.h @@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ +#define MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ + +#include "base/memory/scoped_ptr.h" +#include "mojo/edk/system/message_in_transit.h" + +namespace mojo { +namespace system { +namespace test { + +// Makes a test message. It will be of type +// |MessageInTransit::Type::ENDPOINT_CLIENT| and subtype +// |MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA|, and contain data +// associated with |id| (so that test messages with different |id|s are +// distinguishable). +scoped_ptr<MessageInTransit> MakeTestMessage(unsigned id); + +// Verifies a test message: ASSERTs that |message| is non-null, and EXPECTs that +// it looks like a message created using |MakeTestMessage(id)| (see above). +void VerifyTestMessage(MessageInTransit* message, unsigned id); + +// Checks if |message| looks like a test message created using +// |MakeTestMessage()|, in which case it returns true and sets |*id|. (Otherwise +// it returns false and leaves |*id| alone.) +bool IsTestMessage(MessageInTransit* message, unsigned* id); + +} // namespace test +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe.cc b/third_party/mojo/src/mojo/edk/system/message_pipe.cc index 796ac64..b17344c 100644 --- a/third_party/mojo/src/mojo/edk/system/message_pipe.cc +++ b/third_party/mojo/src/mojo/edk/system/message_pipe.cc @@ -152,8 +152,8 @@ MojoResult MessagePipe::WriteMessage( return EnqueueMessageNoLock( GetPeerPort(port), make_scoped_ptr(new MessageInTransit( - MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, num_bytes, bytes)), + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, bytes)), transports); } @@ -318,7 +318,7 @@ MojoResult MessagePipe::EnqueueMessageNoLock( DCHECK(port == 0 || port == 1); DCHECK(message); - DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpointClient); + DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); DCHECK(endpoints_[GetPeerPort(port)]); // The destination port need not be open, unlike the source port. @@ -352,7 +352,7 @@ MojoResult MessagePipe::AttachTransportsNoLock( for (size_t i = 0; i < transports->size(); i++) { if (!(*transports)[i].is_valid()) continue; - if ((*transports)[i].GetType() == Dispatcher::kTypeMessagePipe) { + if ((*transports)[i].GetType() == Dispatcher::Type::MESSAGE_PIPE) { MessagePipeDispatcherTransport mp_transport((*transports)[i]); if (mp_transport.GetMessagePipe() == this) { // The other case should have been disallowed by |Core|. (Note: |port| diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc index a6733dbe..95faede 100644 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.cc @@ -68,7 +68,7 @@ void MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe, } Dispatcher::Type MessagePipeDispatcher::GetType() const { - return kTypeMessagePipe; + return Type::MESSAGE_PIPE; } // static @@ -223,7 +223,8 @@ bool MessagePipeDispatcher::EndSerializeAndCloseImplNoLock( MessagePipeDispatcherTransport::MessagePipeDispatcherTransport( DispatcherTransport transport) : DispatcherTransport(transport) { - DCHECK_EQ(message_pipe_dispatcher()->GetType(), Dispatcher::kTypeMessagePipe); + DCHECK_EQ(message_pipe_dispatcher()->GetType(), + Dispatcher::Type::MESSAGE_PIPE); } } // namespace system diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc index 760aced..55aedb3 100644 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc @@ -43,7 +43,7 @@ TEST(MessagePipeDispatcherTest, Basic) { for (unsigned i = 0; i < 2; i++) { scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher( MessagePipeDispatcher::kDefaultCreateOptions)); - EXPECT_EQ(Dispatcher::kTypeMessagePipe, d0->GetType()); + EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, d0->GetType()); scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher( MessagePipeDispatcher::kDefaultCreateOptions)); { diff --git a/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 1570007..ed2f30f 100644 --- a/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -240,7 +240,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { CHECK_EQ(read_buffer, std::string("go 1")); CHECK_EQ(num_dispatchers, 1u); - CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypeSharedBuffer); + CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::Type::SHARED_BUFFER); scoped_refptr<SharedBufferDispatcher> dispatcher( static_cast<SharedBufferDispatcher*>(dispatchers[0].get())); @@ -424,7 +424,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { CHECK_GT(num_handles, 0); for (int i = 0; i < num_handles; ++i) { - CHECK_EQ(dispatchers[i]->GetType(), Dispatcher::kTypePlatformHandle); + CHECK_EQ(dispatchers[i]->GetType(), Dispatcher::Type::PLATFORM_HANDLE); scoped_refptr<PlatformHandleDispatcher> dispatcher( static_cast<PlatformHandleDispatcher*>(dispatchers[i].get())); @@ -448,13 +448,7 @@ class MultiprocessMessagePipeTestWithPipeCount : public test::MultiprocessMessagePipeTestBase, public testing::WithParamInterface<size_t> {}; -#if defined(OS_MACOSX) -// http://crbug.com/488260 -TEST_P(MultiprocessMessagePipeTestWithPipeCount, - DISABLED_PlatformHandlePassing) { -#else TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { -#endif base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); @@ -518,7 +512,7 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { #if defined(OS_POSIX) && !defined(OS_ANDROID) INSTANTIATE_TEST_CASE_P(PipeCount, MultiprocessMessagePipeTestWithPipeCount, - testing::Values(1u, 128u, 255u)); + testing::Values(1u, 128u, 140u)); #endif } // namespace diff --git a/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc b/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc index 89c4e60..298355cf 100644 --- a/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/options_validation_unittest.cc @@ -16,7 +16,7 @@ namespace { // Declare a test options struct just as we do in actual public headers. -typedef uint32_t TestOptionsFlags; +using TestOptionsFlags = uint32_t; static_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); struct MOJO_ALIGNAS(8) TestOptions { diff --git a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc index f064c67..94e10e2 100644 --- a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.cc @@ -32,7 +32,7 @@ embedder::ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() { } Dispatcher::Type PlatformHandleDispatcher::GetType() const { - return kTypePlatformHandle; + return Type::PLATFORM_HANDLE; } // static diff --git a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc index dae53b4..3b37b72 100644 --- a/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher_unittest.cc @@ -39,7 +39,7 @@ TEST(PlatformHandleDispatcherTest, Basic) { scoped_refptr<PlatformHandleDispatcher> dispatcher( new PlatformHandleDispatcher(h.Pass())); EXPECT_FALSE(h.is_valid()); - EXPECT_EQ(Dispatcher::kTypePlatformHandle, dispatcher->GetType()); + EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType()); h = dispatcher->PassPlatformHandle().Pass(); EXPECT_TRUE(h.is_valid()); @@ -79,7 +79,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) { DispatcherTransport transport( test::DispatcherTryStartTransport(dispatcher.get())); EXPECT_TRUE(transport.is_valid()); - EXPECT_EQ(Dispatcher::kTypePlatformHandle, transport.GetType()); + EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, transport.GetType()); EXPECT_FALSE(transport.IsBusy()); scoped_refptr<Dispatcher> generic_dispatcher = @@ -90,7 +90,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) { EXPECT_TRUE(dispatcher->HasOneRef()); dispatcher = nullptr; - ASSERT_EQ(Dispatcher::kTypePlatformHandle, generic_dispatcher->GetType()); + ASSERT_EQ(Dispatcher::Type::PLATFORM_HANDLE, generic_dispatcher->GetType()); dispatcher = static_cast<PlatformHandleDispatcher*>(generic_dispatcher.get()); fp = mojo::test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(), diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel.cc b/third_party/mojo/src/mojo/edk/system/raw_channel.cc index 4cf7c02..2dd4cba 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel.cc @@ -318,7 +318,7 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { return; // |this| may have been destroyed in |CallOnError()|. } - if (message_view.type() == MessageInTransit::kTypeRawChannel) { + if (message_view.type() == MessageInTransit::Type::RAW_CHANNEL) { if (!OnReadMessageForRawChannel(message_view)) { CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); return; // |this| may have been destroyed in |CallOnError()|. diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc index c2b2ef0..c14fa6b 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_posix.cc @@ -134,16 +134,16 @@ void RawChannelPosix::EnqueueMessageNoLock( embedder::kPlatformChannelMaxNumHandles; i += embedder::kPlatformChannelMaxNumHandles) { scoped_ptr<MessageInTransit> fd_message(new MessageInTransit( - MessageInTransit::kTypeRawChannel, - MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles, 0, - nullptr)); + MessageInTransit::Type::RAW_CHANNEL, + MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES, + 0, nullptr)); embedder::ScopedPlatformHandleVectorPtr fds( new embedder::PlatformHandleVector( platform_handles->begin() + i, platform_handles->begin() + i + embedder::kPlatformChannelMaxNumHandles)); - fd_message->SetTransportData( - make_scoped_ptr(new TransportData(fds.Pass()))); + fd_message->SetTransportData(make_scoped_ptr( + new TransportData(fds.Pass(), GetSerializedPlatformHandleSize()))); RawChannel::EnqueueMessageNoLock(fd_message.Pass()); } @@ -158,10 +158,10 @@ void RawChannelPosix::EnqueueMessageNoLock( bool RawChannelPosix::OnReadMessageForRawChannel( const MessageInTransit::View& message_view) { - DCHECK_EQ(message_view.type(), MessageInTransit::kTypeRawChannel); + DCHECK_EQ(message_view.type(), MessageInTransit::Type::RAW_CHANNEL); if (message_view.subtype() == - MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles) { + MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES) { // We don't need to do anything. |RawChannel| won't extract the platform // handles, and they'll be accumulated in |Read()|. return true; diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc index 87b9560..6935845 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_unittest.cc @@ -45,8 +45,8 @@ scoped_ptr<MessageInTransit> MakeTestMessage(uint32_t num_bytes) { 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::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, + new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, bytes.empty() ? nullptr : &bytes[0])); } @@ -837,11 +837,12 @@ TEST_F(RawChannelTest, MAYBE_ReadWritePlatformHandles) { platform_handles->push_back( mojo::test::PlatformHandleFromFILE(fp2.Pass()).release()); - scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, sizeof(kHello), kHello)); - message->SetTransportData( - make_scoped_ptr(new TransportData(platform_handles.Pass()))); + scoped_ptr<MessageInTransit> message( + new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, + sizeof(kHello), kHello)); + message->SetTransportData(make_scoped_ptr(new TransportData( + platform_handles.Pass(), rc_write->GetSerializedPlatformHandleSize()))); EXPECT_TRUE(rc_write->WriteMessage(message.Pass())); } diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc index a422c9e..cd9bfdf 100644 --- a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc +++ b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc @@ -40,8 +40,8 @@ class VistaOrHigherFunctions { } private: - typedef BOOL(WINAPI* SetFileCompletionNotificationModesFunc)(HANDLE, UCHAR); - typedef BOOL(WINAPI* CancelIoExFunc)(HANDLE, LPOVERLAPPED); + using SetFileCompletionNotificationModesFunc = BOOL(WINAPI*)(HANDLE, UCHAR); + using CancelIoExFunc = BOOL(WINAPI*)(HANDLE, LPOVERLAPPED); bool is_vista_or_higher_; SetFileCompletionNotificationModesFunc diff --git a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc index f61554a..8e21620 100644 --- a/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc +++ b/third_party/mojo/src/mojo/edk/system/remote_consumer_data_pipe_impl.cc @@ -27,11 +27,11 @@ bool ValidateIncomingMessage(size_t element_num_bytes, size_t consumer_num_bytes, const MessageInTransit* message) { // We should only receive endpoint client messages. - DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpointClient); + DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); // But we should check the subtype; only take data pipe acks. if (message->subtype() != - MessageInTransit::kSubtypeEndpointClientDataPipeAck) { + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK) { LOG(WARNING) << "Received message of unexpected subtype: " << message->subtype(); return false; @@ -149,8 +149,8 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerWriteData( size_t message_num_bytes = std::min(max_message_num_bytes, num_bytes_to_write - offset); scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, static_cast<uint32_t>(message_num_bytes), elements.At(offset))); if (!channel_endpoint_->EnqueueMessage(message.Pass())) { Disconnect(); @@ -228,8 +228,8 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerEndWriteData( size_t message_num_bytes = std::min(max_message_num_bytes, num_bytes_written - offset); scoped_ptr<MessageInTransit> message(new MessageInTransit( - MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientData, + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, static_cast<uint32_t>(message_num_bytes), buffer_.get() + offset)); if (!channel_endpoint_->EnqueueMessage(message.Pass())) { set_producer_two_phase_max_num_bytes_written(0); diff --git a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h index e660a2e..dea0b18 100644 --- a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h +++ b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_ack.h @@ -10,7 +10,7 @@ namespace mojo { namespace system { -// Data payload for |MessageInTransit::kSubtypeEndpointClientDataPipeAck| +// Data payload for |MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK| // messages. struct RemoteDataPipeAck { uint32_t num_bytes_consumed; diff --git a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc index 7efd40a..40d2f6f 100644 --- a/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/remote_data_pipe_impl_unittest.cc @@ -226,7 +226,8 @@ TEST_F(RemoteDataPipeImplTest, SendConsumerWithClosedProducer) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeDataPipeConsumer, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, + read_dispatchers[0]->GetType()); consumer = static_cast<DataPipeConsumerDispatcher*>(read_dispatchers[0].get()); read_dispatchers.clear(); diff --git a/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc index 1860c23..6d22da7 100644 --- a/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/remote_message_pipe_unittest.cc @@ -674,7 +674,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); // Add the waiter now, before it becomes readable to avoid a race. @@ -848,7 +848,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); // |dispatcher| should already be readable and not writable. @@ -982,7 +982,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeSharedBuffer, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, read_dispatchers[0]->GetType()); dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get()); // Make another mapping. @@ -1101,7 +1101,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypePlatformHandle, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, read_dispatchers[0]->GetType()); dispatcher = static_cast<PlatformHandleDispatcher*>(read_dispatchers[0].get()); @@ -1238,7 +1238,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); read_dispatchers.clear(); @@ -1295,7 +1295,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); - EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); + EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_dispatchers[0]->GetType()); dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); read_dispatchers.clear(); diff --git a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc b/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc index 3c1a0b2..8d7fa26 100644 --- a/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc +++ b/third_party/mojo/src/mojo/edk/system/remote_producer_data_pipe_impl.cc @@ -29,10 +29,10 @@ bool ValidateIncomingMessage(size_t element_num_bytes, size_t current_num_bytes, const MessageInTransit* message) { // We should only receive endpoint client messages. - DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpointClient); + DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); // But we should check the subtype; only take data messages. - if (message->subtype() != MessageInTransit::kSubtypeEndpointClientData) { + if (message->subtype() != MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA) { LOG(WARNING) << "Received message of unexpected subtype: " << message->subtype(); return false; @@ -444,10 +444,10 @@ void RemoteProducerDataPipeImpl::MarkDataAsConsumed(size_t num_bytes) { RemoteDataPipeAck ack_data = {}; ack_data.num_bytes_consumed = static_cast<uint32_t>(num_bytes); - scoped_ptr<MessageInTransit> message( - new MessageInTransit(MessageInTransit::kTypeEndpointClient, - MessageInTransit::kSubtypeEndpointClientDataPipeAck, - static_cast<uint32_t>(sizeof(ack_data)), &ack_data)); + scoped_ptr<MessageInTransit> message(new MessageInTransit( + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK, + static_cast<uint32_t>(sizeof(ack_data)), &ack_data)); if (!channel_endpoint_->EnqueueMessage(message.Pass())) Disconnect(); } diff --git a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc index db823d5..653c507 100644 --- a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.cc @@ -82,7 +82,7 @@ MojoResult SharedBufferDispatcher::Create( } Dispatcher::Type SharedBufferDispatcher::GetType() const { - return kTypeSharedBuffer; + return Type::SHARED_BUFFER; } // static diff --git a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index 29dcb57..42446c5 100644 --- a/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -119,7 +119,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); ASSERT_TRUE(dispatcher); - EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType()); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); // Make a couple of mappings. scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1; @@ -166,7 +166,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( NullUserPointer(), &dispatcher2)); ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); @@ -194,7 +194,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( MakeUserPointer(&options[i]), &dispatcher2)); ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); } diff --git a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc index b8e57e9..58f1458 100644 --- a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc @@ -60,7 +60,7 @@ class MockSimpleDispatcher : public SimpleDispatcher { HandleSignalsStateChangedNoLock(); } - Type GetType() const override { return kTypeUnknown; } + Type GetType() const override { return Type::UNKNOWN; } private: friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc index dfe69d4..d59bd82 100644 --- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc +++ b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc @@ -150,8 +150,8 @@ void SlaveConnectionManager::AllowConnectOnPrivateThread( DVLOG(1) << "Sending AllowConnect: connection ID " << connection_id.ToString(); if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::kTypeConnectionManager, - MessageInTransit::kSubtypeConnectionManagerAllowConnect, + MessageInTransit::Type::CONNECTION_MANAGER, + MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT, sizeof(connection_id), &connection_id)))) { // Don't tear things down; possibly we'll still read some messages. *result = false; @@ -175,8 +175,8 @@ void SlaveConnectionManager::CancelConnectOnPrivateThread( DVLOG(1) << "Sending CancelConnect: connection ID " << connection_id.ToString(); if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::kTypeConnectionManager, - MessageInTransit::kSubtypeConnectionManagerCancelConnect, + MessageInTransit::Type::CONNECTION_MANAGER, + MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT, sizeof(connection_id), &connection_id)))) { // Don't tear things down; possibly we'll still read some messages. *result = false; @@ -203,8 +203,8 @@ void SlaveConnectionManager::ConnectOnPrivateThread( DVLOG(1) << "Sending Connect: connection ID " << connection_id.ToString(); if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( - MessageInTransit::kTypeConnectionManager, - MessageInTransit::kSubtypeConnectionManagerConnect, + MessageInTransit::Type::CONNECTION_MANAGER, + MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT, sizeof(connection_id), &connection_id)))) { // Don't tear things down; possibly we'll still read some messages. *result = false; @@ -232,19 +232,19 @@ void SlaveConnectionManager::OnReadMessage( // Unsolicited message. CHECK_NE(awaiting_ack_type_, NOT_AWAITING_ACK); // Bad message type. - CHECK_EQ(message_view.type(), MessageInTransit::kTypeConnectionManagerAck); + CHECK_EQ(message_view.type(), MessageInTransit::Type::CONNECTION_MANAGER_ACK); size_t num_bytes = message_view.num_bytes(); size_t num_platform_handles = platform_handles ? platform_handles->size() : 0; if (message_view.subtype() == - MessageInTransit::kSubtypeConnectionManagerAckFailure) { + MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_FAILURE) { // Failure acks never have any contents. CHECK_EQ(num_bytes, 0u); CHECK_EQ(num_platform_handles, 0u); // Leave |*ack_result_| false. } else if (message_view.subtype() == - MessageInTransit::kSubtypeConnectionManagerAckSuccess) { + MessageInTransit::Subtype::CONNECTION_MANAGER_ACK_SUCCESS) { if (awaiting_ack_type_ == AWAITING_ACCEPT_CONNECT_ACK || awaiting_ack_type_ == AWAITING_CANCEL_CONNECT_ACK) { // Success acks for "accept/cancel connect" have no contents. diff --git a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc new file mode 100644 index 0000000..51d2a58 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.cc @@ -0,0 +1,78 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/test_channel_endpoint_client.h" + +#include "base/synchronization/waitable_event.h" +#include "mojo/edk/system/message_in_transit.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace system { +namespace test { + +TestChannelEndpointClient::TestChannelEndpointClient() + : port_(0), read_event_(nullptr) { +} + +void TestChannelEndpointClient::Init(unsigned port, ChannelEndpoint* endpoint) { + base::AutoLock locker(lock_); + ASSERT_EQ(0u, port_); + ASSERT_FALSE(endpoint_); + port_ = port; + endpoint_ = endpoint; +} + +bool TestChannelEndpointClient::IsDetached() const { + base::AutoLock locker(lock_); + return !endpoint_; +} + +size_t TestChannelEndpointClient::NumMessages() const { + base::AutoLock locker(lock_); + return messages_.Size(); +} + +scoped_ptr<MessageInTransit> TestChannelEndpointClient::PopMessage() { + base::AutoLock locker(lock_); + if (messages_.IsEmpty()) + return nullptr; + return messages_.GetMessage(); +} + +void TestChannelEndpointClient::SetReadEvent(base::WaitableEvent* read_event) { + base::AutoLock locker(lock_); + read_event_ = read_event; +} + +bool TestChannelEndpointClient::OnReadMessage(unsigned port, + MessageInTransit* message) { + base::AutoLock locker(lock_); + + EXPECT_EQ(port_, port); + EXPECT_TRUE(endpoint_); + messages_.AddMessage(make_scoped_ptr(message)); + + if (read_event_) + read_event_->Signal(); + + return true; +} + +void TestChannelEndpointClient::OnDetachFromChannel(unsigned port) { + EXPECT_EQ(port_, port); + + base::AutoLock locker(lock_); + ASSERT_TRUE(endpoint_); + endpoint_->DetachFromClient(); + endpoint_ = nullptr; +} + +TestChannelEndpointClient::~TestChannelEndpointClient() { + EXPECT_FALSE(endpoint_); +} + +} // namespace test +} // namespace system +} // namespace mojo diff --git a/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h new file mode 100644 index 0000000..f708d61 --- /dev/null +++ b/third_party/mojo/src/mojo/edk/system/test_channel_endpoint_client.h @@ -0,0 +1,69 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ +#define MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "mojo/edk/system/channel_endpoint.h" +#include "mojo/edk/system/channel_endpoint_client.h" +#include "mojo/edk/system/message_in_transit_queue.h" + +namespace base { +class WaitableEvent; +} + +namespace mojo { +namespace system { +namespace test { + +class TestChannelEndpointClient : public ChannelEndpointClient { + public: + TestChannelEndpointClient(); + + // Initializes with the given port and endpoint. + void Init(unsigned port, ChannelEndpoint* endpoint); + + // Returns true if we're detached from the |ChannelEndpoint|. + bool IsDetached() const; + + // Gets the current number of messages received (but not dequeued). + size_t NumMessages() const; + + // Gets/removes a message that was received (|NumMessages()| must be + // non-zero), in FIFO order. + scoped_ptr<MessageInTransit> PopMessage(); + + // Sets an event to signal when we receive a message. (|read_event| must live + // until this object is destroyed or the read event is reset to null.) + void SetReadEvent(base::WaitableEvent* read_event); + + // |ChannelEndpointClient| implementation: + bool OnReadMessage(unsigned port, MessageInTransit* message) override; + void OnDetachFromChannel(unsigned port) override; + + private: + ~TestChannelEndpointClient() override; + + mutable base::Lock lock_; // Protects the members below. + + unsigned port_; + scoped_refptr<ChannelEndpoint> endpoint_; + + MessageInTransitQueue messages_; + + // Event to trigger if we read a message (may be null). + base::WaitableEvent* read_event_; + + DISALLOW_COPY_AND_ASSIGN(TestChannelEndpointClient); +}; + +} // namespace test +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ diff --git a/third_party/mojo/src/mojo/edk/system/transport_data.cc b/third_party/mojo/src/mojo/edk/system/transport_data.cc index d388151..783a51d 100644 --- a/third_party/mojo/src/mojo/edk/system/transport_data.cc +++ b/third_party/mojo/src/mojo/edk/system/transport_data.cc @@ -62,7 +62,8 @@ struct TransportData::PrivateStructForCompileAsserts { }; TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, - Channel* channel) { + Channel* channel) + : buffer_size_() { DCHECK(dispatchers); DCHECK(channel); @@ -136,8 +137,8 @@ TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, for (size_t i = 0; i < num_handles; i++) { Dispatcher* dispatcher = (*dispatchers)[i].get(); if (!dispatcher) { - static_assert(Dispatcher::kTypeUnknown == 0, - "Value of Dispatcher::kTypeUnknown must be 0"); + static_assert(static_cast<int32_t>(Dispatcher::Type::UNKNOWN) == 0, + "Value of Dispatcher::Type::UNKNOWN must be 0"); continue; } @@ -165,7 +166,7 @@ TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, #endif } else { // Nothing to do on failure, since |buffer_| was cleared, and - // |kTypeUnknown| is zero. The handle was simply closed. + // |Type::UNKNOWN| is zero. The handle was simply closed. LOG(ERROR) << "Failed to serialize handle to remote message pipe"; } @@ -192,13 +193,18 @@ TransportData::TransportData(scoped_ptr<DispatcherVector> dispatchers, } TransportData::TransportData( - embedder::ScopedPlatformHandleVectorPtr platform_handles) - : buffer_size_(sizeof(Header)), platform_handles_(platform_handles.Pass()) { + embedder::ScopedPlatformHandleVectorPtr platform_handles, + size_t serialized_platform_handle_size) + : buffer_size_(), platform_handles_(platform_handles.Pass()) { + buffer_size_ = MessageInTransit::RoundUpMessageAlignment( + sizeof(Header) + + platform_handles_->size() * serialized_platform_handle_size); buffer_.reset(static_cast<char*>( base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment))); memset(buffer_.get(), 0, buffer_size_); Header* header = reinterpret_cast<Header*>(buffer_.get()); + header->platform_handle_table_offset = static_cast<uint32_t>(sizeof(Header)); header->num_platform_handles = static_cast<uint32_t>(platform_handles_->size()); } diff --git a/third_party/mojo/src/mojo/edk/system/transport_data.h b/third_party/mojo/src/mojo/edk/system/transport_data.h index 1258f49..7cb25d3 100644 --- a/third_party/mojo/src/mojo/edk/system/transport_data.h +++ b/third_party/mojo/src/mojo/edk/system/transport_data.h @@ -96,7 +96,8 @@ class MOJO_SYSTEM_IMPL_EXPORT TransportData { // |Dispatcher|s. (|Header| will be present, and zero except for // |num_platform_handles|, and |platform_handle_table_offset| if necessary.) explicit TransportData( - embedder::ScopedPlatformHandleVectorPtr platform_handles); + embedder::ScopedPlatformHandleVectorPtr platform_handles, + size_t serialized_platform_handle_size); ~TransportData(); @@ -161,7 +162,8 @@ class MOJO_SYSTEM_IMPL_EXPORT TransportData { }; struct HandleTableEntry { - int32_t type; // From |Dispatcher::Type| (|kTypeUnknown| for "invalid"). + // TODO(vtl): Should I make |Dispatcher::Type| an |int32_t| enum class? + int32_t type; // From |Dispatcher::Type| (|UNKNOWN| for "invalid"). uint32_t offset; // Relative to the start of the "secondary buffer". uint32_t size; // (Not including any padding.) uint32_t unused; diff --git a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc b/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc index 93496fb..4fe170c 100644 --- a/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc +++ b/third_party/mojo/src/mojo/edk/test/multiprocess_test_helper_unittest.cc @@ -40,7 +40,7 @@ bool ReadByte(const embedder::PlatformHandle& handle, char* c) { return bytes_read == 1; } -typedef testing::Test MultiprocessTestHelperTest; +using MultiprocessTestHelperTest = testing::Test; #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION index 6a5d5c0..3317b69 100644 --- a/third_party/mojo/src/mojo/public/VERSION +++ b/third_party/mojo/src/mojo/public/VERSION @@ -1 +1 @@ -1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
\ No newline at end of file +c2ace8a3e256e2f78e2ec1f7e1001ef47e2f5983
\ No newline at end of file diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc index e6e38de..65a23fa 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc +++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc @@ -499,8 +499,7 @@ TEST(UnionTest, Validation_UnionsInStruct) { Serialize_(small_struct.Pass(), &buf, &data); void* raw_buf = buf.Leak(); - mojo::internal::BoundsChecker bounds_checker(data, - static_cast<uint32_t>(size), 0); + mojo::internal::BoundsChecker bounds_checker(data, size, 0); EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker)); free(raw_buf); } @@ -520,8 +519,7 @@ TEST(UnionTest, Validation_PodUnionInStruct_Failure) { data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100); void* raw_buf = buf.Leak(); - mojo::internal::BoundsChecker bounds_checker(data, - static_cast<uint32_t>(size), 0); + mojo::internal::BoundsChecker bounds_checker(data, size, 0); EXPECT_FALSE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker)); free(raw_buf); } @@ -539,8 +537,7 @@ TEST(UnionTest, Validation_NullUnion_Failure) { internal::SmallStructNonNullableUnion_Data::New(&buf); void* raw_buf = buf.Leak(); - mojo::internal::BoundsChecker bounds_checker(data, - static_cast<uint32_t>(size), 0); + mojo::internal::BoundsChecker bounds_checker(data, size, 0); EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate( raw_buf, &bounds_checker)); free(raw_buf); @@ -558,8 +555,7 @@ TEST(UnionTest, Validation_NullableUnion) { Serialize_(small_struct.Pass(), &buf, &data); void* raw_buf = buf.Leak(); - mojo::internal::BoundsChecker bounds_checker(data, - static_cast<uint32_t>(size), 0); + mojo::internal::BoundsChecker bounds_checker(data, size, 0); EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker)); free(raw_buf); } diff --git a/third_party/mojo/src/mojo/public/cpp/system/macros.h b/third_party/mojo/src/mojo/public/cpp/system/macros.h index 9836e99f..ecc42fb 100644 --- a/third_party/mojo/src/mojo/public/cpp/system/macros.h +++ b/third_party/mojo/src/mojo/public/cpp/system/macros.h @@ -50,7 +50,8 @@ char(&ArraySizeHelper(const T(&array)[N]))[N]; // more commonly, pass it to a function that takes it as a reference argument -- // probably an STL function.) This macro makes MSVC do the right thing. See // http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more -// information. Use like: +// information. This workaround does not appear to be necessary after VS2015. +// Use like: // // In .h file: // struct Foo { @@ -59,7 +60,7 @@ char(&ArraySizeHelper(const T(&array)[N]))[N]; // // In .cc file: // STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar; -#if defined(_MSC_VER) +#if defined(_MSC_VER) && _MSC_VER < 1900 #define MOJO_STATIC_CONST_MEMBER_DEFINITION __declspec(selectany) #else #define MOJO_STATIC_CONST_MEMBER_DEFINITION diff --git a/third_party/mojo/src/mojo/public/dart/BUILD.gn b/third_party/mojo/src/mojo/public/dart/BUILD.gn index 7305582..c36245c 100644 --- a/third_party/mojo/src/mojo/public/dart/BUILD.gn +++ b/third_party/mojo/src/mojo/public/dart/BUILD.gn @@ -20,6 +20,10 @@ dart_mojo_sdk_sources = [ "lib/src/struct.dart", "lib/src/stub.dart", "lib/src/types.dart", + "sdk_ext/internal.dart", + "sdk_ext/src/handle_watcher.dart", + "sdk_ext/src/natives.dart", + "sdk_ext/src/timer_queue.dart", ] dartzip_package("dart") { diff --git a/third_party/mojo/src/mojo/public/dart/lib/internal.dart b/third_party/mojo/src/mojo/public/dart/sdk_ext/internal.dart index 4239df2..4239df2 100644 --- a/third_party/mojo/src/mojo/public/dart/lib/internal.dart +++ b/third_party/mojo/src/mojo/public/dart/sdk_ext/internal.dart diff --git a/third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/handle_watcher.dart index 4aeeaff..4aeeaff 100644 --- a/third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart +++ b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/handle_watcher.dart diff --git a/third_party/mojo/src/mojo/public/dart/lib/src/natives.dart b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/natives.dart index a46ddd6..a46ddd6 100644 --- a/third_party/mojo/src/mojo/public/dart/lib/src/natives.dart +++ b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/natives.dart diff --git a/third_party/mojo/src/mojo/public/dart/lib/src/timer_queue.dart b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/timer_queue.dart index 01c2493..01c2493 100644 --- a/third_party/mojo/src/mojo/public/dart/lib/src/timer_queue.dart +++ b/third_party/mojo/src/mojo/public/dart/sdk_ext/src/timer_queue.dart diff --git a/third_party/mojo/src/mojo/public/go/bindings/decoder.go b/third_party/mojo/src/mojo/public/go/bindings/decoder.go index dac5110..2a0cd65 100644 --- a/third_party/mojo/src/mojo/public/go/bindings/decoder.go +++ b/third_party/mojo/src/mojo/public/go/bindings/decoder.go @@ -63,20 +63,20 @@ func (d *Decoder) popState() { } } -func (d *Decoder) pushState(header DataHeader, elementBitSize uint32) error { +func (d *Decoder) pushState(header DataHeader, checkElements bool) error { oldEnd := d.end if err := d.claimData(int(header.Size - dataHeaderSize)); err != nil { return err } elements := uint32(0) - if elementBitSize != 0 { + if checkElements { elements = header.ElementsOrVersion } d.stateStack = append(d.stateStack, encodingState{ - offset: oldEnd, - limit: d.end, - elementBitSize: elementBitSize, - elements: elements, + offset: oldEnd, + limit: d.end, + elements: elements, + checkElements: checkElements, }) return nil } @@ -104,7 +104,7 @@ func (d *Decoder) StartArray(elementBitSize uint32) (uint32, error) { fmt.Sprintf("data header size(%d) should be at least %d", got, want), } } - if err := d.pushState(header, elementBitSize); err != nil { + if err := d.pushState(header, true); err != nil { return 0, err } return header.ElementsOrVersion, nil @@ -123,7 +123,7 @@ func (d *Decoder) StartMap() error { fmt.Sprintf("invalid map header: %v", header), } } - if err := d.pushState(header, 0); err != nil { + if err := d.pushState(header, false); err != nil { return err } return nil @@ -143,25 +143,51 @@ func (d *Decoder) StartStruct() (DataHeader, error) { fmt.Sprintf("data header size(%d) should be at least %d", header.Size, dataHeaderSize), } } - if err := d.pushState(header, 0); err != nil { + if err := d.pushState(header, false); err != nil { return DataHeader{}, err } return header, nil } -// StartUnion starts decoding a union and reads its header. -// Returns the read data header. The caller should check if it is valid. -// Note: it doesn't read the data field. -func (d *Decoder) StartUnion() (DataHeader, error) { - header, err := d.readDataHeader() - if err != nil { - return DataHeader{}, err +// StartNestedUnion starts decoding a union. +// Note: it doesn't read a pointer to the encoded struct or the union header. +// Call |Finish()| after reading the header and data. +func (d *Decoder) StartNestedUnion() error { + // We have to trick pushState into claiming 16 bytes. + header := DataHeader{uint32(24), uint32(0)} + if err := d.pushState(header, false); err != nil { + return err } + return nil +} - if err := d.pushState(header, 0); err != nil { - return DataHeader{}, err +// ReadUnionHeader reads the union header and returns the union's size and tag. +func (d *Decoder) ReadUnionHeader() (uint32, uint32, error) { + if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil { + return 0, 0, err } - return header, nil + d.state().alignOffsetToBytes() + d.state().offset = align(d.state().offset, 8) + size := binary.LittleEndian.Uint32(d.buf[d.state().offset:]) + tag := binary.LittleEndian.Uint32(d.buf[d.state().offset+4:]) + d.state().offset += 8 + if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil { + return 0, 0, err + } + return size, tag, nil +} + +// FinishReadingUnionValue should be called after the union value has been read +// in order to indicate to move the decoder past the union value field. +func (d *Decoder) FinishReadingUnionValue() { + d.state().offset = align(d.state().offset, 8) + d.state().alignOffsetToBytes() +} + +// SkipNullUnionValue skips the union's null value. +func (d *Decoder) SkipNullUnionValue() { + d.state().offset += 8 + d.state().elementsProcessed += 1 } func (d *Decoder) readDataHeader() (DataHeader, error) { @@ -182,7 +208,7 @@ func (d *Decoder) Finish() error { if d.state() == nil { return fmt.Errorf("state stack is empty") } - if d.state().elementBitSize != 0 && d.state().elementsProcessed != d.state().elements { + if d.state().checkElements && d.state().elementsProcessed != d.state().elements { return fmt.Errorf("unexpected number of elements read: defined in header %d, but read %d", d.state().elements, d.state().elementsProcessed) } d.popState() diff --git a/third_party/mojo/src/mojo/public/go/bindings/encoder.go b/third_party/mojo/src/mojo/public/go/bindings/encoder.go index 918c883..45da98f 100644 --- a/third_party/mojo/src/mojo/public/go/bindings/encoder.go +++ b/third_party/mojo/src/mojo/public/go/bindings/encoder.go @@ -24,9 +24,6 @@ type encodingState struct { // one-level value. limit int - // Element size in bits of the current one-level array, 0 for other types. - elementBitSize uint32 - // Number of elements declared in the data header for the current one-level // value. elements uint32 @@ -34,6 +31,9 @@ type encodingState struct { // Number of elements already encoded/decoded of the current one-level // value. elementsProcessed uint32 + + // Whether the number of elements processed should be checked. + checkElements bool } func (s *encodingState) alignOffsetToBytes() { @@ -74,10 +74,7 @@ func ensureElementBitSizeAndCapacity(state *encodingState, bitSize uint32) error if state == nil { return fmt.Errorf("empty state stack") } - if state.elementBitSize != 0 && state.elementBitSize != bitSize { - return fmt.Errorf("unexpected element bit size: expected %d, but got %d", state.elementBitSize, bitSize) - } - if state.elementBitSize != 0 && state.elementsProcessed >= state.elements { + if state.checkElements && state.elementsProcessed >= state.elements { return fmt.Errorf("can't process more than elements defined in header(%d)", state.elements) } byteSize := bytesForBits(uint64(state.bitOffset + bitSize)) @@ -109,20 +106,19 @@ func (e *Encoder) popState() { } } -func (e *Encoder) pushState(header DataHeader, elementBitSize uint32) { +func (e *Encoder) pushState(header DataHeader, checkElements bool) { oldEnd := e.end e.claimData(align(int(header.Size), defaultAlignment)) elements := uint32(0) - if elementBitSize != 0 { + if checkElements { elements = header.ElementsOrVersion } e.stateStack = append(e.stateStack, encodingState{ - offset: oldEnd, - limit: e.end, - elementBitSize: elementBitSize, - elements: elements, + offset: oldEnd, + limit: e.end, + elements: elements, + checkElements: checkElements, }) - e.writeDataHeader(header) } // state returns encoder state of the top-level value. @@ -144,14 +140,16 @@ func NewEncoder() *Encoder { func (e *Encoder) StartArray(length, elementBitSize uint32) { dataSize := dataHeaderSize + bytesForBits(uint64(length)*uint64(elementBitSize)) header := DataHeader{uint32(dataSize), length} - e.pushState(header, elementBitSize) + e.pushState(header, true) + e.writeDataHeader(header) } // StartMap starts encoding a map and writes its data header. // Note: it doesn't write a pointer to the encoded map. // Call |Finish()| after writing keys array and values array. func (e *Encoder) StartMap() { - e.pushState(mapHeader, 0) + e.pushState(mapHeader, false) + e.writeDataHeader(mapHeader) } // StartStruct starts encoding a struct and writes its data header. @@ -160,13 +158,16 @@ func (e *Encoder) StartMap() { func (e *Encoder) StartStruct(size, version uint32) { dataSize := dataHeaderSize + int(size) header := DataHeader{uint32(dataSize), version} - e.pushState(header, 0) + e.pushState(header, false) + e.writeDataHeader(header) } -// StartUnion starts encoding a union and writes its data header. -func (e *Encoder) StartUnion(tag uint32) { - header := DataHeader{uint32(16), tag} - e.pushState(header, 0) +// StartNestedUnion starts encoding a nested union. +// Note: it doesn't write a pointer or a union header. +// Call |Finish()| after writing all fields. +func (e *Encoder) StartNestedUnion() { + header := DataHeader{uint32(16), uint32(0)} + e.pushState(header, false) } func (e *Encoder) writeDataHeader(header DataHeader) { @@ -175,13 +176,37 @@ func (e *Encoder) writeDataHeader(header DataHeader) { e.state().offset += 8 } +// WriteUnionHeader writes a union header for a non-null union. +// (See. WriteNullUnion) +func (e *Encoder) WriteUnionHeader(tag uint32) error { + if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil { + return err + } + e.state().alignOffsetToBytes() + e.state().offset = align(e.state().offset, 8) + binary.LittleEndian.PutUint32(e.buf[e.state().offset:], 16) + binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], tag) + e.state().offset += 8 + if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil { + return err + } + return nil +} + +// FinishWritingUnionValue should call after the union value has been read in +// order to indicate to move the encoder past the union value field. +func (e *Encoder) FinishWritingUnionValue() { + e.state().offset = align(e.state().offset, 8) + e.state().alignOffsetToBytes() +} + // Finish indicates the encoder that you have finished writing elements of // a one-level value. func (e *Encoder) Finish() error { if e.state() == nil { return fmt.Errorf("state stack is empty") } - if e.state().elementBitSize != 0 && e.state().elementsProcessed != e.state().elements { + if e.state().checkElements && e.state().elementsProcessed != e.state().elements { return fmt.Errorf("unexpected number of elements written: defined in header %d, but written %d", e.state().elements, e.state().elementsProcessed) } e.popState() @@ -293,18 +318,11 @@ func (e *Encoder) WriteFloat64(value float64) error { // WriteNullUnion writes a null union. func (e *Encoder) WriteNullUnion() error { - if err := ensureElementBitSizeAndCapacity(e.state(), 128); err != nil { + if err := e.WriteUint64(0); err != nil { return err } - e.state().alignOffsetToBytes() - e.state().offset = align(e.state().offset, 16) - binary.LittleEndian.PutUint64(e.buf[e.state().offset:], 0) - e.state().skipBytes(8) - binary.LittleEndian.PutUint64(e.buf[e.state().offset:], 0) - e.state().skipBytes(8) - e.state().elementsProcessed++ - - return nil + e.state().elementsProcessed-- + return e.WriteUint64(0) } // WriteNullPointer writes a null pointer. diff --git a/third_party/mojo/src/mojo/public/go/bindings/message.go b/third_party/mojo/src/mojo/public/go/bindings/message.go index adc8b31..0e0833c 100644 --- a/third_party/mojo/src/mojo/public/go/bindings/message.go +++ b/third_party/mojo/src/mojo/public/go/bindings/message.go @@ -43,6 +43,7 @@ const ( UnexpectedArrayHeader = "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER" UnexpectedInvalidHandle = "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE" UnexpectedNullPointer = "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER" + UnexpectedNullUnion = "VALIDATION_ERROR_UNEXPECTED_NULL_UNION" UnexpectedStructHeader = "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER" ) diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom index adebff8..b55b43e 100644 --- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom @@ -363,3 +363,9 @@ interface SomeInterface { struct ContainsInterface { SomeInterface some_interface; }; + +// Regression: Verify that a field can be called |other|. + +struct ContainsOther { + int32 other; +}; diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom index 6c573bc..8794259 100644 --- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom @@ -43,6 +43,12 @@ union HandleUnion { SmallCache f_small_cache; }; +struct WrapperStruct { + ObjectUnion? object_union; + PodUnion? pod_union; + HandleUnion? handle_union; +}; + struct HandleStruct { SmallCache f_small_cache; }; diff --git a/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION b/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION index f66a51a3..79a193f 100644 --- a/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION +++ b/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION @@ -1 +1 @@ -custom_build_base_0f9ad3a20275b77d228f67c2edd89dbea0e3e9ea_issue_1113493008_patchset_20001
\ No newline at end of file +050294719f6890ceea4b27540d66295fe6e710a3
\ No newline at end of file diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl index c171aa3..5ab301c 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl @@ -30,7 +30,7 @@ bool {{struct.name}}::Equals(const {{struct.name}}& other) const { {%- for field in struct.fields %} - if (!mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals({{field.name}}, other.{{field.name}})) + if (!mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals(this->{{field.name}}, other.{{field.name}})) return false; {%- endfor %} return true; diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl index 6e3cae4..1378fa3 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl @@ -3,7 +3,7 @@ const int k{{interface|name}}_{{method|name}}_name = {{method.ordinal}}; {%- endfor %} const String {{interface|name}}Name = - '{{namespace|replace(".","::")}}::{{interface|name}}'; + '{{namespace|replace(".","::")}}::{{interface.name}}'; abstract class {{interface|name}} { {%- for method in interface.methods %} diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/encoding_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/encoding_macros.tmpl index 31e5c63..0d86593 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/encoding_macros.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/encoding_macros.tmpl @@ -11,7 +11,10 @@ if {{value}} == nil { encoder.WriteNullPointer() {% endif %} } else { - {{encodeNonNullable('(*'~value~')', kind, level)|tab_indent()}} +{% if not kind|is_union %} +{% set value = '(*'~value~')' %} +{% endif %} + {{encodeNonNullable(value, kind, level)|tab_indent()}} } {% else -%} {{encodeNonNullable(value, kind, level)}} @@ -25,6 +28,10 @@ if {{value}} == nil { if err := encoder.WritePointer(); err != nil { return err } +{% elif kind|is_union and not kind|is_nullable %} +if {{value}} == nil { + return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} +} {% endif %} {% if kind|is_struct or kind|is_union %} if err := {{value}}.Encode(encoder); err != nil { @@ -93,6 +100,18 @@ if pointer{{level}} == 0 { {{decodePointerValue(value, kind, level)|tab_indent()}} } {% endif %} +{% elif kind|is_union %} +var err error +{% set decoding_function = ('Decode'~ kind|name)|qualified(kind|package) %} +{{value}}, err = {{decoding_function}}(decoder) +if err != nil { + return err +} +{% if not kind|is_nullable %} +if {{value}} == nil { + return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} +} +{% endif %} {% elif kind|is_handle or kind|is_interface %} handle{{level}}, err := decoder.Read{{kind|decode_suffix}}() if err != nil { @@ -134,8 +153,6 @@ if err != nil { if err := {{value}}.Decode(decoder); err != nil { return err } -{% elif kind|is_union %} -// TODO(azani): Implement union decoding. {% elif kind|is_array %} len{{level}}, err := decoder.StartArray({{kind.kind|bit_size}}) if err != nil { diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/union.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/union.tmpl index ccb8d5d..a7c47ee 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/union.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/union.tmpl @@ -20,26 +20,29 @@ type __{{union|name(exported)}}Reflect struct { } func Decode{{union|name(exported)}}(decoder *bindings.Decoder) ({{union|name(exported)}}, error) { - header, err := decoder.StartUnion() + size, tag, err := decoder.ReadUnionHeader() if err != nil { return nil, err } - if header.Size == 0 { + if size == 0 { + decoder.SkipNullUnionValue() return nil, nil } - switch header.ElementsOrVersion { + switch tag { {% for field in union.fields %} case {{field.ordinal}}: var value {{union|name(exported)}}{{field|name(exported)}} - value.decodeInternal(decoder) - decoder.Finish() + if err := value.decodeInternal(decoder); err != nil { + return nil, err + } + decoder.FinishReadingUnionValue() return &value, nil {% endfor %} } - return nil, fmt.Errorf("Unknown tag %d in {{union|name(exported)}}", header.ElementsOrVersion); + return nil, fmt.Errorf("Unknown tag %d in {{union|name(exported)}}", tag); } {% for field in union.fields %} @@ -50,17 +53,57 @@ func (u *{{struct_name}}) Interface() interface{} { return u.Value } func (u *{{struct_name}}) __Reflect(__{{union|name(exported)}}Reflect) {} func (u *{{struct_name}}) Encode(encoder *bindings.Encoder) error { - encoder.StartUnion(u.Tag()) - {{encoding_macros.encode('u.Value', field.kind)|tab_indent()}} - encoder.Finish() + encoder.WriteUnionHeader(u.Tag()) + {{encode_union_field('u.Value', field.kind)|tab_indent()}} + encoder.FinishWritingUnionValue() return nil } func (u *{{struct_name}}) decodeInternal(decoder *bindings.Decoder) error { - {{encoding_macros.decode('u.Value', field.kind)|tab_indent()}} + {{decode_union_field('u.Value', field.kind)|tab_indent()}} return nil } {% endfor %} {% endmacro %} + +{% macro encode_union_field(value, kind) %} +{% if kind|is_union %} +if err := encoder.WritePointer(); err != nil { + return err +} + +encoder.StartNestedUnion() +{{encoding_macros.encode(value, kind)}} +encoder.Finish() +{% else %} +{{encoding_macros.encode(value, kind)}} +{% endif %} +{% endmacro %} + +{% macro decode_union_field(value, kind) %} +{% if kind|is_union %} +if pointer, err := decoder.ReadPointer(); err != nil || pointer == 0 { + if err != nil { + return err + } +{% if kind|is_nullable %} + {{value}} = nil + return nil +{% else %} + return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} +{% endif %} +} + +if err := decoder.StartNestedUnion(); err != nil { + return err +} + +{{encoding_macros.decode(value, kind)}} + +decoder.Finish() +{% else %} +{{encoding_macros.decode(value, kind)}} +{% endif %} +{% endmacro %} diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl index 5c686f3..e9c3b65 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl @@ -215,7 +215,7 @@ if (decoder{{level+1}} == null) { {% if struct.fields|length %} {{struct|name}} other = ({{struct|name}}) object; {% for field in struct.fields %} - if ({{equality(field.kind, field|name, 'other.'~field|name, True)}}) + if ({{equality(field.kind, 'this.'~field|name, 'other.'~field|name, True)}}) return false; {% endfor %} {% endif %} diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py index e20e9e4..78d938c 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py @@ -75,7 +75,7 @@ def GetBitSize(kind): # Returns go type corresponding to provided kind. If |nullable| is true # and kind is nullable adds an '*' to type (example: ?string -> *string). def GetGoType(kind, nullable = True): - if nullable and mojom.IsNullableKind(kind): + if nullable and mojom.IsNullableKind(kind) and not mojom.IsUnionKind(kind): return '*%s' % GetNonNullableGoType(kind) return GetNonNullableGoType(kind) @@ -98,6 +98,9 @@ def GetNonNullableGoType(kind): return GetNameForNestedElement(kind) return _kind_infos[kind].go_type +def IsPointer(kind): + return mojom.IsObjectKind(kind) and not mojom.IsUnionKind(kind) + # Splits name to lower-cased parts used for camel-casing # (example: HTTPEntry2FooBar -> ['http', 'entry2', 'foo', 'bar']). def NameToComponent(name): @@ -126,14 +129,8 @@ def FormatName(name, exported=True): # |element| should have attr 'name'. |exported| argument is used to make # |FormatName()| calls only. def GetFullName(element, exported=True): - if not hasattr(element, 'imported_from') or not element.imported_from: - return FormatName(element.name, exported) - path = '' - if element.imported_from['module'].path: - path += GetPackagePath(element.imported_from['module']) - if path in _imports: - return '%s.%s' % (_imports[path], FormatName(element.name, exported)) - return FormatName(element.name, exported) + return GetQualifiedName( + element.name, GetPackageNameForElement(element), exported) # Returns a name for nested elements like enum field or constant. # The returned name consists of camel-cased parts separated by '_'. @@ -189,6 +186,21 @@ def EncodeSuffix(kind): def GetPackageName(module): return module.name.split('.')[0] +def GetPackageNameForElement(element): + if not hasattr(element, 'imported_from') or not element.imported_from: + return '' + path = '' + if element.imported_from['module'].path: + path += GetPackagePath(element.imported_from['module']) + if path in _imports: + return _imports[path] + return '' + +def GetQualifiedName(name, package=None, exported=True): + if not package: + return FormatName(name, exported) + return '%s.%s' % (package, FormatName(name, exported)) + def GetPackagePath(module): name = module.name.split('.')[0] return '/'.join(module.path.split('/')[:-1] + [name]) @@ -250,10 +262,13 @@ class Generator(generator.Generator): 'is_map': mojom.IsMapKind, 'is_none_or_empty': lambda array: array == None or len(array) == 0, 'is_nullable': mojom.IsNullableKind, - 'is_pointer': mojom.IsObjectKind, + 'is_pointer': IsPointer, + 'is_object': mojom.IsObjectKind, 'is_struct': mojom.IsStructKind, 'is_union': mojom.IsUnionKind, + 'qualified': GetQualifiedName, 'name': GetNameForElement, + 'package': GetPackageNameForElement, 'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines()) } diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py index 5fdce42..b034f97 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/pack.py @@ -61,6 +61,8 @@ class PackedField(object): def GetAlignmentForKind(cls, kind): if isinstance(kind, mojom.Interface): return 4 + if isinstance(kind, mojom.Union): + return 8 return cls.GetSizeForKind(kind) def __init__(self, field, index, ordinal): diff --git a/third_party/mojo/src/mojo/public/tools/dart_package.py b/third_party/mojo/src/mojo/public/tools/dart_package.py index 083a6d5..0ded17d 100755 --- a/third_party/mojo/src/mojo/public/tools/dart_package.py +++ b/third_party/mojo/src/mojo/public/tools/dart_package.py @@ -47,6 +47,21 @@ def IsPathInLib(path): def PackageRelativePath(path): return os.path.relpath(path, "lib/") +def HasPubspec(paths): + for path in paths: + _, filename = os.path.split(path) + if 'pubspec.yaml' == filename: + return True + return False + +def ReadPackageName(paths): + for path in paths: + _, filename = os.path.split(path) + if 'pubspec.yaml' == filename: + with open(path, 'r') as f: + return FindPackageName(f.read()) + return None + def DoZip(inputs, zip_inputs, output, base_dir): files = [] with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as outfile: @@ -55,9 +70,24 @@ def DoZip(inputs, zip_inputs, output, base_dir): file_name = os.path.relpath(f, base_dir) # We should never see a packages/ path here. assert not IsPackagesPath(file_name) - # We should never see a .mojom.dart path here. files.append(file_name) outfile.write(f, file_name) + + if HasPubspec(inputs): + # We are writing out a package, write lib/ into packages/<package_name> + # so that package:<package_name>/ imports work within the package. + package_name = ReadPackageName(inputs) + assert not (package_name is None), "pubspec.yaml does not have a name" + package_path = os.path.join("packages/", package_name) + for f in inputs: + file_name = os.path.relpath(f, base_dir) + if IsPathInLib(file_name): + output_name = os.path.join(package_path, + PackageRelativePath(file_name)) + if output_name not in files: + files.append(output_name) + outfile.write(f, output_name) + # zip file inputs (other packages) for zf_name in zip_inputs: with zipfile.ZipFile(zf_name, 'r') as zf: diff --git a/third_party/mojo/src/mojo/public/tools/gn/last_commit_timestamp.py b/third_party/mojo/src/mojo/public/tools/gn/last_commit_timestamp.py new file mode 100755 index 0000000..99c7e45 --- /dev/null +++ b/third_party/mojo/src/mojo/public/tools/gn/last_commit_timestamp.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# Copyright 2015 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. + +"""Outputs the timestamp of the last commit in a Git repository.""" + +import argparse +import subprocess +import sys + +def get_timestamp(directory): + return subprocess.check_output(["git", "log", "-1", "--pretty=format:%ct"], + cwd=directory) + +def main(): + parser = argparse.ArgumentParser(description="Prints the timestamp of the " + "last commit in a git repository") + parser.add_argument("--directory", nargs='?', + help="Directory of the git repository", default=".") + parser.add_argument("--output", nargs='?', + help="Output file, or stdout if omitted") + args = parser.parse_args() + + output_file = sys.stdout + if args.output: + output_file = open(args.output, 'w') + + with output_file: + # Print without newline so GN can read it. + output_file.write(get_timestamp(args.directory)) + +if __name__ == '__main__': + sys.exit(main()) + |