diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:20:33 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:28:57 +0000 |
commit | d17ea114e5ef69ad5d5d7413280a13e6428098aa (patch) | |
tree | 2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/mojo | |
parent | 8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff) | |
download | qtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz |
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/mojo')
260 files changed, 6471 insertions, 3491 deletions
diff --git a/chromium/mojo/BUILD.gn b/chromium/mojo/BUILD.gn index 664daace7bd..fcc91bbf5ca 100644 --- a/chromium/mojo/BUILD.gn +++ b/chromium/mojo/BUILD.gn @@ -61,7 +61,7 @@ test("mojo_perftests") { deps += [ "//base", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/edk/system:test_utils", "//testing/gtest", ] diff --git a/chromium/mojo/README.md b/chromium/mojo/README.md index 4d80acada03..11b0df01455 100644 --- a/chromium/mojo/README.md +++ b/chromium/mojo/README.md @@ -1,5 +1,4 @@ # Mojo -This document is a subset of the [Mojo documentation](/mojo). [TOC] @@ -68,7 +67,7 @@ wrapping and unwrapping helpers, common handle operations, and utilities for more easily watching handle state changes. ### JavaScript -The [**JavaScript System API**](/third_party/WebKit/Source/core/mojo) exposes +The [**JavaScript System API**](/third_party/blink/renderer/core/mojo) exposes the Mojo primitives to JavaScript, covering all basic functionality of the low-level C API. diff --git a/chromium/mojo/android/BUILD.gn b/chromium/mojo/android/BUILD.gn index f4932ffa94f..223f859aae4 100644 --- a/chromium/mojo/android/BUILD.gn +++ b/chromium/mojo/android/BUILD.gn @@ -130,7 +130,7 @@ shared_library("mojo_java_unittests") { "//base", "//base/test:test_support", "//build/config:exe_and_shlib_deps", - "//mojo/edk/system", + "//mojo/edk", "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils", "//mojo/public/cpp/test_support:test_utils", ] diff --git a/chromium/mojo/android/system/base_run_loop.cc b/chromium/mojo/android/system/base_run_loop.cc index 5227405b8b0..bfc170007cf 100644 --- a/chromium/mojo/android/system/base_run_loop.cc +++ b/chromium/mojo/android/system/base_run_loop.cc @@ -5,7 +5,7 @@ #include <jni.h> #include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" +#include "base/android/scoped_java_ref.h" #include "base/bind.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" @@ -74,4 +74,3 @@ static void JNI_BaseRunLoop_DeleteMessageLoop( } // namespace android } // namespace mojo - diff --git a/chromium/mojo/android/system/core_impl.cc b/chromium/mojo/android/system/core_impl.cc index 0e833f0b2f5..acf9179d808 100644 --- a/chromium/mojo/android/system/core_impl.cc +++ b/chromium/mojo/android/system/core_impl.cc @@ -7,8 +7,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_array.h" -#include "base/android/jni_registrar.h" -#include "base/android/library_loader/library_loader_hooks.h" #include "base/android/scoped_java_ref.h" #include "jni/CoreImpl_jni.h" #include "mojo/public/c/system/core.h" @@ -146,7 +144,7 @@ static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadMessage( return Java_CoreImpl_newReadMessageResult(env, result, nullptr, nullptr); DCHECK(message.is_valid()); - result = MojoSerializeMessage(message->value()); + result = MojoSerializeMessage(message->value(), nullptr); if (result != MOJO_RESULT_OK && result != MOJO_RESULT_FAILED_PRECONDITION) { return Java_CoreImpl_newReadMessageResult(env, MOJO_RESULT_ABORTED, nullptr, nullptr); @@ -156,14 +154,12 @@ static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadMessage( void* buffer; uint32_t num_handles = 0; std::vector<MojoHandle> handles; - result = MojoGetSerializedMessageContents( - message->value(), &buffer, &num_bytes, nullptr, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes, + nullptr, &num_handles); if (result == MOJO_RESULT_RESOURCE_EXHAUSTED) { handles.resize(num_handles); - result = MojoGetSerializedMessageContents( - message->value(), &buffer, &num_bytes, handles.data(), &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes, + handles.data(), &num_handles); } if (result != MOJO_RESULT_OK) diff --git a/chromium/mojo/android/system/watcher_impl.cc b/chromium/mojo/android/system/watcher_impl.cc index ffbb00de4ea..b744416ff7b 100644 --- a/chromium/mojo/android/system/watcher_impl.cc +++ b/chromium/mojo/android/system/watcher_impl.cc @@ -6,8 +6,6 @@ #include <stdint.h> #include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "base/android/library_loader/library_loader_hooks.h" #include "base/android/scoped_java_ref.h" #include "base/bind.h" #include "jni/WatcherImpl_jni.h" @@ -23,7 +21,10 @@ namespace { class WatcherImpl { public: - WatcherImpl() : watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC) {} + WatcherImpl() + : watcher_(FROM_HERE, + SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()) {} ~WatcherImpl() = default; diff --git a/chromium/mojo/common/BUILD.gn b/chromium/mojo/common/BUILD.gn index 23b0118192d..d4042376285 100644 --- a/chromium/mojo/common/BUILD.gn +++ b/chromium/mojo/common/BUILD.gn @@ -7,64 +7,23 @@ import("//testing/test.gni") group("common") { public_deps = [ - ":common_base", ":common_custom_types", ] } mojom("common_custom_types") { sources = [ - "file.mojom", - "file_info.mojom", - "file_path.mojom", - "memory_allocator_dump_cross_process_uid.mojom", - "process_id.mojom", - "text_direction.mojom", - "thread_priority.mojom", - "time.mojom", - "unguessable_token.mojom", "values.mojom", - "version.mojom", ] - if (is_win) { - sources += [ "logfont_win.mojom" ] - } - public_deps = [ "//mojo/public/mojom/base", ] } -mojom("read_only_buffer") { - sources = [ - "read_only_buffer.mojom", - ] -} - -component("common_base") { - output_name = "mojo_common_lib" - - sources = [ - "data_pipe_drainer.cc", - "data_pipe_drainer.h", - "data_pipe_utils.cc", - "data_pipe_utils.h", - ] - - defines = [ "MOJO_COMMON_IMPLEMENTATION" ] - - public_deps = [ - "//base", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - ] -} - mojom("test_common_custom_types") { sources = [ "test_common_custom_types.mojom", - "traits_test_service.mojom", ] public_deps = [ ":common_custom_types", @@ -75,7 +34,6 @@ test("mojo_common_unittests") { deps = [ ":common", ":common_custom_types", - ":struct_traits", ":test_common_custom_types", "//base", "//base/test:test_support", @@ -89,23 +47,6 @@ test("mojo_common_unittests") { sources = [ "common_custom_types_unittest.cc", - "struct_traits_unittest.cc", - ] -} - -source_set("struct_traits") { - sources = [ - "common_custom_types_struct_traits.cc", - "common_custom_types_struct_traits.h", - "time_struct_traits.h", - ] - deps = [ - ":common_custom_types_shared_cpp_sources", - "//base", - "//mojo/public/cpp/system", - ] - public_deps = [ - "//base:i18n", ] } diff --git a/chromium/mojo/common/common_custom_types_struct_traits.cc b/chromium/mojo/common/common_custom_types_struct_traits.cc deleted file mode 100644 index 5304d99d8b8..00000000000 --- a/chromium/mojo/common/common_custom_types_struct_traits.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/common/common_custom_types_struct_traits.h" - -#include "mojo/public/cpp/system/platform_handle.h" - -namespace mojo { - -// static -const std::vector<uint32_t>& -StructTraits<common::mojom::VersionDataView, base::Version>::components( - const base::Version& version) { - return version.components(); -} - -// static -bool StructTraits<common::mojom::VersionDataView, base::Version>::Read( - common::mojom::VersionDataView data, - base::Version* out) { - std::vector<uint32_t> components; - if (!data.ReadComponents(&components)) - return false; - - *out = base::Version(base::Version(std::move(components))); - return out->IsValid(); -} - -// static -bool StructTraits< - common::mojom::UnguessableTokenDataView, - base::UnguessableToken>::Read(common::mojom::UnguessableTokenDataView data, - base::UnguessableToken* out) { - uint64_t high = data.high(); - uint64_t low = data.low(); - - // Receiving a zeroed UnguessableToken is a security issue. - if (high == 0 && low == 0) - return false; - - *out = base::UnguessableToken::Deserialize(high, low); - return true; -} - -mojo::ScopedHandle StructTraits<common::mojom::FileDataView, base::File>::fd( - base::File& file) { - DCHECK(file.IsValid()); - return mojo::WrapPlatformFile(file.TakePlatformFile()); -} - -bool StructTraits<common::mojom::FileDataView, base::File>::Read( - common::mojom::FileDataView data, - base::File* file) { - base::PlatformFile platform_handle = base::kInvalidPlatformFile; - if (mojo::UnwrapPlatformFile(data.TakeFd(), &platform_handle) != - MOJO_RESULT_OK) { - return false; - } - *file = base::File(platform_handle); - return true; -} - -// static -common::mojom::TextDirection -EnumTraits<common::mojom::TextDirection, base::i18n::TextDirection>::ToMojom( - base::i18n::TextDirection text_direction) { - switch (text_direction) { - case base::i18n::UNKNOWN_DIRECTION: - return common::mojom::TextDirection::UNKNOWN_DIRECTION; - case base::i18n::RIGHT_TO_LEFT: - return common::mojom::TextDirection::RIGHT_TO_LEFT; - case base::i18n::LEFT_TO_RIGHT: - return common::mojom::TextDirection::LEFT_TO_RIGHT; - } - NOTREACHED(); - return common::mojom::TextDirection::UNKNOWN_DIRECTION; -} - -// static -bool EnumTraits<common::mojom::TextDirection, base::i18n::TextDirection>:: - FromMojom(common::mojom::TextDirection input, - base::i18n::TextDirection* out) { - switch (input) { - case common::mojom::TextDirection::UNKNOWN_DIRECTION: - *out = base::i18n::UNKNOWN_DIRECTION; - return true; - case common::mojom::TextDirection::RIGHT_TO_LEFT: - *out = base::i18n::RIGHT_TO_LEFT; - return true; - case common::mojom::TextDirection::LEFT_TO_RIGHT: - *out = base::i18n::LEFT_TO_RIGHT; - return true; - } - return false; -} - -// static -common::mojom::ThreadPriority -EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority>::ToMojom( - base::ThreadPriority thread_priority) { - switch (thread_priority) { - case base::ThreadPriority::BACKGROUND: - return common::mojom::ThreadPriority::BACKGROUND; - case base::ThreadPriority::NORMAL: - return common::mojom::ThreadPriority::NORMAL; - case base::ThreadPriority::DISPLAY: - return common::mojom::ThreadPriority::DISPLAY; - case base::ThreadPriority::REALTIME_AUDIO: - return common::mojom::ThreadPriority::REALTIME_AUDIO; - } - NOTREACHED(); - return common::mojom::ThreadPriority::BACKGROUND; -} - -// static -bool EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority>::FromMojom( - common::mojom::ThreadPriority input, - base::ThreadPriority* out) { - switch (input) { - case common::mojom::ThreadPriority::BACKGROUND: - *out = base::ThreadPriority::BACKGROUND; - return true; - case common::mojom::ThreadPriority::NORMAL: - *out = base::ThreadPriority::NORMAL; - return true; - case common::mojom::ThreadPriority::DISPLAY: - *out = base::ThreadPriority::DISPLAY; - return true; - case common::mojom::ThreadPriority::REALTIME_AUDIO: - *out = base::ThreadPriority::REALTIME_AUDIO; - return true; - } - return false; -} - -// static -bool StructTraits<common::mojom::MemoryAllocatorDumpCrossProcessUidDataView, - base::trace_event::MemoryAllocatorDumpGuid>:: - Read(common::mojom::MemoryAllocatorDumpCrossProcessUidDataView data, - base::trace_event::MemoryAllocatorDumpGuid* out) { - // Receiving a zeroed MemoryAllocatorDumpCrossProcessUid is a bug. - if (data.value() == 0) - return false; - - *out = base::trace_event::MemoryAllocatorDumpGuid(data.value()); - return true; -} - -} // namespace mojo diff --git a/chromium/mojo/common/common_custom_types_struct_traits.h b/chromium/mojo/common/common_custom_types_struct_traits.h deleted file mode 100644 index 0d6bf6b8083..00000000000 --- a/chromium/mojo/common/common_custom_types_struct_traits.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ -#define MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ - -#include "base/files/file.h" -#include "base/i18n/rtl.h" -#include "base/process/process_handle.h" -#include "base/strings/utf_string_conversions.h" -#include "base/trace_event/memory_allocator_dump_guid.h" -#include "base/unguessable_token.h" -#include "base/version.h" -#include "mojo/common/file.mojom-shared.h" -#include "mojo/common/memory_allocator_dump_cross_process_uid.mojom-shared.h" -#include "mojo/common/mojo_common_export.h" -#include "mojo/common/process_id.mojom-shared.h" -#include "mojo/common/text_direction.mojom-shared.h" -#include "mojo/common/thread_priority.mojom-shared.h" -#include "mojo/common/unguessable_token.mojom-shared.h" -#include "mojo/common/version.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<common::mojom::VersionDataView, base::Version> { - static bool IsNull(const base::Version& version) { - return !version.IsValid(); - } - static void SetToNull(base::Version* out) { - *out = base::Version(std::string()); - } - static const std::vector<uint32_t>& components(const base::Version& version); - static bool Read(common::mojom::VersionDataView data, base::Version* out); -}; - -// If base::UnguessableToken is no longer 128 bits, the logic below and the -// mojom::UnguessableToken type should be updated. -static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t), - "base::UnguessableToken should be of size 2 * sizeof(uint64_t)."); - -template <> -struct StructTraits<common::mojom::UnguessableTokenDataView, - base::UnguessableToken> { - static uint64_t high(const base::UnguessableToken& token) { - return token.GetHighForSerialization(); - } - - static uint64_t low(const base::UnguessableToken& token) { - return token.GetLowForSerialization(); - } - - static bool Read(common::mojom::UnguessableTokenDataView data, - base::UnguessableToken* out); -}; - -template <> -struct StructTraits<common::mojom::ProcessIdDataView, base::ProcessId> { - static uint32_t pid(const base::ProcessId& process_id) { - return static_cast<uint32_t>(process_id); - } - - static bool Read(common::mojom::ProcessIdDataView data, - base::ProcessId* process_id) { - *process_id = static_cast<base::ProcessId>(data.pid()); - return true; - } -}; - -template <> -struct StructTraits<common::mojom::FileDataView, base::File> { - static bool IsNull(const base::File& file) { return !file.IsValid(); } - - static void SetToNull(base::File* file) { *file = base::File(); } - - static mojo::ScopedHandle fd(base::File& file); - static bool Read(common::mojom::FileDataView data, base::File* file); -}; - -template <> -struct EnumTraits<common::mojom::TextDirection, base::i18n::TextDirection> { - static common::mojom::TextDirection ToMojom( - base::i18n::TextDirection text_direction); - static bool FromMojom(common::mojom::TextDirection input, - base::i18n::TextDirection* out); -}; - -template <> -struct EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority> { - static common::mojom::ThreadPriority ToMojom( - base::ThreadPriority thread_priority); - static bool FromMojom(common::mojom::ThreadPriority input, - base::ThreadPriority* out); -}; - -template <> -struct StructTraits<common::mojom::MemoryAllocatorDumpCrossProcessUidDataView, - base::trace_event::MemoryAllocatorDumpGuid> { - static uint64_t value(const base::trace_event::MemoryAllocatorDumpGuid& id) { - return id.ToUint64(); - } - - static bool Read( - common::mojom::MemoryAllocatorDumpCrossProcessUidDataView data, - base::trace_event::MemoryAllocatorDumpGuid* out); -}; - -} // namespace mojo - -#endif // MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ diff --git a/chromium/mojo/common/common_custom_types_unittest.cc b/chromium/mojo/common/common_custom_types_unittest.cc index 77310359ffc..ba9af3598c6 100644 --- a/chromium/mojo/common/common_custom_types_unittest.cc +++ b/chromium/mojo/common/common_custom_types_unittest.cc @@ -2,16 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/numerics/safe_math.h" -#include "base/process/process_handle.h" #include "base/run_loop.h" #include "base/values.h" -#include "mojo/common/common_custom_types_struct_traits.h" -#include "mojo/common/process_id.mojom.h" #include "mojo/common/test_common_custom_types.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "testing/gtest/include/gtest/gtest.h" @@ -63,60 +58,6 @@ base::Callback<void(typename PassTraits<T>::Type)> ExpectResponse( return base::Bind(&DoExpectResponse<T>, expected_value, closure); } -class TestFilePathImpl : public TestFilePath { - public: - explicit TestFilePathImpl(TestFilePathRequest request) - : binding_(this, std::move(request)) {} - - // TestFilePath implementation: - void BounceFilePath(const base::FilePath& in, - BounceFilePathCallback callback) override { - std::move(callback).Run(in); - } - - private: - mojo::Binding<TestFilePath> binding_; -}; - -class TestUnguessableTokenImpl : public TestUnguessableToken { - public: - explicit TestUnguessableTokenImpl(TestUnguessableTokenRequest request) - : binding_(this, std::move(request)) {} - - // TestUnguessableToken implementation: - void BounceNonce(const base::UnguessableToken& in, - BounceNonceCallback callback) override { - std::move(callback).Run(in); - } - - private: - mojo::Binding<TestUnguessableToken> binding_; -}; - -class TestTimeImpl : public TestTime { - public: - explicit TestTimeImpl(TestTimeRequest request) - : binding_(this, std::move(request)) {} - - // TestTime implementation: - void BounceTime(base::Time in, BounceTimeCallback callback) override { - std::move(callback).Run(in); - } - - void BounceTimeDelta(base::TimeDelta in, - BounceTimeDeltaCallback callback) override { - std::move(callback).Run(in); - } - - void BounceTimeTicks(base::TimeTicks in, - BounceTimeTicksCallback callback) override { - std::move(callback).Run(in); - } - - private: - mojo::Binding<TestTime> binding_; -}; - class TestValueImpl : public TestValue { public: explicit TestValueImpl(TestValueRequest request) @@ -142,35 +83,6 @@ class TestValueImpl : public TestValue { mojo::Binding<TestValue> binding_; }; -class TestFileImpl : public TestFile { - public: - explicit TestFileImpl(TestFileRequest request) - : binding_(this, std::move(request)) {} - - // TestFile implementation: - void BounceFile(base::File in, BounceFileCallback callback) override { - std::move(callback).Run(std::move(in)); - } - - private: - mojo::Binding<TestFile> binding_; -}; - -class TestTextDirectionImpl : public TestTextDirection { - public: - explicit TestTextDirectionImpl(TestTextDirectionRequest request) - : binding_(this, std::move(request)) {} - - // TestTextDirection: - void BounceTextDirection(base::i18n::TextDirection in, - BounceTextDirectionCallback callback) override { - std::move(callback).Run(in); - } - - private: - mojo::Binding<TestTextDirection> binding_; -}; - class CommonCustomTypesTest : public testing::Test { protected: CommonCustomTypesTest() {} @@ -184,81 +96,6 @@ class CommonCustomTypesTest : public testing::Test { } // namespace -TEST_F(CommonCustomTypesTest, FilePath) { - base::RunLoop run_loop; - - TestFilePathPtr ptr; - TestFilePathImpl impl(MakeRequest(&ptr)); - - base::FilePath dir(FILE_PATH_LITERAL("hello")); - base::FilePath file = dir.Append(FILE_PATH_LITERAL("world")); - - ptr->BounceFilePath(file, ExpectResponse(&file, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, UnguessableToken) { - base::RunLoop run_loop; - - TestUnguessableTokenPtr ptr; - TestUnguessableTokenImpl impl(MakeRequest(&ptr)); - - base::UnguessableToken token = base::UnguessableToken::Create(); - - ptr->BounceNonce(token, ExpectResponse(&token, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, ProcessId) { - base::ProcessId pid = base::GetCurrentProcId(); - base::ProcessId out_pid = base::kNullProcessId; - ASSERT_NE(pid, out_pid); - EXPECT_TRUE(mojom::ProcessId::Deserialize(mojom::ProcessId::Serialize(&pid), - &out_pid)); - EXPECT_EQ(pid, out_pid); -} - -TEST_F(CommonCustomTypesTest, Time) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::Time t = base::Time::Now(); - - ptr->BounceTime(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, TimeDelta) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::TimeDelta t = base::TimeDelta::FromDays(123); - - ptr->BounceTimeDelta(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, TimeTicks) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::TimeTicks t = base::TimeTicks::Now(); - - ptr->BounceTimeTicks(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - TEST_F(CommonCustomTypesTest, Value) { TestValuePtr ptr; TestValueImpl impl(MakeRequest(&ptr)); @@ -337,64 +174,6 @@ TEST_F(CommonCustomTypesTest, Value) { ASSERT_EQ(*input, *output); } -TEST_F(CommonCustomTypesTest, File) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - TestFilePtr ptr; - TestFileImpl impl(MakeRequest(&ptr)); - - base::File file( - temp_dir.GetPath().AppendASCII("test_file.txt"), - base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); - const base::StringPiece test_content = - "A test string to be stored in a test file"; - file.WriteAtCurrentPos( - test_content.data(), - base::CheckedNumeric<int>(test_content.size()).ValueOrDie()); - - base::File file_out; - ASSERT_TRUE(ptr->BounceFile(std::move(file), &file_out)); - std::vector<char> content(test_content.size()); - ASSERT_TRUE(file_out.IsValid()); - ASSERT_EQ(static_cast<int>(test_content.size()), - file_out.Read( - 0, content.data(), - base::CheckedNumeric<int>(test_content.size()).ValueOrDie())); - EXPECT_EQ(test_content, - base::StringPiece(content.data(), test_content.size())); -} - -TEST_F(CommonCustomTypesTest, InvalidFile) { - TestFilePtr ptr; - TestFileImpl impl(MakeRequest(&ptr)); - - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - // Test that |file_out| is set to an invalid file. - base::File file_out( - temp_dir.GetPath().AppendASCII("test_file.txt"), - base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); - - ASSERT_TRUE(ptr->BounceFile(base::File(), &file_out)); - EXPECT_FALSE(file_out.IsValid()); -} - -TEST_F(CommonCustomTypesTest, TextDirection) { - base::i18n::TextDirection kTestDirections[] = {base::i18n::LEFT_TO_RIGHT, - base::i18n::RIGHT_TO_LEFT, - base::i18n::UNKNOWN_DIRECTION}; - - TestTextDirectionPtr ptr; - TestTextDirectionImpl impl(MakeRequest(&ptr)); - - for (size_t i = 0; i < arraysize(kTestDirections); i++) { - base::i18n::TextDirection direction_out; - ASSERT_TRUE(ptr->BounceTextDirection(kTestDirections[i], &direction_out)); - EXPECT_EQ(kTestDirections[i], direction_out); - } -} - } // namespace test } // namespace common } // namespace mojo diff --git a/chromium/mojo/common/file.typemap b/chromium/mojo/common/file.typemap deleted file mode 100644 index 26d494139e8..00000000000 --- a/chromium/mojo/common/file.typemap +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/file.mojom" -public_headers = [ "//base/files/file.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = - [ "mojo.common.mojom.File=base::File[move_only,nullable_is_same_type]" ] diff --git a/chromium/mojo/common/memory_allocator_dump_cross_process_uid.typemap b/chromium/mojo/common/memory_allocator_dump_cross_process_uid.typemap deleted file mode 100644 index 8a73ec7be74..00000000000 --- a/chromium/mojo/common/memory_allocator_dump_cross_process_uid.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2017 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. - -mojom = "//mojo/common/memory_allocator_dump_cross_process_uid.mojom" -public_headers = [ "//base/trace_event/memory_allocator_dump_guid.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.MemoryAllocatorDumpCrossProcessUid=base::trace_event::MemoryAllocatorDumpGuid" ] diff --git a/chromium/mojo/common/process_id.typemap b/chromium/mojo/common/process_id.typemap deleted file mode 100644 index 671454044a9..00000000000 --- a/chromium/mojo/common/process_id.typemap +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2017 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. - -mojom = "//mojo/common/process_id.mojom" -public_headers = [ "//base/process/process_handle.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = - [ "mojo.common.mojom.ProcessId=base::ProcessId[copyable_pass_by_value]" ] diff --git a/chromium/mojo/common/read_only_buffer.typemap b/chromium/mojo/common/read_only_buffer.typemap deleted file mode 100644 index bd7dfafd97a..00000000000 --- a/chromium/mojo/common/read_only_buffer.typemap +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 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. - -mojom = "//mojo/common/read_only_buffer.mojom" -public_headers = [ "//base/containers/span.h" ] -traits_headers = [ "//mojo/common/read_only_buffer_struct_traits.h" ] -type_mappings = [ "mojo.common.mojom.ReadOnlyBuffer=base::span<const uint8_t>[copyable_pass_by_value,force_serialize]" ] diff --git a/chromium/mojo/common/read_only_buffer_struct_traits.h b/chromium/mojo/common/read_only_buffer_struct_traits.h deleted file mode 100644 index c35efac6e03..00000000000 --- a/chromium/mojo/common/read_only_buffer_struct_traits.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 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_COMMON_READ_ONLY_BUFFER_STRUCT_TRAITS_H_ -#define MOJO_COMMON_READ_ONLY_BUFFER_STRUCT_TRAITS_H_ - -#include "base/containers/span.h" -#include "mojo/common/read_only_buffer.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<common::mojom::ReadOnlyBufferDataView, - base::span<const uint8_t>> { - static base::span<const uint8_t> buffer(base::span<const uint8_t> input) { - return input; - } - - static bool Read(common::mojom::ReadOnlyBufferDataView input, - base::span<const uint8_t>* out) { - ArrayDataView<uint8_t> data_view; - input.GetBufferDataView(&data_view); - - // NOTE: This output directly refers to memory owned by the message. - // Therefore, the message must stay valid while the output is passed to the - // user code. - *out = base::span<const uint8_t>(data_view.data(), data_view.size()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_COMMON_READ_ONLY_BUFFER_STRUCT_TRAITS_H_ diff --git a/chromium/mojo/common/struct_traits_unittest.cc b/chromium/mojo/common/struct_traits_unittest.cc deleted file mode 100644 index 8956aea0397..00000000000 --- a/chromium/mojo/common/struct_traits_unittest.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop/message_loop.h" -#include "mojo/common/traits_test_service.mojom.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace common { -namespace { - -class StructTraitsTest : public testing::Test, public mojom::TraitsTestService { - public: - StructTraitsTest() {} - - protected: - mojom::TraitsTestServicePtr GetTraitsTestProxy() { - mojom::TraitsTestServicePtr proxy; - traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy)); - return proxy; - } - - private: - // TraitsTestService: - void EchoVersion(const base::Optional<base::Version>& m, - EchoVersionCallback callback) override { - std::move(callback).Run(m); - } - - base::MessageLoop loop_; - mojo::BindingSet<TraitsTestService> traits_test_bindings_; - - DISALLOW_COPY_AND_ASSIGN(StructTraitsTest); -}; - -TEST_F(StructTraitsTest, Version) { - const std::string& version_str = "1.2.3.4"; - base::Version input(version_str); - mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); - base::Optional<base::Version> output; - proxy->EchoVersion(input, &output); - EXPECT_TRUE(output.has_value()); - EXPECT_EQ(version_str, output->GetString()); -} - -TEST_F(StructTraitsTest, InvalidVersion) { - const std::string invalid_version_str; - base::Version input(invalid_version_str); - mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); - base::Optional<base::Version> output; - proxy->EchoVersion(input, &output); - EXPECT_FALSE(output.has_value()); -} - -} // namespace -} // namespace common -} // namespace mojo diff --git a/chromium/mojo/common/test_common_custom_types.mojom b/chromium/mojo/common/test_common_custom_types.mojom index da48124ca46..e23a94ae75e 100644 --- a/chromium/mojo/common/test_common_custom_types.mojom +++ b/chromium/mojo/common/test_common_custom_types.mojom @@ -4,31 +4,8 @@ module mojo.common.test; -import "mojo/common/file.mojom"; -import "mojo/common/file_path.mojom"; -import "mojo/common/text_direction.mojom"; -import "mojo/common/time.mojom"; -import "mojo/common/unguessable_token.mojom"; import "mojo/common/values.mojom"; -interface TestFilePath { - BounceFilePath(mojo.common.mojom.FilePath in) - => (mojo.common.mojom.FilePath out); -}; - -interface TestUnguessableToken { - BounceNonce(mojo.common.mojom.UnguessableToken in) - => (mojo.common.mojom.UnguessableToken out); -}; - -interface TestTime { - BounceTime(mojo.common.mojom.Time time) => (mojo.common.mojom.Time time); - BounceTimeDelta(mojo.common.mojom.TimeDelta time_delta) - => (mojo.common.mojom.TimeDelta time_delta); - BounceTimeTicks(mojo.common.mojom.TimeTicks time_ticks) - => (mojo.common.mojom.TimeTicks time_ticks); -}; - interface TestValue { [Sync] BounceDictionaryValue(mojo.common.mojom.DictionaryValue in) @@ -40,15 +17,3 @@ interface TestValue { BounceValue(mojo.common.mojom.Value? in) => (mojo.common.mojom.Value? out); }; - -interface TestFile { - [Sync] - BounceFile(mojo.common.mojom.File? in) - => (mojo.common.mojom.File? out); -}; - -interface TestTextDirection { - [Sync] - BounceTextDirection(mojo.common.mojom.TextDirection in) - => (mojo.common.mojom.TextDirection out); -}; diff --git a/chromium/mojo/common/text_direction.typemap b/chromium/mojo/common/text_direction.typemap deleted file mode 100644 index 1f5be8edbaf..00000000000 --- a/chromium/mojo/common/text_direction.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2017 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. - -mojom = "//mojo/common/text_direction.mojom" -public_headers = [ "//base/i18n/rtl.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//base:i18n", - "//mojo/common:struct_traits", -] -type_mappings = [ "mojo.common.mojom.TextDirection=base::i18n::TextDirection" ] diff --git a/chromium/mojo/common/thread_priority.typemap b/chromium/mojo/common/thread_priority.typemap deleted file mode 100644 index d3f9be12e76..00000000000 --- a/chromium/mojo/common/thread_priority.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2017 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. - -mojom = "//mojo/common/thread_priority.mojom" -public_headers = [ "//base/threading/platform_thread.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//base", - "//mojo/common:struct_traits", -] -type_mappings = [ "mojo.common.mojom.ThreadPriority=base::ThreadPriority" ] diff --git a/chromium/mojo/common/time.typemap b/chromium/mojo/common/time.typemap deleted file mode 100644 index 20661f6ecb2..00000000000 --- a/chromium/mojo/common/time.typemap +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/time.mojom" -public_headers = [ "//base/time/time.h" ] -traits_headers = [ "//mojo/common/time_struct_traits.h" ] -public_deps = [ - "//base", - "//mojo/common:struct_traits", -] - -type_mappings = [ - "mojo.common.mojom.Time=base::Time[copyable_pass_by_value]", - "mojo.common.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]", - "mojo.common.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]", -] diff --git a/chromium/mojo/common/time_struct_traits.h b/chromium/mojo/common/time_struct_traits.h deleted file mode 100644 index b480edb6488..00000000000 --- a/chromium/mojo/common/time_struct_traits.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 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_COMMON_TIME_STRUCT_TRAITS_H_ -#define MOJO_COMMON_TIME_STRUCT_TRAITS_H_ - -#include "base/time/time.h" -#include "mojo/common/time.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<common::mojom::TimeDataView, base::Time> { - static int64_t internal_value(const base::Time& time) { - return time.since_origin().InMicroseconds(); - } - - static bool Read(common::mojom::TimeDataView data, base::Time* time) { - *time = - base::Time() + base::TimeDelta::FromMicroseconds(data.internal_value()); - return true; - } -}; - -template <> -struct StructTraits<common::mojom::TimeDeltaDataView, base::TimeDelta> { - static int64_t microseconds(const base::TimeDelta& delta) { - return delta.InMicroseconds(); - } - - static bool Read(common::mojom::TimeDeltaDataView data, - base::TimeDelta* delta) { - *delta = base::TimeDelta::FromMicroseconds(data.microseconds()); - return true; - } -}; - -template <> -struct StructTraits<common::mojom::TimeTicksDataView, base::TimeTicks> { - static int64_t internal_value(const base::TimeTicks& time) { - return time.since_origin().InMicroseconds(); - } - - static bool Read(common::mojom::TimeTicksDataView data, - base::TimeTicks* time) { - *time = base::TimeTicks() + - base::TimeDelta::FromMicroseconds(data.internal_value()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_COMMON_TIME_STRUCT_TRAITS_H_ diff --git a/chromium/mojo/common/traits_test_service.mojom b/chromium/mojo/common/traits_test_service.mojom deleted file mode 100644 index 7659eea8abb..00000000000 --- a/chromium/mojo/common/traits_test_service.mojom +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -import "mojo/common/version.mojom"; - -// All functions on this interface echo their arguments to test StructTraits -// serialization and deserialization. -interface TraitsTestService { - [Sync] - EchoVersion(Version? v) => (Version? pass); -}; diff --git a/chromium/mojo/common/typemaps.gni b/chromium/mojo/common/typemaps.gni index 4d9e7f50592..f58f1128267 100644 --- a/chromium/mojo/common/typemaps.gni +++ b/chromium/mojo/common/typemaps.gni @@ -2,18 +2,4 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -typemaps = [ - "//mojo/common/file.typemap", - "//mojo/common/file_info.typemap", - "//mojo/common/file_path.typemap", - "//mojo/common/logfont_win.typemap", - "//mojo/common/memory_allocator_dump_cross_process_uid.typemap", - "//mojo/common/process_id.typemap", - "//mojo/common/read_only_buffer.typemap", - "//mojo/common/text_direction.typemap", - "//mojo/common/thread_priority.typemap", - "//mojo/common/time.typemap", - "//mojo/common/unguessable_token.typemap", - "//mojo/common/values.typemap", - "//mojo/common/version.typemap", -] +typemaps = [ "//mojo/common/values.typemap" ] diff --git a/chromium/mojo/common/unguessable_token.typemap b/chromium/mojo/common/unguessable_token.typemap deleted file mode 100644 index ec7b1942b34..00000000000 --- a/chromium/mojo/common/unguessable_token.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/unguessable_token.mojom" -public_headers = [ "//base/unguessable_token.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.UnguessableToken=base::UnguessableToken" ] diff --git a/chromium/mojo/common/version.mojom b/chromium/mojo/common/version.mojom deleted file mode 100644 index 6ddf6e6b8cd..00000000000 --- a/chromium/mojo/common/version.mojom +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::Version| in base/version.h -struct Version { - array<uint32> components; -}; diff --git a/chromium/mojo/common/version.typemap b/chromium/mojo/common/version.typemap deleted file mode 100644 index fa7fed9acfd..00000000000 --- a/chromium/mojo/common/version.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/version.mojom" -public_headers = [ "//base/version.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.Version=base::Version" ] diff --git a/chromium/mojo/edk/BUILD.gn b/chromium/mojo/edk/BUILD.gn new file mode 100644 index 00000000000..54841895df2 --- /dev/null +++ b/chromium/mojo/edk/BUILD.gn @@ -0,0 +1,245 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/nacl/config.gni") +import("//testing/test.gni") + +# Targets should depend on this if directly referencing the |mojo::edk| +# namespace. +component("edk") { + output_name = "mojo_edk" + + public = [ + "embedder/embedder.h", + "embedder/incoming_broker_client_invitation.h", + "embedder/outgoing_broker_client_invitation.h", + "embedder/peer_connection.h", + ] + + sources = [ + "embedder/embedder.cc", + "embedder/incoming_broker_client_invitation.cc", + "embedder/outgoing_broker_client_invitation.cc", + "embedder/peer_connection.cc", + ] + + defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] + + deps = [] + if (!is_nacl) { + deps += [ "//crypto" ] + } + + public_deps = [ + ":impl_for_edk", + "//mojo/public/cpp/system", + ] +} + +# Bits of the EDK library which do not depend on public API linkage. It is +# not allowed for this target or any of its transitive dependencies to depend +# on anything under //mojo/public beyond strict C type definitions. +# +# This is templated because it's consumed by both the ":edk" component library +# as well as the ":mojo_core" shared library. In the former case we want to +# export symbols, but in the latter case we don't. The template stamps out two +# nearly identical targets which differ only in what symbols they export. +template("core_impl_source_set") { + source_set(target_name) { + if (invoker.for_mojo_core) { + visibility = [ ":mojo_core" ] + } else { + visibility = [ ":edk" ] + } + + public = [ + "embedder/configuration.h", + "embedder/connection_params.h", + "embedder/entrypoints.h", + "embedder/named_platform_channel_pair.h", + "embedder/named_platform_handle.h", + "embedder/named_platform_handle_utils.h", + "embedder/platform_channel_pair.h", + "embedder/platform_handle.h", + "embedder/platform_handle_utils.h", + "embedder/process_error_callback.h", + "embedder/scoped_ipc_support.h", + "embedder/scoped_platform_handle.h", + "embedder/transport_protocol.h", + "system/channel.h", + "system/configuration.h", + "system/core.h", + "system/data_pipe_consumer_dispatcher.h", + "system/data_pipe_control_message.h", + "system/data_pipe_producer_dispatcher.h", + "system/dispatcher.h", + "system/handle_signals_state.h", + "system/handle_table.h", + "system/message_pipe_dispatcher.h", + "system/node_controller.h", + "system/options_validation.h", + "system/platform_handle_dispatcher.h", + "system/request_context.h", + "system/shared_buffer_dispatcher.h", + "system/user_message_impl.h", + ] + + sources = [ + "embedder/connection_params.cc", + "embedder/entrypoints.cc", + "embedder/named_platform_channel_pair_win.cc", + "embedder/named_platform_handle_utils_win.cc", + "embedder/platform_channel_pair.cc", + "embedder/platform_channel_pair_win.cc", + "embedder/platform_handle.cc", + "embedder/platform_handle_utils_win.cc", + "embedder/platform_shared_buffer.cc", + "embedder/scoped_ipc_support.cc", + "system/atomic_flag.h", + "system/broker.h", + "system/broker_host.cc", + "system/broker_host.h", + "system/broker_win.cc", + "system/channel.cc", + "system/channel_win.cc", + "system/configuration.cc", + "system/core.cc", + "system/data_pipe_consumer_dispatcher.cc", + "system/data_pipe_control_message.cc", + "system/data_pipe_producer_dispatcher.cc", + "system/dispatcher.cc", + "system/handle_table.cc", + "system/mapping_table.cc", + "system/mapping_table.h", + "system/message_pipe_dispatcher.cc", + "system/node_channel.cc", + "system/node_channel.h", + "system/node_controller.cc", + "system/platform_handle_dispatcher.cc", + "system/request_context.cc", + "system/shared_buffer_dispatcher.cc", + "system/user_message_impl.cc", + "system/watch.cc", + "system/watch.h", + "system/watcher_dispatcher.cc", + "system/watcher_dispatcher.h", + "system/watcher_set.cc", + "system/watcher_set.h", + ] + + if (is_fuchsia) { + sources += [ + "embedder/named_platform_handle_utils_fuchsia.cc", + "embedder/platform_channel_pair_fuchsia.cc", + "embedder/platform_handle_utils_fuchsia.cc", + "system/channel_fuchsia.cc", + ] + } else if (is_posix) { + public += [ "embedder/platform_channel_utils_posix.h" ] + + sources += [ + "embedder/platform_channel_pair_posix.cc", + "embedder/platform_channel_utils_posix.cc", + "embedder/platform_handle_utils_posix.cc", + ] + + if (!is_nacl || is_nacl_nonsfi) { + sources += [ + "system/broker_posix.cc", + "system/channel_posix.cc", + ] + } + + if (!is_nacl) { + sources += [ "embedder/named_platform_handle_utils_posix.cc" ] + } + } + + if (is_mac && !is_ios) { + sources += [ + "system/mach_port_relay.cc", + "system/mach_port_relay.h", + ] + } + + if (is_nacl && !is_nacl_nonsfi) { + sources -= [ + "embedder/platform_channel_utils_posix.cc", + "system/broker_host.cc", + ] + } + + defines = [] + if (!invoker.for_mojo_core) { + defines += [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] + } + + public_deps = [ + "//base", + "//mojo/edk/system/ports", + "//mojo/public/c/system:headers", + ] + + deps = [] + if (is_android) { + deps += [ "//third_party/ashmem" ] + } + if (!is_nacl) { + deps += [ "//crypto" ] + } + + if (is_win) { + cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()), + # which is uninteresting. + } + + # Use target_os == "chromeos" instead of is_chromeos because we need to + # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS. + if (is_android || target_os == "chromeos") { + defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ] + } + } +} + +core_impl_source_set("impl_for_edk") { + for_mojo_core = false +} + +if (is_chromeos || is_linux) { + core_impl_source_set("impl_for_mojo_core") { + for_mojo_core = true + } + + shared_library("mojo_core") { + sources = [ + "mojo_core.cc", + ] + deps = [ + ":impl_for_mojo_core", + "//build/config:exe_and_shlib_deps", + "//mojo/public/c/system:headers", + ] + if (!is_component_build) { + public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } + } + + test("mojo_core_unittests") { + sources = [ + "mojo_core_unittest.cc", + "run_all_core_unittests.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + "//mojo/public/c/system", + "//testing/gtest", + ] + + data_deps = [ + ":mojo_core", + ] + } +} diff --git a/chromium/mojo/edk/embedder/BUILD.gn b/chromium/mojo/edk/embedder/BUILD.gn index fa60f2f7471..7cf4f13ab2a 100644 --- a/chromium/mojo/edk/embedder/BUILD.gn +++ b/chromium/mojo/edk/embedder/BUILD.gn @@ -2,142 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/nacl/config.gni") - -source_set("headers") { - sources = [ - "configuration.h", - "connection_params.h", - "embedder.h", - "embedder_internal.h", - "incoming_broker_client_invitation.h", - "named_platform_channel_pair.h", - "named_platform_handle.h", - "named_platform_handle_utils.h", - "outgoing_broker_client_invitation.h", - "peer_connection.h", - "platform_channel_pair.h", - "platform_handle.h", - "platform_handle_utils.h", - "scoped_ipc_support.h", - "scoped_platform_handle.h", - "transport_protocol.h", - ] - - public_deps = [ - "//base", - "//mojo/public/cpp/system", - ] -} - -source_set("embedder") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - "//mojo/edk/system", - "//components/nacl:nacl", - ] - - sources = [ - "configuration.h", - "connection_params.cc", - "embedder.cc", - "entrypoints.cc", - "entrypoints.h", - "incoming_broker_client_invitation.cc", - "outgoing_broker_client_invitation.cc", - "peer_connection.cc", - "scoped_ipc_support.cc", - - # Test-only code: - # TODO(vtl): It's a little unfortunate that these end up in the same - # component as non-test-only code. In the static build, this code should - # hopefully be dead-stripped. - "test_embedder.cc", - "test_embedder.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - deps = [ - "//mojo/edk/system/ports", - ] - - public_deps = [ - ":headers", - ":platform", - "//base", - "//mojo/public/cpp/system", - ] - - if (!is_nacl) { - deps += [ "//crypto" ] - } -} - -source_set("platform") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - ":embedder", - "//mojo/edk/system", - ] - - sources = [ - "named_platform_channel_pair.h", - "named_platform_channel_pair_win.cc", - "named_platform_handle.h", - "named_platform_handle_utils.h", - "named_platform_handle_utils_win.cc", - "platform_channel_pair.cc", - "platform_channel_pair.h", - "platform_channel_pair_win.cc", - "platform_handle.cc", - "platform_handle.h", - "platform_handle_utils.h", - "platform_handle_utils_win.cc", - "platform_shared_buffer.cc", - "platform_shared_buffer.h", - "scoped_platform_handle.h", - ] - - if (is_fuchsia) { - sources += [ - "named_platform_handle_utils_fuchsia.cc", - "platform_channel_pair_fuchsia.cc", - "platform_handle_utils_fuchsia.cc", - ] - } else if (is_posix) { - sources += [ - "platform_channel_pair_posix.cc", - "platform_channel_utils_posix.cc", - "platform_channel_utils_posix.h", - "platform_handle_utils_posix.cc", - ] - if (!is_nacl) { - sources += [ "named_platform_handle_utils_posix.cc" ] - } - } - - if (is_nacl && !is_nacl_nonsfi) { - sources -= [ "platform_channel_utils_posix.cc" ] - } - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] - - if (is_android) { - deps += [ "//third_party/ashmem" ] - } -} - source_set("embedder_unittests") { testonly = true @@ -149,14 +13,14 @@ source_set("embedder_unittests") { "platform_shared_buffer_unittest.cc", ] - if (is_posix && !is_fuchsia) { + if (is_posix) { sources += [ "platform_channel_pair_posix_unittest.cc" ] } deps = [ "//base", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/edk/system:test_utils", "//mojo/edk/test:test_support", "//testing/gtest", diff --git a/chromium/mojo/edk/embedder/README.md b/chromium/mojo/edk/embedder/README.md index b6e0a4490b1..30dd15118f3 100644 --- a/chromium/mojo/edk/embedder/README.md +++ b/chromium/mojo/edk/embedder/README.md @@ -8,10 +8,9 @@ This document is a subset of the [Mojo documentation](/mojo). The Mojo EDK is a (binary-unstable) API which enables a process to use Mojo both internally and for IPC to other Mojo-embedding processes. -Using any of the API surface in `//mojo/edk/embedder` requires (somewhat -confusingly) a direct dependency on the GN `//mojo/edk/system` target. Despite -this fact, you should never reference any of the headers in `mojo/edk/system` -directly, as everything there is considered to be an internal detail of the EDK. +Using any of the API surface in `//mojo/edk/embedder` requires a direct +dependency on the GN `//mojo/edk` target. Headers in `mojo/edk/system` are +reserved for internal use by the EDK only. **NOTE:** Unless you are introducing a new binary entry point into the system (*e.g.,* a new executable with a new `main()` definition), you probably don't @@ -139,9 +138,9 @@ int main(int argc, char** argv) { base::ProcessHandle child_handle = LaunchCoolChildProcess(channel.PassClientHandle()); - // At this point it's safe for |child| to go out of scope and nothing will - // break. - child.Connect(child_handle, channel.PassServerHandle()); + // At this point it's safe for |invitation| to go out of scope and nothing + // will break. + invitation.Send(child_handle, channel.PassServerHandle()); return 0; } diff --git a/chromium/mojo/edk/embedder/embedder.cc b/chromium/mojo/edk/embedder/embedder.cc index 7cf5fb6afc8..1148ac3030c 100644 --- a/chromium/mojo/edk/embedder/embedder.cc +++ b/chromium/mojo/edk/embedder/embedder.cc @@ -13,11 +13,11 @@ #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/task_runner.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/entrypoints.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/node_controller.h" +#include "mojo/public/c/system/thunks.h" #if !defined(OS_NACL) #include "crypto/random.h" @@ -26,24 +26,10 @@ namespace mojo { namespace edk { -class Core; -class PlatformSupport; - -namespace internal { - -Core* g_core; - -Core* GetCore() { return g_core; } - -} // namespace internal - void Init(const Configuration& configuration) { - MojoSystemThunks thunks = MakeSystemThunks(); - size_t expected_size = MojoEmbedderSetSystemThunks(&thunks); - DCHECK_EQ(expected_size, sizeof(thunks)); - internal::g_configuration = configuration; - internal::g_core = new Core; + InitializeCore(); + MojoEmbedderSetSystemThunks(&GetSystemThunks()); } void Init() { @@ -51,7 +37,7 @@ void Init() { } void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) { - internal::g_core->SetDefaultProcessErrorCallback(callback); + Core::Get()->SetDefaultProcessErrorCallback(callback); } std::string GenerateRandomToken() { @@ -68,14 +54,14 @@ std::string GenerateRandomToken() { MojoResult CreatePlatformHandleWrapper( ScopedPlatformHandle platform_handle, MojoHandle* platform_handle_wrapper_handle) { - return internal::g_core->CreatePlatformHandleWrapper( + return Core::Get()->CreatePlatformHandleWrapper( std::move(platform_handle), platform_handle_wrapper_handle); } MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, ScopedPlatformHandle* platform_handle) { - return internal::g_core->PassWrappedPlatformHandle( - platform_handle_wrapper_handle, platform_handle); + return Core::Get()->PassWrappedPlatformHandle(platform_handle_wrapper_handle, + platform_handle); } MojoResult CreateSharedBufferWrapper( @@ -83,8 +69,8 @@ MojoResult CreateSharedBufferWrapper( size_t num_bytes, bool read_only, MojoHandle* mojo_wrapper_handle) { - return internal::g_core->CreateSharedBufferWrapper( - shared_memory_handle, num_bytes, read_only, mojo_wrapper_handle); + return Core::Get()->CreateSharedBufferWrapper(shared_memory_handle, num_bytes, + read_only, mojo_wrapper_handle); } MojoResult PassSharedMemoryHandle( @@ -92,23 +78,22 @@ MojoResult PassSharedMemoryHandle( base::SharedMemoryHandle* shared_memory_handle, size_t* num_bytes, bool* read_only) { - return internal::g_core->PassSharedMemoryHandle( - mojo_handle, shared_memory_handle, num_bytes, read_only); + return Core::Get()->PassSharedMemoryHandle(mojo_handle, shared_memory_handle, + num_bytes, read_only); } MojoResult SetProperty(MojoPropertyType type, const void* value) { - CHECK(internal::g_core); - return internal::g_core->SetProperty(type, value); + return Core::Get()->SetProperty(type, value); } scoped_refptr<base::TaskRunner> GetIOTaskRunner() { - return internal::g_core->GetNodeController()->io_task_runner(); + return Core::Get()->GetNodeController()->io_task_runner(); } #if defined(OS_MACOSX) && !defined(OS_IOS) void SetMachPortProvider(base::PortProvider* port_provider) { DCHECK(port_provider); - internal::g_core->SetMachPortProvider(port_provider); + Core::Get()->SetMachPortProvider(port_provider); } #endif diff --git a/chromium/mojo/edk/embedder/embedder_internal.h b/chromium/mojo/edk/embedder/embedder_internal.h deleted file mode 100644 index 7deeca157d1..00000000000 --- a/chromium/mojo/edk/embedder/embedder_internal.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This header contains internal details for the *implementation* of the -// embedder API. It should not be included by any public header (nor by users of -// the embedder API). - -#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ -#define MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ - -#include <stdint.h> - -#include "mojo/edk/system/system_impl_export.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { - -namespace edk { - -class Broker; -class Core; -class ProcessDelegate; - -namespace internal { - -// Instance of |Broker| to use. -extern Broker* g_broker; - -// Instance of |Core| used by the system functions (|Mojo...()|). -extern MOJO_SYSTEM_IMPL_EXPORT Core* g_core; -extern base::TaskRunner* g_delegate_thread_task_runner; -extern ProcessDelegate* g_process_delegate; - -} // namespace internal - -} // namepace edk - -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ diff --git a/chromium/mojo/edk/embedder/embedder_unittest.cc b/chromium/mojo/edk/embedder/embedder_unittest.cc index 6cfdc820fa8..6f91de29c98 100644 --- a/chromium/mojo/edk/embedder/embedder_unittest.cc +++ b/chromium/mojo/edk/embedder/embedder_unittest.cc @@ -31,7 +31,6 @@ #include "mojo/edk/embedder/outgoing_broker_client_invitation.h" #include "mojo/edk/embedder/peer_connection.h" #include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/test_embedder.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/test/mojo_test_base.h" #include "mojo/public/c/system/core.h" diff --git a/chromium/mojo/edk/embedder/entrypoints.cc b/chromium/mojo/edk/embedder/entrypoints.cc index 6ff95b39915..d079178ca8c 100644 --- a/chromium/mojo/edk/embedder/entrypoints.cc +++ b/chromium/mojo/edk/embedder/entrypoints.cc @@ -6,7 +6,6 @@ #include <stdint.h> -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" #include "mojo/public/c/system/buffer.h" #include "mojo/public/c/system/data_pipe.h" @@ -14,11 +13,17 @@ #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/platform_handle.h" -using mojo::edk::internal::g_core; +namespace { + +mojo::edk::Core* g_core; -// Definitions of the system functions. extern "C" { +MojoResult MojoInitializeImpl(const struct MojoInitializeOptions* options) { + NOTREACHED() << "Do not call MojoInitialize() as an EDK embedder!"; + return MOJO_RESULT_OK; +} + MojoTimeTicks MojoGetTimeTicksNowImpl() { return g_core->GetTimeTicksNow(); } @@ -33,96 +38,90 @@ MojoResult MojoQueryHandleSignalsStateImpl( return g_core->QueryHandleSignalsState(handle, signals_state); } -MojoResult MojoCreateWatcherImpl(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { - return g_core->CreateWatcher(callback, watcher_handle); +MojoResult MojoCreateTrapImpl(MojoTrapEventHandler handler, + const MojoCreateTrapOptions* options, + MojoHandle* trap_handle) { + return g_core->CreateTrap(handler, options, trap_handle); } -MojoResult MojoArmWatcherImpl(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - return g_core->ArmWatcher(watcher_handle, num_ready_contexts, ready_contexts, - ready_results, ready_signals_states); +MojoResult MojoArmTrapImpl(MojoHandle trap_handle, + const MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals_states) { + return g_core->ArmTrap(trap_handle, options, num_ready_triggers, + ready_triggers, ready_results, ready_signals_states); } -MojoResult MojoWatchImpl(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context) { - return g_core->Watch(watcher_handle, handle, signals, condition, context); +MojoResult MojoAddTriggerImpl(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const MojoAddTriggerOptions* options) { + return g_core->AddTrigger(trap_handle, handle, signals, condition, context, + options); } -MojoResult MojoCancelWatchImpl(MojoHandle watcher_handle, uintptr_t context) { - return g_core->CancelWatch(watcher_handle, context); +MojoResult MojoRemoveTriggerImpl(MojoHandle trap_handle, + uintptr_t context, + const MojoRemoveTriggerOptions* options) { + return g_core->RemoveTrigger(trap_handle, context, options); } -MojoResult MojoCreateMessageImpl(MojoMessageHandle* message) { - return g_core->CreateMessage(message); -} - -MojoResult MojoDestroyMessageImpl(MojoMessageHandle message) { - return g_core->DestroyMessage(message); +MojoResult MojoCreateMessageImpl(const MojoCreateMessageOptions* options, + MojoMessageHandle* message) { + return g_core->CreateMessage(options, message); } -MojoResult MojoSerializeMessageImpl(MojoMessageHandle message) { - return g_core->SerializeMessage(message); -} - -MojoResult MojoAttachSerializedMessageBufferImpl(MojoMessageHandle message, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size) { - return g_core->AttachSerializedMessageBuffer( - message, payload_size, handles, num_handles, buffer, buffer_size); -} - -MojoResult MojoExtendSerializedMessagePayloadImpl(MojoMessageHandle message, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** new_buffer, - uint32_t* new_buffer_size) { - return g_core->ExtendSerializedMessagePayload(message, new_payload_size, - handles, num_handles, - new_buffer, new_buffer_size); +MojoResult MojoSerializeMessageImpl( + MojoMessageHandle message, + const MojoSerializeMessageOptions* options) { + return g_core->SerializeMessage(message, options); } -MojoResult MojoCommitSerializedMessageContentsImpl(MojoMessageHandle message, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size) { - return g_core->CommitSerializedMessageContents(message, final_payload_size, - buffer, buffer_size); +MojoResult MojoDestroyMessageImpl(MojoMessageHandle message) { + return g_core->DestroyMessage(message); } -MojoResult MojoGetSerializedMessageContentsImpl( +MojoResult MojoAppendMessageDataImpl( MojoMessageHandle message, + uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const MojoAppendMessageDataOptions* options, void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags) { - return g_core->GetSerializedMessageContents(message, buffer, num_bytes, - handles, num_handles, flags); + uint32_t* buffer_size) { + return g_core->AppendMessageData(message, additional_payload_size, handles, + num_handles, options, buffer, buffer_size); +} + +MojoResult MojoGetMessageDataImpl(MojoMessageHandle message, + const MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles) { + return g_core->GetMessageData(message, options, buffer, num_bytes, handles, + num_handles); } -MojoResult MojoAttachMessageContextImpl( +MojoResult MojoSetMessageContextImpl( MojoMessageHandle message, uintptr_t context, MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor) { - return g_core->AttachMessageContext(message, context, serializer, destructor); + MojoMessageContextDestructor destructor, + const MojoSetMessageContextOptions* options) { + return g_core->SetMessageContext(message, context, serializer, destructor, + options); } -MojoResult MojoGetMessageContextImpl(MojoMessageHandle message, - uintptr_t* context, - MojoGetMessageContextFlags flags) { - return g_core->GetMessageContext(message, context, flags); +MojoResult MojoGetMessageContextImpl( + MojoMessageHandle message, + const MojoGetMessageContextOptions* options, + uintptr_t* context) { + return g_core->GetMessageContext(message, options, context); } MojoResult MojoCreateMessagePipeImpl( @@ -199,7 +198,7 @@ MojoResult MojoEndReadDataImpl(MojoHandle data_pipe_consumer_handle, } MojoResult MojoCreateSharedBufferImpl( - const struct MojoCreateSharedBufferOptions* options, + const MojoCreateSharedBufferOptions* options, uint64_t num_bytes, MojoHandle* shared_buffer_handle) { return g_core->CreateSharedBuffer(options, num_bytes, shared_buffer_handle); @@ -207,7 +206,7 @@ MojoResult MojoCreateSharedBufferImpl( MojoResult MojoDuplicateBufferHandleImpl( MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, + const MojoDuplicateBufferHandleOptions* options, MojoHandle* new_buffer_handle) { return g_core->DuplicateBufferHandle(buffer_handle, options, new_buffer_handle); @@ -225,6 +224,12 @@ MojoResult MojoUnmapBufferImpl(void* buffer) { return g_core->UnmapBuffer(buffer); } +MojoResult MojoGetBufferInfoImpl(MojoHandle buffer_handle, + const MojoSharedBufferOptions* options, + MojoSharedBufferInfo* info) { + return g_core->GetBufferInfo(buffer_handle, options, info); +} + MojoResult MojoWrapPlatformHandleImpl(const MojoPlatformHandle* platform_handle, MojoHandle* mojo_handle) { return g_core->WrapPlatformHandle(platform_handle, mojo_handle); @@ -267,49 +272,61 @@ MojoResult MojoGetPropertyImpl(MojoPropertyType type, void* value) { } // extern "C" +MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks), + MojoInitializeImpl, + MojoGetTimeTicksNowImpl, + MojoCloseImpl, + MojoQueryHandleSignalsStateImpl, + MojoCreateMessagePipeImpl, + MojoWriteMessageImpl, + MojoReadMessageImpl, + MojoCreateDataPipeImpl, + MojoWriteDataImpl, + MojoBeginWriteDataImpl, + MojoEndWriteDataImpl, + MojoReadDataImpl, + MojoBeginReadDataImpl, + MojoEndReadDataImpl, + MojoCreateSharedBufferImpl, + MojoDuplicateBufferHandleImpl, + MojoMapBufferImpl, + MojoUnmapBufferImpl, + MojoGetBufferInfoImpl, + MojoCreateTrapImpl, + MojoAddTriggerImpl, + MojoRemoveTriggerImpl, + MojoArmTrapImpl, + MojoFuseMessagePipesImpl, + MojoCreateMessageImpl, + MojoDestroyMessageImpl, + MojoSerializeMessageImpl, + MojoAppendMessageDataImpl, + MojoGetMessageDataImpl, + MojoSetMessageContextImpl, + MojoGetMessageContextImpl, + MojoWrapPlatformHandleImpl, + MojoUnwrapPlatformHandleImpl, + MojoWrapPlatformSharedBufferHandleImpl, + MojoUnwrapPlatformSharedBufferHandleImpl, + MojoNotifyBadMessageImpl, + MojoGetPropertyImpl}; + +} // namespace + namespace mojo { namespace edk { -MojoSystemThunks MakeSystemThunks() { - MojoSystemThunks system_thunks = {sizeof(MojoSystemThunks), - MojoGetTimeTicksNowImpl, - MojoCloseImpl, - MojoQueryHandleSignalsStateImpl, - MojoCreateMessagePipeImpl, - MojoWriteMessageImpl, - MojoReadMessageImpl, - MojoCreateDataPipeImpl, - MojoWriteDataImpl, - MojoBeginWriteDataImpl, - MojoEndWriteDataImpl, - MojoReadDataImpl, - MojoBeginReadDataImpl, - MojoEndReadDataImpl, - MojoCreateSharedBufferImpl, - MojoDuplicateBufferHandleImpl, - MojoMapBufferImpl, - MojoUnmapBufferImpl, - MojoCreateWatcherImpl, - MojoWatchImpl, - MojoCancelWatchImpl, - MojoArmWatcherImpl, - MojoFuseMessagePipesImpl, - MojoCreateMessageImpl, - MojoDestroyMessageImpl, - MojoSerializeMessageImpl, - MojoAttachSerializedMessageBufferImpl, - MojoExtendSerializedMessagePayloadImpl, - MojoCommitSerializedMessageContentsImpl, - MojoGetSerializedMessageContentsImpl, - MojoAttachMessageContextImpl, - MojoGetMessageContextImpl, - MojoWrapPlatformHandleImpl, - MojoUnwrapPlatformHandleImpl, - MojoWrapPlatformSharedBufferHandleImpl, - MojoUnwrapPlatformSharedBufferHandleImpl, - MojoNotifyBadMessageImpl, - MojoGetPropertyImpl}; - return system_thunks; +// static +Core* Core::Get() { + return g_core; +} + +void InitializeCore() { + g_core = new Core; +} + +const MojoSystemThunks& GetSystemThunks() { + return g_thunks; } } // namespace edk diff --git a/chromium/mojo/edk/embedder/entrypoints.h b/chromium/mojo/edk/embedder/entrypoints.h index 8e448c156f7..63299a627ce 100644 --- a/chromium/mojo/edk/embedder/entrypoints.h +++ b/chromium/mojo/edk/embedder/entrypoints.h @@ -11,10 +11,13 @@ namespace mojo { namespace edk { -// Creates a MojoSystemThunks struct populated with the EDK's implementation of +// Initializes the global Core object. +MOJO_SYSTEM_IMPL_EXPORT void InitializeCore(); + +// Returns a MojoSystemThunks struct populated with the EDK's implementation of // each function. This may be used by embedders to populate thunks for // application loading. -MOJO_SYSTEM_IMPL_EXPORT MojoSystemThunks MakeSystemThunks(); +MOJO_SYSTEM_IMPL_EXPORT const MojoSystemThunks& GetSystemThunks(); } // namespace edk } // namespace mojo diff --git a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc b/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc index 80a3a264c24..8c0b693de7d 100644 --- a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc +++ b/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc @@ -7,7 +7,6 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/core.h" @@ -38,13 +37,13 @@ IncomingBrokerClientInvitation::AcceptFromCommandLine( ScopedMessagePipeHandle IncomingBrokerClientInvitation::ExtractMessagePipe( const std::string& name) { - return internal::g_core->ExtractMessagePipeFromInvitation(name); + return ScopedMessagePipeHandle( + MessagePipeHandle(Core::Get()->ExtractMessagePipeFromInvitation(name))); } IncomingBrokerClientInvitation::IncomingBrokerClientInvitation( ConnectionParams params) { - DCHECK(internal::g_core); - internal::g_core->AcceptBrokerClientInvitation(std::move(params)); + Core::Get()->AcceptBrokerClientInvitation(std::move(params)); } } // namespace edk diff --git a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc b/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc index 718b8d26508..6c9ae1ed398 100644 --- a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc +++ b/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc @@ -5,7 +5,6 @@ #include "mojo/edk/embedder/outgoing_broker_client_invitation.h" #include "base/logging.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/ports/port_ref.h" @@ -14,22 +13,20 @@ namespace mojo { namespace edk { -OutgoingBrokerClientInvitation::OutgoingBrokerClientInvitation() { - DCHECK(internal::g_core); -} +OutgoingBrokerClientInvitation::OutgoingBrokerClientInvitation() = default; OutgoingBrokerClientInvitation::~OutgoingBrokerClientInvitation() { RequestContext request_context; for (auto& entry : attached_ports_) - internal::g_core->GetNodeController()->ClosePort(entry.second); + Core::Get()->GetNodeController()->ClosePort(entry.second); } ScopedMessagePipeHandle OutgoingBrokerClientInvitation::AttachMessagePipe( const std::string& name) { DCHECK(!sent_); ports::PortRef port; - ScopedMessagePipeHandle pipe = - internal::g_core->CreatePartialMessagePipe(&port); + ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle( + MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&port))); attached_ports_.emplace_back(name, port); return pipe; } @@ -42,8 +39,8 @@ OutgoingBrokerClientInvitation::ExtractInProcessMessagePipe( // a single entry. for (auto it = attached_ports_.begin(); it != attached_ports_.end(); ++it) { if (it->first == name) { - ScopedMessagePipeHandle pipe = - internal::g_core->CreatePartialMessagePipe(it->second); + ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle( + MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(it->second))); attached_ports_.erase(it); return pipe; } @@ -59,8 +56,8 @@ void OutgoingBrokerClientInvitation::Send( const ProcessErrorCallback& error_callback) { DCHECK(!sent_); sent_ = true; - internal::g_core->SendBrokerClientInvitation( - target_process, std::move(params), attached_ports_, error_callback); + Core::Get()->SendBrokerClientInvitation(target_process, std::move(params), + attached_ports_, error_callback); attached_ports_.clear(); } diff --git a/chromium/mojo/edk/embedder/peer_connection.cc b/chromium/mojo/edk/embedder/peer_connection.cc index 77b26488837..85344114e90 100644 --- a/chromium/mojo/edk/embedder/peer_connection.cc +++ b/chromium/mojo/edk/embedder/peer_connection.cc @@ -4,7 +4,6 @@ #include "mojo/edk/embedder/peer_connection.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" namespace mojo { @@ -14,7 +13,7 @@ PeerConnection::PeerConnection() = default; PeerConnection::~PeerConnection() { if (is_connected_) - internal::g_core->ClosePeerConnection(connection_id_); + Core::Get()->ClosePeerConnection(connection_id_); } ScopedMessagePipeHandle PeerConnection::Connect(ConnectionParams params) { @@ -22,9 +21,9 @@ ScopedMessagePipeHandle PeerConnection::Connect(ConnectionParams params) { is_connected_ = true; ports::PortRef peer_port; - auto pipe = internal::g_core->CreatePartialMessagePipe(&peer_port); - connection_id_ = - internal::g_core->ConnectToPeer(std::move(params), peer_port); + auto pipe = ScopedMessagePipeHandle( + MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&peer_port))); + connection_id_ = Core::Get()->ConnectToPeer(std::move(params), peer_port); return pipe; } diff --git a/chromium/mojo/edk/embedder/process_error_callback.h b/chromium/mojo/edk/embedder/process_error_callback.h new file mode 100644 index 00000000000..53234def1f4 --- /dev/null +++ b/chromium/mojo/edk/embedder/process_error_callback.h @@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_ +#define MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_ + +#include <string> + +#include "base/callback.h" + +namespace mojo { +namespace edk { + +using ProcessErrorCallback = + base::RepeatingCallback<void(const std::string& error)>; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_ diff --git a/chromium/mojo/edk/embedder/scoped_ipc_support.cc b/chromium/mojo/edk/embedder/scoped_ipc_support.cc index 03813bbe346..a0231726d8f 100644 --- a/chromium/mojo/edk/embedder/scoped_ipc_support.cc +++ b/chromium/mojo/edk/embedder/scoped_ipc_support.cc @@ -8,8 +8,6 @@ #include "base/bind_helpers.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_restrictions.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" namespace mojo { @@ -18,8 +16,7 @@ namespace edk { namespace { void ShutdownIPCSupport(const base::Closure& callback) { - DCHECK(internal::g_core); - internal::g_core->RequestShutdown(callback); + Core::Get()->RequestShutdown(callback); } } // namespace @@ -27,8 +24,7 @@ void ShutdownIPCSupport(const base::Closure& callback) { ScopedIPCSupport::ScopedIPCSupport( scoped_refptr<base::TaskRunner> io_thread_task_runner, ShutdownPolicy shutdown_policy) : shutdown_policy_(shutdown_policy) { - DCHECK(internal::g_core); - internal::g_core->SetIOTaskRunner(io_thread_task_runner); + Core::Get()->SetIOTaskRunner(io_thread_task_runner); } ScopedIPCSupport::~ScopedIPCSupport() { diff --git a/chromium/mojo/edk/embedder/test_embedder.cc b/chromium/mojo/edk/embedder/test_embedder.cc deleted file mode 100644 index 9658010586f..00000000000 --- a/chromium/mojo/edk/embedder/test_embedder.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/test_embedder.h" - -#include <memory> - -#include "base/logging.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/handle_table.h" - -namespace mojo { - -namespace edk { -namespace internal { - -bool ShutdownCheckNoLeaks(Core* core) { - std::vector<MojoHandle> leaked_handles; - core->GetActiveHandlesForTest(&leaked_handles); - if (leaked_handles.empty()) - return true; - for (auto handle : leaked_handles) - LOG(ERROR) << "Mojo embedder shutdown: Leaking handle " << handle; - return false; -} - -} // namespace internal - -namespace test { - -bool Shutdown() { - CHECK(internal::g_core); - bool rv = internal::ShutdownCheckNoLeaks(internal::g_core); - delete internal::g_core; - internal::g_core = nullptr; - - return rv; -} - -} // namespace test -} // namespace edk - -} // namespace mojo diff --git a/chromium/mojo/edk/embedder/test_embedder.h b/chromium/mojo/edk/embedder/test_embedder.h deleted file mode 100644 index c64ba179e1d..00000000000 --- a/chromium/mojo/edk/embedder/test_embedder.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ -#define MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ - -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { -namespace test { - -// This shuts down the global, singleton instance. (Note: "Real" embedders are -// not expected to ever shut down this instance. This |Shutdown()| function will -// do more work to ensure that tests don't leak, etc.) Returns true if there -// were no problems, false if there were leaks -- i.e., handles still open -- or -// any other problems. -// -// Note: It is up to the caller to ensure that there are not outstanding -// callbacks from |CreateChannel()| before calling this. -MOJO_SYSTEM_IMPL_EXPORT bool Shutdown(); - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ diff --git a/chromium/mojo/edk/mojo_core.cc b/chromium/mojo/edk/mojo_core.cc new file mode 100644 index 00000000000..b0c652750bf --- /dev/null +++ b/chromium/mojo/edk/mojo_core.cc @@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/time/time.h" +#include "mojo/edk/embedder/entrypoints.h" +#include "mojo/edk/system/core.h" +#include "mojo/public/c/system/core.h" +#include "mojo/public/c/system/thunks.h" + +extern "C" { + +namespace { + +MojoResult InitializeImpl(const struct MojoInitializeOptions* options) { + mojo::edk::InitializeCore(); + return MOJO_RESULT_OK; +} + +MojoSystemThunks g_thunks = {0}; + +} // namespace + +#if defined(WIN32) +#define EXPORT_FROM_MOJO_CORE __declspec(dllexport) +#else +#define EXPORT_FROM_MOJO_CORE __attribute__((visibility("default"))) +#endif + +EXPORT_FROM_MOJO_CORE void MojoGetSystemThunks(MojoSystemThunks* thunks) { + if (!g_thunks.size) { + g_thunks = mojo::edk::GetSystemThunks(); + g_thunks.Initialize = InitializeImpl; + } + + // Since this is the first version of the library, no valid system API + // implementation can request fewer thunks than we have available. + CHECK_GE(thunks->size, g_thunks.size); + memcpy(thunks, &g_thunks, g_thunks.size); +} + +} // extern "C" diff --git a/chromium/mojo/edk/mojo_core_unittest.cc b/chromium/mojo/edk/mojo_core_unittest.cc new file mode 100644 index 00000000000..ddd24d230d5 --- /dev/null +++ b/chromium/mojo/edk/mojo_core_unittest.cc @@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/c/system/core.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +TEST(MojoCoreTest, SanityCheck) { + // Exercises some APIs against the mojo_core library and expects them to work + // as intended. + + MojoHandle a, b; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &a, &b)); + + MojoMessageHandle m; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &m)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoSetMessageContext(m, 42, nullptr, nullptr, nullptr)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWriteMessage(a, m, MOJO_WRITE_MESSAGE_FLAG_NONE)); + m = MOJO_MESSAGE_HANDLE_INVALID; + + MojoHandleSignalsState state; + EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); + EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); + + EXPECT_EQ(MOJO_RESULT_OK, + MojoReadMessage(b, &m, MOJO_READ_MESSAGE_FLAG_NONE)); + + uintptr_t context = 0; + EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageContext(m, nullptr, &context)); + EXPECT_EQ(42u, context); + + EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(m)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); +} + +} // namespace diff --git a/chromium/mojo/edk/run_all_core_unittests.cc b/chromium/mojo/edk/run_all_core_unittests.cc new file mode 100644 index 00000000000..92dcafc9619 --- /dev/null +++ b/chromium/mojo/edk/run_all_core_unittests.cc @@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/test/launcher/unit_test_launcher.h" +#include "base/test/test_suite.h" +#include "build/build_config.h" +#include "mojo/public/c/system/core.h" + +int main(int argc, char** argv) { + base::TestSuite test_suite(argc, argv); + + CHECK_EQ(MOJO_RESULT_OK, MojoInitialize(nullptr)); + return base::LaunchUnitTests( + argc, argv, + base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); +} diff --git a/chromium/mojo/edk/system/BUILD.gn b/chromium/mojo/edk/system/BUILD.gn index dfe6940ddc2..6387dcda11b 100644 --- a/chromium/mojo/edk/system/BUILD.gn +++ b/chromium/mojo/edk/system/BUILD.gn @@ -10,114 +10,6 @@ if (is_android) { import("//build/config/android/rules.gni") } -component("system") { - output_name = "mojo_system_impl" - - sources = [ - "atomic_flag.h", - "broker.h", - "broker_host.cc", - "broker_host.h", - "broker_win.cc", - "channel.cc", - "channel.h", - "channel_win.cc", - "configuration.cc", - "configuration.h", - "core.cc", - "core.h", - "data_pipe_consumer_dispatcher.cc", - "data_pipe_consumer_dispatcher.h", - "data_pipe_control_message.cc", - "data_pipe_control_message.h", - "data_pipe_producer_dispatcher.cc", - "data_pipe_producer_dispatcher.h", - "dispatcher.cc", - "dispatcher.h", - "handle_signals_state.h", - "handle_table.cc", - "handle_table.h", - "mapping_table.cc", - "mapping_table.h", - "message_pipe_dispatcher.cc", - "message_pipe_dispatcher.h", - "node_channel.cc", - "node_channel.h", - "node_controller.cc", - "node_controller.h", - "options_validation.h", - "platform_handle_dispatcher.cc", - "platform_handle_dispatcher.h", - "request_context.cc", - "request_context.h", - "shared_buffer_dispatcher.cc", - "shared_buffer_dispatcher.h", - "user_message_impl.cc", - "user_message_impl.h", - "watch.cc", - "watch.h", - "watcher_dispatcher.cc", - "watcher_dispatcher.h", - "watcher_set.cc", - "watcher_set.h", - ] - - if (is_mac && !is_ios) { - sources += [ - "mach_port_relay.cc", - "mach_port_relay.h", - ] - } - - if (is_fuchsia) { - sources += [ "channel_fuchsia.cc" ] - } else if (is_posix) { - sources += [ - "broker_posix.cc", - "channel_posix.cc", - ] - } - - if (is_nacl && !is_nacl_nonsfi) { - sources -= [ - "broker_host.cc", - "broker_posix.cc", - "channel_posix.cc", - ] - } - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - "//mojo/edk/embedder", - "//mojo/edk/embedder:platform", - "//mojo/edk/system/ports", - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] - - if (!is_nacl) { - deps += [ "//crypto" ] - } - - if (is_win) { - cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()), - # which is uninteresting. - } - - # Use target_os == "chromeos" instead of is_chromeos because we need to - # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS. - if (is_android || target_os == "chromeos") { - defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ] - } - - allow_circular_includes_from = [ "//mojo/edk/embedder" ] -} - source_set("test_utils") { testonly = true @@ -154,7 +46,7 @@ source_set("test_sources") { "shared_buffer_dispatcher_unittest.cc", "shared_buffer_unittest.cc", "signals_unittest.cc", - "watcher_unittest.cc", + "trap_unittest.cc", ] if (!is_ios) { @@ -169,8 +61,8 @@ source_set("test_sources") { ":test_utils", "//base", "//base/test:test_support", + "//mojo/edk", "//mojo/edk/embedder:embedder_unittests", - "//mojo/edk/system", "//mojo/edk/system/ports:tests", "//mojo/edk/test:run_all_unittests", "//mojo/edk/test:test_support", diff --git a/chromium/mojo/edk/system/broker_host.h b/chromium/mojo/edk/system/broker_host.h index ccfbce84a4e..3f1b7ce1bef 100644 --- a/chromium/mojo/edk/system/broker_host.h +++ b/chromium/mojo/edk/system/broker_host.h @@ -12,7 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/process/process_handle.h" #include "base/strings/string_piece.h" -#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_error_callback.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/channel.h" diff --git a/chromium/mojo/edk/system/broker_posix.cc b/chromium/mojo/edk/system/broker_posix.cc index fcca4901bc9..88695e9b646 100644 --- a/chromium/mojo/edk/system/broker_posix.cc +++ b/chromium/mojo/edk/system/broker_posix.cc @@ -10,7 +10,6 @@ #include <utility> #include "base/logging.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_channel_utils_posix.h" #include "mojo/edk/embedder/platform_handle_utils.h" #include "mojo/edk/embedder/platform_shared_buffer.h" diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/edk/system/channel.cc index eacdf5ce9dc..41ff3ee3509 100644 --- a/chromium/mojo/edk/system/channel.cc +++ b/chromium/mojo/edk/system/channel.cc @@ -16,7 +16,6 @@ #include "base/numerics/safe_math.h" #include "base/process/process_handle.h" #include "build/build_config.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" diff --git a/chromium/mojo/edk/system/channel_fuchsia.cc b/chromium/mojo/edk/system/channel_fuchsia.cc index ea1f817b3ee..31ddb9486c1 100644 --- a/chromium/mojo/edk/system/channel_fuchsia.cc +++ b/chromium/mojo/edk/system/channel_fuchsia.cc @@ -14,11 +14,13 @@ #include "base/bind.h" #include "base/containers/circular_deque.h" #include "base/files/scoped_file.h" +#include "base/fuchsia/scoped_zx_handle.h" #include "base/location.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_for_io.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" @@ -184,7 +186,7 @@ class MessageView { class ChannelFuchsia : public Channel, public base::MessageLoop::DestructionObserver, - public base::MessageLoopForIO::ZxHandleWatcher { + public base::MessagePumpForIO::ZxHandleWatcher { public: ChannelFuchsia(Delegate* delegate, ConnectionParams connection_params, @@ -201,14 +203,14 @@ class ChannelFuchsia : public Channel, StartOnIOThread(); } else { io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelFuchsia::StartOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelFuchsia::StartOnIOThread, this)); } } void ShutDownImpl() override { // Always shut down asynchronously when called through the public interface. io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelFuchsia::ShutDownOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelFuchsia::ShutDownOnIOThread, this)); } void Write(MessagePtr message) override { @@ -221,11 +223,11 @@ class ChannelFuchsia : public Channel, reject_writes_ = write_error = true; } if (write_error) { - // Do not synchronously invoke OnError(). Write() may have been called by - // the delegate and we don't want to re-enter it. + // Do not synchronously invoke OnWriteError(). Write() may have been + // called by the delegate and we don't want to re-enter it. io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelFuchsia::OnError, this, Error::kDisconnected)); + FROM_HERE, base::BindOnce(&ChannelFuchsia::OnWriteError, this, + Error::kDisconnected)); } } @@ -285,7 +287,7 @@ class ChannelFuchsia : public Channel, base::MessageLoop::current()->AddDestructionObserver(this); read_watch_.reset( - new base::MessageLoopForIO::ZxHandleWatchController(FROM_HERE)); + new base::MessagePumpForIO::ZxHandleWatchController(FROM_HERE)); base::MessageLoopForIO::current()->WatchZxHandle( handle_.get().as_handle(), true /* persistent */, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, read_watch_.get(), this); @@ -310,7 +312,7 @@ class ChannelFuchsia : public Channel, ShutDownOnIOThread(); } - // base::MessageLoopForIO::ZxHandleWatcher: + // base::MessagePumpForIO::ZxHandleWatcher: void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); CHECK_EQ(handle, handle_.get().as_handle()); @@ -410,6 +412,24 @@ class ChannelFuchsia : public Channel, return true; } + void OnWriteError(Error error) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(reject_writes_); + + if (error == Error::kDisconnected) { + // If we can't write because the pipe is disconnected then continue + // reading to fetch any in-flight messages, relying on end-of-stream to + // signal the actual disconnection. + if (read_watch_) { + // TODO: When we add flow-control for writes, we also need to reset the + // write-watcher here. + return; + } + } + + OnError(error); + } + // Keeps the Channel alive at least until explicit shutdown on the IO thread. scoped_refptr<Channel> self_; @@ -417,7 +437,7 @@ class ChannelFuchsia : public Channel, scoped_refptr<base::TaskRunner> io_task_runner_; // These members are only used on the IO thread. - std::unique_ptr<base::MessageLoopForIO::ZxHandleWatchController> read_watch_; + std::unique_ptr<base::MessagePumpForIO::ZxHandleWatchController> read_watch_; base::circular_deque<base::ScopedZxHandle> incoming_handles_; bool leak_handle_ = false; diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/edk/system/channel_posix.cc index 193ab6aee13..998fe5d6716 100644 --- a/chromium/mojo/edk/system/channel_posix.cc +++ b/chromium/mojo/edk/system/channel_posix.cc @@ -17,6 +17,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_for_io.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" #include "mojo/edk/embedder/platform_channel_utils_posix.h" @@ -87,7 +88,7 @@ class MessageView { class ChannelPosix : public Channel, public base::MessageLoop::DestructionObserver, - public base::MessageLoopForIO::Watcher { + public base::MessagePumpForIO::FdWatcher { public: ChannelPosix(Delegate* delegate, ConnectionParams connection_params, @@ -105,14 +106,14 @@ class ChannelPosix : public Channel, StartOnIOThread(); } else { io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::StartOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelPosix::StartOnIOThread, this)); } } void ShutDownImpl() override { // Always shut down asynchronously when called through the public interface. io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::ShutDownOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelPosix::ShutDownOnIOThread, this)); } void Write(MessagePtr message) override { @@ -129,11 +130,11 @@ class ChannelPosix : public Channel, } } if (write_error) { - // Do not synchronously invoke OnError(). Write() may have been called by - // the delegate and we don't want to re-enter it. + // Invoke OnWriteError() asynchronously on the IO thread, in case Write() + // was called by the delegate, in which case we should not re-enter it. io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelPosix::OnError, this, Error::kDisconnected)); + FROM_HERE, base::BindOnce(&ChannelPosix::OnWriteError, this, + Error::kDisconnected)); } } @@ -209,18 +210,18 @@ class ChannelPosix : public Channel, DCHECK(!read_watcher_); DCHECK(!write_watcher_); read_watcher_.reset( - new base::MessageLoopForIO::FileDescriptorWatcher(FROM_HERE)); + new base::MessagePumpForIO::FdWatchController(FROM_HERE)); base::MessageLoop::current()->AddDestructionObserver(this); if (handle_.get().needs_connection) { base::MessageLoopForIO::current()->WatchFileDescriptor( handle_.get().handle, false /* persistent */, - base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this); + base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this); } else { write_watcher_.reset( - new base::MessageLoopForIO::FileDescriptorWatcher(FROM_HERE)); + new base::MessagePumpForIO::FdWatchController(FROM_HERE)); base::MessageLoopForIO::current()->WatchFileDescriptor( handle_.get().handle, true /* persistent */, - base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this); + base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this); base::AutoLock lock(write_lock_); FlushOutgoingMessagesNoLock(); } @@ -240,10 +241,11 @@ class ChannelPosix : public Channel, pending_write_ = true; base::MessageLoopForIO::current()->WatchFileDescriptor( handle_.get().handle, false /* persistent */, - base::MessageLoopForIO::WATCH_WRITE, write_watcher_.get(), this); + base::MessagePumpForIO::WATCH_WRITE, write_watcher_.get(), this); } else { io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::WaitForWriteOnIOThread, this)); + FROM_HERE, + base::BindOnce(&ChannelPosix::WaitForWriteOnIOThread, this)); } } @@ -270,7 +272,7 @@ class ChannelPosix : public Channel, ShutDownOnIOThread(); } - // base::MessageLoopForIO::Watcher: + // base::MessagePumpForIO::FdWatcher: void OnFileCanReadWithoutBlocking(int fd) override { CHECK_EQ(fd, handle_.get().handle); if (handle_.get().needs_connection) { @@ -340,7 +342,7 @@ class ChannelPosix : public Channel, reject_writes_ = write_error = true; } if (write_error) - OnError(Error::kDisconnected); + OnWriteError(Error::kDisconnected); } // Attempts to write a message directly to the channel. If the full message @@ -524,6 +526,23 @@ class ChannelPosix : public Channel, } #endif // defined(OS_MACOSX) + void OnWriteError(Error error) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(reject_writes_); + + if (error == Error::kDisconnected) { + // If we can't write because the pipe is disconnected then continue + // reading to fetch any in-flight messages, relying on end-of-stream to + // signal the actual disconnection. + if (read_watcher_) { + write_watcher_.reset(); + return; + } + } + + OnError(error); + } + // Keeps the Channel alive at least until explicit shutdown on the IO thread. scoped_refptr<Channel> self_; @@ -531,8 +550,8 @@ class ChannelPosix : public Channel, scoped_refptr<base::TaskRunner> io_task_runner_; // These watchers must only be accessed on the IO thread. - std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; - std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; + std::unique_ptr<base::MessagePumpForIO::FdWatchController> read_watcher_; + std::unique_ptr<base::MessagePumpForIO::FdWatchController> write_watcher_; base::circular_deque<ScopedPlatformHandle> incoming_platform_handles_; diff --git a/chromium/mojo/edk/system/channel_unittest.cc b/chromium/mojo/edk/system/channel_unittest.cc index 3e54e5bc19e..de6aa850640 100644 --- a/chromium/mojo/edk/system/channel_unittest.cc +++ b/chromium/mojo/edk/system/channel_unittest.cc @@ -3,7 +3,12 @@ // found in the LICENSE file. #include "mojo/edk/system/channel.h" + +#include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop.h" +#include "base/threading/thread.h" +#include "mojo/edk/embedder/platform_channel_pair.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -172,6 +177,101 @@ TEST(ChannelTest, OnReadNonLegacyMessage) { channel_delegate.GetReceivedPayloadSize()); } +class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate { + public: + ChannelTestShutdownAndWriteDelegate( + ScopedPlatformHandle handle, + scoped_refptr<base::TaskRunner> task_runner, + scoped_refptr<Channel> client_channel, + std::unique_ptr<base::Thread> client_thread, + base::RepeatingClosure quit_closure) + : quit_closure_(std::move(quit_closure)), + client_channel_(std::move(client_channel)), + client_thread_(std::move(client_thread)) { + channel_ = Channel::Create( + this, ConnectionParams(TransportProtocol::kLegacy, std::move(handle)), + std::move(task_runner)); + channel_->Start(); + } + ~ChannelTestShutdownAndWriteDelegate() override { channel_->ShutDown(); } + + // Channel::Delegate implementation + void OnChannelMessage(const void* payload, + size_t payload_size, + std::vector<ScopedPlatformHandle> handles) override { + ++message_count_; + + // If |client_channel_| exists then close it and its thread. + if (client_channel_) { + // Write a fresh message, making our channel readable again. + Channel::MessagePtr message = CreateDefaultMessage(false); + client_thread_->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&Channel::Write, client_channel_, + base::Passed(&message))); + + // Close the channel and wait for it to shutdown. + client_channel_->ShutDown(); + client_channel_ = nullptr; + + client_thread_->Stop(); + client_thread_ = nullptr; + } + + // Write a message to the channel, to verify whether this triggers an + // OnChannelError callback before all messages were read. + Channel::MessagePtr message = CreateDefaultMessage(false); + channel_->Write(std::move(message)); + } + + void OnChannelError(Channel::Error error) override { + EXPECT_EQ(2, message_count_); + quit_closure_.Run(); + } + + base::RepeatingClosure quit_closure_; + int message_count_ = 0; + scoped_refptr<Channel> channel_; + + scoped_refptr<Channel> client_channel_; + std::unique_ptr<base::Thread> client_thread_; +}; + +TEST(ChannelTest, PeerShutdownDuringRead) { + base::MessageLoop message_loop(base::MessageLoop::TYPE_IO); + PlatformChannelPair channel_pair; + + // Create a "client" Channel with one end of the pipe, and Start() it. + std::unique_ptr<base::Thread> client_thread = + std::make_unique<base::Thread>("clientio_thread"); + client_thread->StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + + scoped_refptr<Channel> client_channel = + Channel::Create(nullptr, + ConnectionParams(TransportProtocol::kLegacy, + channel_pair.PassClientHandle()), + client_thread->task_runner()); + client_channel->Start(); + + // On the "client" IO thread, create and write a message. + Channel::MessagePtr message = CreateDefaultMessage(false); + client_thread->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&Channel::Write, client_channel, base::Passed(&message))); + + // Create a "server" Channel with the other end of the pipe, and process the + // messages from it. The |server_delegate| will ShutDown the client end of + // the pipe after the first message, and quit the RunLoop when OnChannelError + // is received. + base::RunLoop run_loop; + ChannelTestShutdownAndWriteDelegate server_delegate( + channel_pair.PassServerHandle(), message_loop.task_runner(), + std::move(client_channel), std::move(client_thread), + run_loop.QuitClosure()); + + run_loop.Run(); +} + } // namespace } // namespace edk } // namespace mojo diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/edk/system/channel_win.cc index cd47caf7b8c..ff4c8135fc3 100644 --- a/chromium/mojo/edk/system/channel_win.cc +++ b/chromium/mojo/edk/system/channel_win.cc @@ -17,6 +17,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_for_io.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" #include "base/win/win_util.h" @@ -27,51 +28,9 @@ namespace edk { namespace { -// A view over a Channel::Message object. The write queue uses these since -// large messages may need to be sent in chunks. -class MessageView { - public: - // Owns |message|. |offset| indexes the first unsent byte in the message. - MessageView(Channel::MessagePtr message, size_t offset) - : message_(std::move(message)), - offset_(offset) { - DCHECK_GT(message_->data_num_bytes(), offset_); - } - - MessageView(MessageView&& other) { *this = std::move(other); } - - MessageView& operator=(MessageView&& other) { - message_ = std::move(other.message_); - offset_ = other.offset_; - return *this; - } - - ~MessageView() {} - - const void* data() const { - return static_cast<const char*>(message_->data()) + offset_; - } - - size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; } - - size_t data_offset() const { return offset_; } - void advance_data_offset(size_t num_bytes) { - DCHECK_GE(message_->data_num_bytes(), offset_ + num_bytes); - offset_ += num_bytes; - } - - Channel::MessagePtr TakeChannelMessage() { return std::move(message_); } - - private: - Channel::MessagePtr message_; - size_t offset_; - - DISALLOW_COPY_AND_ASSIGN(MessageView); -}; - class ChannelWin : public Channel, public base::MessageLoop::DestructionObserver, - public base::MessageLoopForIO::IOHandler { + public base::MessagePumpForIO::IOHandler { public: ChannelWin(Delegate* delegate, ScopedPlatformHandle handle, @@ -81,19 +40,17 @@ class ChannelWin : public Channel, handle_(std::move(handle)), io_task_runner_(io_task_runner) { CHECK(handle_.is_valid()); - - wait_for_connect_ = handle_.get().needs_connection; } void Start() override { io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelWin::StartOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelWin::StartOnIOThread, this)); } void ShutDownImpl() override { // Always shut down asynchronously when called through the public interface. io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelWin::ShutDownOnIOThread, this)); + FROM_HERE, base::BindOnce(&ChannelWin::ShutDownOnIOThread, this)); } void Write(MessagePtr message) override { @@ -104,16 +61,16 @@ class ChannelWin : public Channel, return; bool write_now = !delay_writes_ && outgoing_messages_.empty(); - outgoing_messages_.emplace_back(std::move(message), 0); + outgoing_messages_.emplace_back(std::move(message)); if (write_now && !WriteNoLock(outgoing_messages_.front())) reject_writes_ = write_error = true; } if (write_error) { - // Do not synchronously invoke OnError(). Write() may have been called by - // the delegate and we don't want to re-enter it. - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ChannelWin::OnError, this, Error::kDisconnected)); + // Do not synchronously invoke OnWriteError(). Write() may have been + // called by the delegate and we don't want to re-enter it. + io_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&ChannelWin::OnWriteError, this, + Error::kDisconnected)); } } @@ -153,7 +110,7 @@ class ChannelWin : public Channel, base::MessageLoopForIO::current()->RegisterIOHandler( handle_.get().handle, this); - if (wait_for_connect_) { + if (handle_.get().needs_connection) { BOOL ok = ConnectNamedPipe(handle_.get().handle, &connect_context_.overlapped); if (ok) { @@ -165,12 +122,13 @@ class ChannelWin : public Channel, const DWORD err = GetLastError(); switch (err) { case ERROR_PIPE_CONNECTED: - wait_for_connect_ = false; break; case ERROR_IO_PENDING: + is_connect_pending_ = true; AddRef(); return; case ERROR_NO_DATA: + default: OnError(Error::kConnectionFailed); return; } @@ -185,7 +143,8 @@ class ChannelWin : public Channel, } } - // Keep this alive in case we synchronously run shutdown. + // Keep this alive in case we synchronously run shutdown, via OnError(), + // as a result of a ReadFile() failure on the channel. scoped_refptr<ChannelWin> keep_alive(this); ReadMore(0); } @@ -201,7 +160,7 @@ class ChannelWin : public Channel, ignore_result(handle_.release()); handle_.reset(); - // May destroy the |this| if it was the last reference. + // Allow |this| to be destroyed as soon as no IO is pending. self_ = nullptr; } @@ -213,14 +172,22 @@ class ChannelWin : public Channel, } // base::MessageLoop::IOHandler: - void OnIOCompleted(base::MessageLoopForIO::IOContext* context, + void OnIOCompleted(base::MessagePumpForIO::IOContext* context, DWORD bytes_transfered, DWORD error) override { if (error != ERROR_SUCCESS) { - OnError(Error::kDisconnected); + if (context == &write_context_) { + { + base::AutoLock lock(write_lock_); + reject_writes_ = true; + } + OnWriteError(Error::kDisconnected); + } else { + OnError(Error::kDisconnected); + } } else if (context == &connect_context_) { - DCHECK(wait_for_connect_); - wait_for_connect_ = false; + DCHECK(is_connect_pending_); + is_connect_pending_ = false; ReadMore(0); base::AutoLock lock(write_lock_); @@ -234,10 +201,13 @@ class ChannelWin : public Channel, CHECK(context == &write_context_); OnWriteDone(static_cast<size_t>(bytes_transfered)); } - Release(); // Balancing reference taken after ReadFile / WriteFile. + Release(); } void OnReadDone(size_t bytes_read) { + DCHECK(is_read_pending_); + is_read_pending_ = false; + if (bytes_read > 0) { size_t next_read_size = 0; if (OnReadComplete(bytes_read, &next_read_size)) { @@ -258,28 +228,31 @@ class ChannelWin : public Channel, { base::AutoLock lock(write_lock_); + DCHECK(is_write_pending_); + is_write_pending_ = false; DCHECK(!outgoing_messages_.empty()); - MessageView& message_view = outgoing_messages_.front(); - message_view.advance_data_offset(bytes_written); - if (message_view.data_num_bytes() == 0) { - Channel::MessagePtr message = message_view.TakeChannelMessage(); - outgoing_messages_.pop_front(); + Channel::MessagePtr message = std::move(outgoing_messages_.front()); + outgoing_messages_.pop_front(); - // Clear any handles so they don't get closed on destruction. - std::vector<ScopedPlatformHandle> handles = message->TakeHandles(); - for (auto& handle : handles) - ignore_result(handle.release()); - } + // Clear any handles so they don't get closed on destruction. + std::vector<ScopedPlatformHandle> handles = message->TakeHandles(); + for (auto& handle : handles) + ignore_result(handle.release()); - if (!WriteNextNoLock()) + // Overlapped WriteFile() to a pipe should always fully complete. + if (message->data_num_bytes() != bytes_written) + reject_writes_ = write_error = true; + else if (!WriteNextNoLock()) reject_writes_ = write_error = true; } if (write_error) - OnError(Error::kDisconnected); + OnWriteError(Error::kDisconnected); } void ReadMore(size_t next_read_size_hint) { + DCHECK(!is_read_pending_); + size_t buffer_capacity = next_read_size_hint; char* buffer = GetReadBuffer(&buffer_capacity); DCHECK_GT(buffer_capacity, 0u); @@ -291,7 +264,8 @@ class ChannelWin : public Channel, &read_context_.overlapped); if (ok || GetLastError() == ERROR_IO_PENDING) { - AddRef(); // Will be balanced in OnIOCompleted + is_read_pending_ = true; + AddRef(); } else { OnError(Error::kDisconnected); } @@ -300,15 +274,14 @@ class ChannelWin : public Channel, // Attempts to write a message directly to the channel. If the full message // cannot be written, it's queued and a wait is initiated to write the message // ASAP on the I/O thread. - bool WriteNoLock(const MessageView& message_view) { - BOOL ok = WriteFile(handle_.get().handle, - message_view.data(), - static_cast<DWORD>(message_view.data_num_bytes()), - NULL, + bool WriteNoLock(const Channel::MessagePtr& message) { + BOOL ok = WriteFile(handle_.get().handle, message->data(), + static_cast<DWORD>(message->data_num_bytes()), NULL, &write_context_.overlapped); if (ok || GetLastError() == ERROR_IO_PENDING) { - AddRef(); // Will be balanced in OnIOCompleted. + is_write_pending_ = true; + AddRef(); return true; } return false; @@ -320,25 +293,39 @@ class ChannelWin : public Channel, return WriteNoLock(outgoing_messages_.front()); } + void OnWriteError(Error error) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(reject_writes_); + + if (error == Error::kDisconnected) { + // If we can't write because the pipe is disconnected then continue + // reading to fetch any in-flight messages, relying on end-of-stream to + // signal the actual disconnection. + if (is_read_pending_ || is_connect_pending_) + return; + } + + OnError(error); + } + // Keeps the Channel alive at least until explicit shutdown on the IO thread. scoped_refptr<Channel> self_; ScopedPlatformHandle handle_; - scoped_refptr<base::TaskRunner> io_task_runner_; + const scoped_refptr<base::TaskRunner> io_task_runner_; - base::MessageLoopForIO::IOContext connect_context_; - base::MessageLoopForIO::IOContext read_context_; - base::MessageLoopForIO::IOContext write_context_; + base::MessagePumpForIO::IOContext connect_context_; + base::MessagePumpForIO::IOContext read_context_; + bool is_connect_pending_ = false; + bool is_read_pending_ = false; - // Protects |reject_writes_| and |outgoing_messages_|. + // Protects all fields potentially accessed on multiple threads via Write(). base::Lock write_lock_; - + base::MessagePumpForIO::IOContext write_context_; + base::circular_deque<Channel::MessagePtr> outgoing_messages_; bool delay_writes_ = true; - bool reject_writes_ = false; - base::circular_deque<MessageView> outgoing_messages_; - - bool wait_for_connect_; + bool is_write_pending_ = false; bool leak_handle_ = false; diff --git a/chromium/mojo/edk/system/core.cc b/chromium/mojo/edk/system/core.cc index fc941b441e1..bf2f95c06b4 100644 --- a/chromium/mojo/edk/system/core.cc +++ b/chromium/mojo/edk/system/core.cc @@ -20,9 +20,8 @@ #include "base/time/time.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_shared_buffer.h" +#include "mojo/edk/embedder/process_error_callback.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" @@ -186,21 +185,18 @@ void Core::SetDefaultProcessErrorCallback( default_process_error_callback_ = callback; } -ScopedMessagePipeHandle Core::CreatePartialMessagePipe(ports::PortRef* peer) { +MojoHandle Core::CreatePartialMessagePipe(ports::PortRef* peer) { RequestContext request_context; ports::PortRef local_port; GetNodeController()->node()->CreatePortPair(&local_port, peer); - MojoHandle handle = AddDispatcher(new MessagePipeDispatcher( + return AddDispatcher(new MessagePipeDispatcher( GetNodeController(), local_port, kUnknownPipeIdForDebug, 0)); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); } -ScopedMessagePipeHandle Core::CreatePartialMessagePipe( - const ports::PortRef& port) { +MojoHandle Core::CreatePartialMessagePipe(const ports::PortRef& port) { RequestContext request_context; - return ScopedMessagePipeHandle( - MessagePipeHandle(AddDispatcher(new MessagePipeDispatcher( - GetNodeController(), port, kUnknownPipeIdForDebug, 1)))); + return AddDispatcher(new MessagePipeDispatcher(GetNodeController(), port, + kUnknownPipeIdForDebug, 1)); } void Core::SendBrokerClientInvitation( @@ -382,15 +378,14 @@ void Core::RequestShutdown(const base::Closure& callback) { GetNodeController()->RequestShutdown(callback); } -ScopedMessagePipeHandle Core::ExtractMessagePipeFromInvitation( - const std::string& name) { +MojoHandle Core::ExtractMessagePipeFromInvitation(const std::string& name) { RequestContext request_context; ports::PortRef port0, port1; GetNodeController()->node()->CreatePortPair(&port0, &port1); MojoHandle handle = AddDispatcher(new MessagePipeDispatcher( GetNodeController(), port0, kUnknownPipeIdForDebug, 1)); GetNodeController()->MergePortIntoInviter(name, port1); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); + return handle; } MojoResult Core::SetProperty(MojoPropertyType type, const void* value) { @@ -432,57 +427,79 @@ MojoResult Core::QueryHandleSignalsState( return MOJO_RESULT_OK; } -MojoResult Core::CreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { +MojoResult Core::CreateTrap(MojoTrapEventHandler handler, + const MojoCreateTrapOptions* options, + MojoHandle* trap_handle) { + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; + RequestContext request_context; - if (!watcher_handle) + if (!trap_handle) return MOJO_RESULT_INVALID_ARGUMENT; - *watcher_handle = AddDispatcher(new WatcherDispatcher(callback)); - if (*watcher_handle == MOJO_HANDLE_INVALID) + *trap_handle = AddDispatcher(new WatcherDispatcher(handler)); + if (*trap_handle == MOJO_HANDLE_INVALID) return MOJO_RESULT_RESOURCE_EXHAUSTED; return MOJO_RESULT_OK; } -MojoResult Core::Watch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context) { +MojoResult Core::AddTrigger(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const MojoAddTriggerOptions* options) { + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; + RequestContext request_context; - scoped_refptr<Dispatcher> watcher = GetDispatcher(watcher_handle); + scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle); if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) return MOJO_RESULT_INVALID_ARGUMENT; + scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; + return watcher->WatchDispatcher(std::move(dispatcher), signals, condition, context); } -MojoResult Core::CancelWatch(MojoHandle watcher_handle, uintptr_t context) { +MojoResult Core::RemoveTrigger(MojoHandle trap_handle, + uintptr_t context, + const MojoRemoveTriggerOptions* options) { + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; + RequestContext request_context; - scoped_refptr<Dispatcher> watcher = GetDispatcher(watcher_handle); + scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle); if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) return MOJO_RESULT_INVALID_ARGUMENT; return watcher->CancelWatch(context); } -MojoResult Core::ArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { +MojoResult Core::ArmTrap(MojoHandle trap_handle, + const MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals_states) { + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; + RequestContext request_context; - scoped_refptr<Dispatcher> watcher = GetDispatcher(watcher_handle); + scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle); if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) return MOJO_RESULT_INVALID_ARGUMENT; - return watcher->Arm(num_ready_contexts, ready_contexts, ready_results, + return watcher->Arm(num_ready_triggers, ready_triggers, ready_results, ready_signals_states); } -MojoResult Core::CreateMessage(MojoMessageHandle* message_handle) { +MojoResult Core::CreateMessage(const MojoCreateMessageOptions* options, + MojoMessageHandle* message_handle) { if (!message_handle) return MOJO_RESULT_INVALID_ARGUMENT; + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; *message_handle = reinterpret_cast<MojoMessageHandle>( UserMessageImpl::CreateEventForNewMessage().release()); return MOJO_RESULT_OK; @@ -497,74 +514,43 @@ MojoResult Core::DestroyMessage(MojoMessageHandle message_handle) { return MOJO_RESULT_OK; } -MojoResult Core::SerializeMessage(MojoMessageHandle message_handle) { +MojoResult Core::SerializeMessage(MojoMessageHandle message_handle, + const MojoSerializeMessageOptions* options) { if (!message_handle) return MOJO_RESULT_INVALID_ARGUMENT; + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; RequestContext request_context; return reinterpret_cast<ports::UserMessageEvent*>(message_handle) ->GetMessage<UserMessageImpl>() ->SerializeIfNecessary(); } -MojoResult Core::AttachSerializedMessageBuffer(MojoMessageHandle message_handle, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size) { - if (!message_handle || (num_handles && !handles) || !buffer || !buffer_size) - return MOJO_RESULT_INVALID_ARGUMENT; - RequestContext request_context; - auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) - ->GetMessage<UserMessageImpl>(); - MojoResult rv = message->AttachSerializedMessageBuffer(payload_size, handles, - num_handles); - if (rv != MOJO_RESULT_OK) - return rv; - - *buffer = message->user_payload(); - *buffer_size = base::checked_cast<uint32_t>(message->user_payload_capacity()); - return MOJO_RESULT_OK; -} - -MojoResult Core::ExtendSerializedMessagePayload( - MojoMessageHandle message_handle, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** new_buffer, - uint32_t* new_buffer_size) { - if (!message_handle || !new_buffer || !new_buffer_size) +MojoResult Core::AppendMessageData(MojoMessageHandle message_handle, + uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const MojoAppendMessageDataOptions* options, + void** buffer, + uint32_t* buffer_size) { + if (!message_handle || (num_handles && !handles)) return MOJO_RESULT_INVALID_ARGUMENT; - if (!handles && num_handles) + if (options && options->struct_size != sizeof(*options)) return MOJO_RESULT_INVALID_ARGUMENT; - auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) - ->GetMessage<UserMessageImpl>(); - MojoResult rv = message->ExtendSerializedMessagePayload(new_payload_size, - handles, num_handles); - if (rv != MOJO_RESULT_OK) - return rv; - - *new_buffer = message->user_payload(); - *new_buffer_size = - base::checked_cast<uint32_t>(message->user_payload_capacity()); - return MOJO_RESULT_OK; -} -MojoResult Core::CommitSerializedMessageContents( - MojoMessageHandle message_handle, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size) { - if (!message_handle) - return MOJO_RESULT_INVALID_ARGUMENT; RequestContext request_context; auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) ->GetMessage<UserMessageImpl>(); - MojoResult rv = message->CommitSerializedContents(final_payload_size); + MojoResult rv = + message->AppendData(additional_payload_size, handles, num_handles); if (rv != MOJO_RESULT_OK) return rv; + if (options && (options->flags & MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE)) { + RequestContext request_context; + message->CommitSize(); + } + if (buffer) *buffer = message->user_payload(); if (buffer_size) { @@ -574,15 +560,16 @@ MojoResult Core::CommitSerializedMessageContents( return MOJO_RESULT_OK; } -MojoResult Core::GetSerializedMessageContents( - MojoMessageHandle message_handle, - void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags) { +MojoResult Core::GetMessageData(MojoMessageHandle message_handle, + const MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles) { if (!message_handle || (num_handles && *num_handles && !handles)) return MOJO_RESULT_INVALID_ARGUMENT; + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) ->GetMessage<UserMessageImpl>(); @@ -603,6 +590,9 @@ MojoResult Core::GetSerializedMessageContents( *buffer = nullptr; } + if (options && (options->flags & MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES)) + return MOJO_RESULT_OK; + uint32_t max_num_handles = 0; if (num_handles) { max_num_handles = *num_handles; @@ -619,32 +609,35 @@ MojoResult Core::GetSerializedMessageContents( UserMessageImpl::ExtractBadHandlePolicy::kAbort, handles); } -MojoResult Core::AttachMessageContext(MojoMessageHandle message_handle, - uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor) { - if (!message_handle || !context) +MojoResult Core::SetMessageContext( + MojoMessageHandle message_handle, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const MojoSetMessageContextOptions* options) { + if (!message_handle) + return MOJO_RESULT_INVALID_ARGUMENT; + if (options && options->struct_size != sizeof(*options)) return MOJO_RESULT_INVALID_ARGUMENT; auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) ->GetMessage<UserMessageImpl>(); - return message->AttachContext(context, serializer, destructor); + return message->SetContext(context, serializer, destructor); } MojoResult Core::GetMessageContext(MojoMessageHandle message_handle, - uintptr_t* context, - MojoGetMessageContextFlags flags) { + const MojoGetMessageContextOptions* options, + uintptr_t* context) { if (!message_handle) return MOJO_RESULT_INVALID_ARGUMENT; + if (options && options->struct_size != sizeof(*options)) + return MOJO_RESULT_INVALID_ARGUMENT; auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle) ->GetMessage<UserMessageImpl>(); if (!message->HasContext()) return MOJO_RESULT_NOT_FOUND; - if (flags & MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE) - *context = message->ReleaseContext(); - else - *context = message->context(); + *context = message->context(); return MOJO_RESULT_OK; } @@ -1015,6 +1008,21 @@ MojoResult Core::UnmapBuffer(void* buffer) { return result; } +MojoResult Core::GetBufferInfo(MojoHandle buffer_handle, + const MojoSharedBufferOptions* options, + MojoSharedBufferInfo* info) { + if (options && options->struct_size != sizeof(MojoSharedBufferOptions)) + return MOJO_RESULT_INVALID_ARGUMENT; + if (!info || info->struct_size != sizeof(MojoSharedBufferInfo)) + return MOJO_RESULT_INVALID_ARGUMENT; + + scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); + if (!dispatcher) + return MOJO_RESULT_INVALID_ARGUMENT; + + return dispatcher->GetBufferInfo(info); +} + MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle, MojoHandle* mojo_handle) { ScopedPlatformHandle handle; diff --git a/chromium/mojo/edk/system/core.h b/chromium/mojo/edk/system/core.h index 38e2041ffff..478971e2dc6 100644 --- a/chromium/mojo/edk/system/core.h +++ b/chromium/mojo/edk/system/core.h @@ -26,9 +26,8 @@ #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/platform_handle.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/message_pipe.h" namespace base { class PortProvider; @@ -44,6 +43,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { Core(); virtual ~Core(); + static Core* Get(); + // Called exactly once, shortly after construction, and before any other // methods are called on this object. void SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner); @@ -61,11 +62,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { // // The value returned in |*peer| may be passed along with a broker client // invitation. See SendBrokerClientInvitation() below. - ScopedMessagePipeHandle CreatePartialMessagePipe(ports::PortRef* peer); + MojoHandle CreatePartialMessagePipe(ports::PortRef* peer); // Like above but exchanges an existing ports::PortRef for a message pipe // handle which wraps it. - ScopedMessagePipeHandle CreatePartialMessagePipe(const ports::PortRef& port); + MojoHandle CreatePartialMessagePipe(const ports::PortRef& port); // Sends a broker client invitation to |target_process| over the connection // medium in |connection_params|. The other end of the connection medium in @@ -90,8 +91,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { // Extracts a named message pipe endpoint from the broker client invitation // accepted by this process. Must only be called after // AcceptBrokerClientInvitation. - ScopedMessagePipeHandle ExtractMessagePipeFromInvitation( - const std::string& name); + MojoHandle ExtractMessagePipeFromInvitation(const std::string& name); // Called to connect to a peer process. This should be called only if there // is no common ancestor for the processes involved within this mojo system. @@ -179,52 +179,50 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { MojoResult Close(MojoHandle handle); MojoResult QueryHandleSignalsState(MojoHandle handle, MojoHandleSignalsState* signals_state); - MojoResult CreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - MojoResult Watch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context); - MojoResult CancelWatch(MojoHandle watcher_handle, uintptr_t context); - MojoResult ArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states); - MojoResult CreateMessage(MojoMessageHandle* message_handle); + MojoResult CreateTrap(MojoTrapEventHandler handler, + const MojoCreateTrapOptions* options, + MojoHandle* trap_handle); + MojoResult AddTrigger(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const MojoAddTriggerOptions* options); + MojoResult RemoveTrigger(MojoHandle trap_handle, + uintptr_t context, + const MojoRemoveTriggerOptions* options); + MojoResult ArmTrap(MojoHandle trap_handle, + const MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals_states); + MojoResult CreateMessage(const MojoCreateMessageOptions* options, + MojoMessageHandle* message_handle); MojoResult DestroyMessage(MojoMessageHandle message_handle); - MojoResult SerializeMessage(MojoMessageHandle message_handle); - MojoResult AttachSerializedMessageBuffer(MojoMessageHandle message_handle, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size); - MojoResult ExtendSerializedMessagePayload(MojoMessageHandle message_handle, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** new_buffer, - uint32_t* new_buffer_size); - MojoResult CommitSerializedMessageContents(MojoMessageHandle message_handle, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size); - MojoResult GetSerializedMessageContents( - MojoMessageHandle message_handle, - void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags); - MojoResult AttachMessageContext(MojoMessageHandle message_handle, - uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor); + MojoResult SerializeMessage(MojoMessageHandle message_handle, + const MojoSerializeMessageOptions* options); + MojoResult AppendMessageData(MojoMessageHandle message_handle, + uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const MojoAppendMessageDataOptions* options, + void** buffer, + uint32_t* buffer_size); + MojoResult GetMessageData(MojoMessageHandle message_handle, + const MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles); + MojoResult SetMessageContext(MojoMessageHandle message_handle, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const MojoSetMessageContextOptions* options); MojoResult GetMessageContext(MojoMessageHandle message_handle, - uintptr_t* context, - MojoGetMessageContextFlags flags); + const MojoGetMessageContextOptions* options, + uintptr_t* context); MojoResult GetProperty(MojoPropertyType type, void* value); // These methods correspond to the API functions defined in @@ -284,6 +282,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { void** buffer, MojoMapBufferFlags flags); MojoResult UnmapBuffer(void* buffer); + MojoResult GetBufferInfo(MojoHandle buffer_handle, + const MojoSharedBufferOptions* options, + MojoSharedBufferInfo* info); // These methods correspond to the API functions defined in // "mojo/public/c/system/platform_handle.h". diff --git a/chromium/mojo/edk/system/core_test_base.cc b/chromium/mojo/edk/system/core_test_base.cc index 9f8637c4a9a..ff7b7c3ae52 100644 --- a/chromium/mojo/edk/system/core_test_base.cc +++ b/chromium/mojo/edk/system/core_test_base.cc @@ -12,7 +12,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/dispatcher.h" @@ -121,7 +120,7 @@ MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) { } Core* CoreTestBase::core() { - return mojo::edk::internal::g_core; + return Core::Get(); } // CoreTestBase_MockHandleInfo ------------------------------------------------- diff --git a/chromium/mojo/edk/system/core_test_base.h b/chromium/mojo/edk/system/core_test_base.h index 3d156e32e2c..84718be2944 100644 --- a/chromium/mojo/edk/system/core_test_base.h +++ b/chromium/mojo/edk/system/core_test_base.h @@ -9,7 +9,6 @@ #include "base/macros.h" #include "base/synchronization/lock.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/test_utils.h" #include "mojo/public/c/system/types.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/mojo/edk/system/core_unittest.cc b/chromium/mojo/edk/system/core_unittest.cc index f4747b05789..7fe7ba0e95b 100644 --- a/chromium/mojo/edk/system/core_unittest.cc +++ b/chromium/mojo/edk/system/core_unittest.cc @@ -9,7 +9,6 @@ #include <limits> #include "base/bind.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core_test_base.h" #include "mojo/edk/system/test_utils.h" #include "mojo/public/cpp/system/wait.h" @@ -51,7 +50,7 @@ TEST_F(CoreTest, Basic) { ASSERT_EQ(0u, info.GetWriteMessageCallCount()); MojoMessageHandle message; - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); ASSERT_EQ(1u, info.GetWriteMessageCallCount()); @@ -173,10 +172,10 @@ TEST_F(CoreTest, MessagePipe) { // Write to |h[1]|. const uintptr_t kTestMessageContext = 123; - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - core()->AttachMessageContext(message, kTestMessageContext, nullptr, - nullptr)); + core()->SetMessageContext(message, kTestMessageContext, nullptr, + nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); @@ -189,8 +188,9 @@ TEST_F(CoreTest, MessagePipe) { core()->ReadMessage(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; ASSERT_EQ(MOJO_RESULT_OK, - core()->GetMessageContext(message, &context, - MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE)); + core()->GetMessageContext(message, nullptr, &context)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->SetMessageContext(message, 0, nullptr, nullptr, nullptr)); ASSERT_EQ(kTestMessageContext, context); ASSERT_EQ(MOJO_RESULT_OK, core()->DestroyMessage(message)); @@ -201,10 +201,10 @@ TEST_F(CoreTest, MessagePipe) { ASSERT_EQ(kAllSignals, hss[0].satisfiable_signals); // Write to |h[0]|. - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - core()->AttachMessageContext(message, kTestMessageContext, nullptr, - nullptr)); + core()->SetMessageContext(message, kTestMessageContext, nullptr, + nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[0], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); @@ -240,10 +240,10 @@ TEST_F(CoreTest, MessagePipe) { EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfiable_signals); // Try writing to |h[1]|. - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - core()->AttachMessageContext(message, kTestMessageContext, nullptr, - nullptr)); + core()->SetMessageContext(message, kTestMessageContext, nullptr, + nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); @@ -260,10 +260,10 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { // Make sure that |h_passing[]| work properly. const uintptr_t kTestMessageContext = 42; MojoMessageHandle message; - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - core()->AttachMessageContext(message, kTestMessageContext, nullptr, - nullptr)); + core()->SetMessageContext(message, kTestMessageContext, nullptr, + nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h_passing[0], message, MOJO_WRITE_MESSAGE_FLAG_NONE)); hss = kEmptyMojoHandleSignalsState; @@ -277,8 +277,9 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; ASSERT_EQ(MOJO_RESULT_OK, - core()->GetMessageContext(message_handle, &context, - MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE)); + core()->GetMessageContext(message_handle, nullptr, &context)); + ASSERT_EQ(MOJO_RESULT_OK, + core()->SetMessageContext(message, 0, nullptr, nullptr, nullptr)); ASSERT_EQ(kTestMessageContext, context); ASSERT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc index e1ecc853c25..f5c0c7e6b25 100644 --- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc @@ -15,7 +15,6 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/data_pipe_control_message.h" @@ -374,7 +373,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data, return nullptr; } - NodeController* node_controller = internal::g_core->GetNodeController(); + NodeController* node_controller = Core::Get()->GetNodeController(); ports::PortRef port; if (node_controller->node()->GetPort(ports[0], &port) != ports::OK) return nullptr; diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc index de0b768b63b..987e4d61de2 100644 --- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc @@ -13,7 +13,6 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/core.h" @@ -337,7 +336,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data, return nullptr; } - NodeController* node_controller = internal::g_core->GetNodeController(); + NodeController* node_controller = Core::Get()->GetNodeController(); ports::PortRef port; if (node_controller->node()->GetPort(ports[0], &port) != ports::OK) return nullptr; diff --git a/chromium/mojo/edk/system/data_pipe_unittest.cc b/chromium/mojo/edk/system/data_pipe_unittest.cc index 0aef4f581d6..a8a65f85791 100644 --- a/chromium/mojo/edk/system/data_pipe_unittest.cc +++ b/chromium/mojo/edk/system/data_pipe_unittest.cc @@ -1981,9 +1981,11 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient, }, &run_loop, &count); SimpleWatcher producer_watcher(FROM_HERE, - SimpleWatcher::ArmingPolicy::AUTOMATIC); + SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()); SimpleWatcher consumer_watcher(FROM_HERE, - SimpleWatcher::ArmingPolicy::AUTOMATIC); + SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()); producer_watcher.Watch(Handle(producers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, callback); consumer_watcher.Watch(Handle(consumers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, diff --git a/chromium/mojo/edk/system/dispatcher.cc b/chromium/mojo/edk/system/dispatcher.cc index 3ad0601231b..e736276dfd3 100644 --- a/chromium/mojo/edk/system/dispatcher.cc +++ b/chromium/mojo/edk/system/dispatcher.cc @@ -25,7 +25,7 @@ Dispatcher::DispatcherInTransit::~DispatcherInTransit() {} MojoResult Dispatcher::WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, uintptr_t context) { return MOJO_RESULT_INVALID_ARGUMENT; } @@ -66,6 +66,10 @@ MojoResult Dispatcher::MapBuffer( return MOJO_RESULT_INVALID_ARGUMENT; } +MojoResult Dispatcher::GetBufferInfo(MojoSharedBufferInfo* info) { + return MOJO_RESULT_INVALID_ARGUMENT; +} + MojoResult Dispatcher::ReadData(void* elements, uint32_t* num_bytes, MojoReadDataFlags flags) { diff --git a/chromium/mojo/edk/system/dispatcher.h b/chromium/mojo/edk/system/dispatcher.h index 3c3de631fde..3e13c1bd143 100644 --- a/chromium/mojo/edk/system/dispatcher.h +++ b/chromium/mojo/edk/system/dispatcher.h @@ -25,6 +25,7 @@ #include "mojo/public/c/system/buffer.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" namespace mojo { @@ -73,7 +74,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher virtual MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, uintptr_t context); virtual MojoResult CancelWatch(uintptr_t context); virtual MojoResult Arm(uint32_t* num_ready_contexts, @@ -105,6 +106,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher MojoMapBufferFlags flags, std::unique_ptr<PlatformSharedBufferMapping>* mapping); + virtual MojoResult GetBufferInfo(MojoSharedBufferInfo* info); + ///////////// Data pipe consumer API ///////////// virtual MojoResult ReadData(void* elements, diff --git a/chromium/mojo/edk/system/handle_signals_state.h b/chromium/mojo/edk/system/handle_signals_state.h index f2412787cbf..c8c5b5ea4a0 100644 --- a/chromium/mojo/edk/system/handle_signals_state.h +++ b/chromium/mojo/edk/system/handle_signals_state.h @@ -5,9 +5,102 @@ #ifndef MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ #define MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ -#include "mojo/public/cpp/system/handle_signals_state.h" +#include "mojo/edk/system/system_impl_export.h" +#include "mojo/public/c/system/types.h" -// TODO(rockot): Remove this header and use the C++ system library type -// directly inside the EDK. +namespace mojo { +namespace edk { + +// A convenience wrapper around the MojoHandleSignalsState struct. +// +// NOTE: This is duplicated in the public C++ SDK to avoid circular +// dependencies between the EDK and the public SDK. +struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState final + : public MojoHandleSignalsState { + HandleSignalsState() { + satisfied_signals = MOJO_HANDLE_SIGNAL_NONE; + satisfiable_signals = MOJO_HANDLE_SIGNAL_NONE; + } + + HandleSignalsState(MojoHandleSignals satisfied, + MojoHandleSignals satisfiable) { + satisfied_signals = satisfied; + satisfiable_signals = satisfiable; + } + + bool operator==(const HandleSignalsState& other) const { + return satisfied_signals == other.satisfied_signals && + satisfiable_signals == other.satisfiable_signals; + } + + // TODO(rockot): Remove this in favor of operator==. + bool equals(const HandleSignalsState& other) const { + return satisfied_signals == other.satisfied_signals && + satisfiable_signals == other.satisfiable_signals; + } + + bool satisfies_any(MojoHandleSignals signals) const { + return !!(satisfied_signals & signals); + } + + bool satisfies_all(MojoHandleSignals signals) const { + return (satisfied_signals & signals) == signals; + } + + bool can_satisfy_any(MojoHandleSignals signals) const { + return !!(satisfiable_signals & signals); + } + + // The handle is currently readable. May apply to a message pipe handle or + // data pipe consumer handle. + bool readable() const { return satisfies_any(MOJO_HANDLE_SIGNAL_READABLE); } + + // The handle is currently writable. May apply to a message pipe handle or + // data pipe producer handle. + bool writable() const { return satisfies_any(MOJO_HANDLE_SIGNAL_WRITABLE); } + + // The handle's peer is closed. May apply to any message pipe or data pipe + // handle. + bool peer_closed() const { + return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_CLOSED); + } + + // The handle's peer exists in a remote execution context (e.g. in another + // process.) + bool peer_remote() const { + return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE); + } + + // The handle will never be |readable()| again. + bool never_readable() const { + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_READABLE); + } + + // The handle will never be |writable()| again. + bool never_writable() const { + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_WRITABLE); + } + + // The handle can never indicate |peer_closed()|. Never true for message pipe + // or data pipe handles (they can always signal peer closure), but always true + // for other types of handles (they have no peer.) + bool never_peer_closed() const { + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_PEER_CLOSED); + } + + // The handle will never indicate |peer_remote()| again. True iff the peer is + // known to be closed. + bool never_peer_remote() const { + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE); + } + + // (Copy and assignment allowed.) +}; + +static_assert(sizeof(HandleSignalsState) == sizeof(MojoHandleSignalsState), + "HandleSignalsState should add no overhead"); + +} // namespace edk +} // namespace mojo #endif // MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ diff --git a/chromium/mojo/edk/system/mapping_table.h b/chromium/mojo/edk/system/mapping_table.h index 81cc56bb8bd..a9498201977 100644 --- a/chromium/mojo/edk/system/mapping_table.h +++ b/chromium/mojo/edk/system/mapping_table.h @@ -21,12 +21,6 @@ namespace edk { class Core; class PlatformSharedBufferMapping; -// Test-only function (defined/used in embedder/test_embedder.cc). Declared here -// so it can be friended. -namespace internal { -bool ShutdownCheckNoLeaks(Core*); -} - // This class provides the (global) table of memory mappings (owned by |Core|), // which maps mapping base addresses to |PlatformSharedBufferMapping|s. // @@ -44,8 +38,6 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable { std::unique_ptr<PlatformSharedBufferMapping>* mapping); private: - friend bool internal::ShutdownCheckNoLeaks(Core*); - using AddressToMappingMap = base::hash_map<void*, PlatformSharedBufferMapping*>; AddressToMappingMap address_to_mapping_map_; diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.cc b/chromium/mojo/edk/system/message_pipe_dispatcher.cc index eb15227dae9..a095ab4e497 100644 --- a/chromium/mojo/edk/system/message_pipe_dispatcher.cc +++ b/chromium/mojo/edk/system/message_pipe_dispatcher.cc @@ -10,7 +10,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/ports/event.h" @@ -274,7 +273,7 @@ scoped_refptr<Dispatcher> MessagePipeDispatcher::Deserialize( const SerializedState* state = static_cast<const SerializedState*>(data); - ports::Node* node = internal::g_core->GetNodeController()->node(); + ports::Node* node = Core::Get()->GetNodeController()->node(); ports::PortRef port; if (node->GetPort(ports[0], &port) != ports::OK) return nullptr; @@ -283,7 +282,7 @@ scoped_refptr<Dispatcher> MessagePipeDispatcher::Deserialize( if (node->GetStatus(port, &status) != ports::OK) return nullptr; - return new MessagePipeDispatcher(internal::g_core->GetNodeController(), port, + return new MessagePipeDispatcher(Core::Get()->GetNodeController(), port, state->pipe_id, state->endpoint); } diff --git a/chromium/mojo/edk/system/message_pipe_unittest.cc b/chromium/mojo/edk/system/message_pipe_unittest.cc index e4d837ab13a..6ec0bfb077d 100644 --- a/chromium/mojo/edk/system/message_pipe_unittest.cc +++ b/chromium/mojo/edk/system/message_pipe_unittest.cc @@ -61,9 +61,8 @@ class MessagePipeTest : public test::MojoTestBase { const uint32_t expected_num_bytes = *num_bytes; void* buffer; - rv = MojoGetSerializedMessageContents( - message_handle, &buffer, num_bytes, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + rv = MojoGetMessageData(message_handle, nullptr, &buffer, num_bytes, + nullptr, nullptr); if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { CHECK(may_discard); diff --git a/chromium/mojo/edk/system/message_unittest.cc b/chromium/mojo/edk/system/message_unittest.cc index 88b2e869151..8a3df875e8a 100644 --- a/chromium/mojo/edk/system/message_unittest.cc +++ b/chromium/mojo/edk/system/message_unittest.cc @@ -35,13 +35,13 @@ class TestMessageBase { static MojoMessageHandle MakeMessageHandle( std::unique_ptr<TestMessageBase> message) { MojoMessageHandle handle; - MojoResult rv = MojoCreateMessage(&handle); + MojoResult rv = MojoCreateMessage(nullptr, &handle); DCHECK_EQ(MOJO_RESULT_OK, rv); - rv = MojoAttachMessageContext( + rv = MojoSetMessageContext( handle, reinterpret_cast<uintptr_t>(message.release()), &TestMessageBase::SerializeMessageContext, - &TestMessageBase::DestroyMessageContext); + &TestMessageBase::DestroyMessageContext, nullptr); DCHECK_EQ(MOJO_RESULT_OK, rv); return handle; @@ -53,8 +53,9 @@ class TestMessageBase { MojoMessageHandle handle = MOJO_HANDLE_INVALID; std::swap(handle, *message_handle); uintptr_t context; - MojoResult rv = MojoGetMessageContext( - handle, &context, MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE); + MojoResult rv = MojoGetMessageContext(handle, nullptr, &context); + DCHECK_EQ(MOJO_RESULT_OK, rv); + rv = MojoSetMessageContext(handle, 0, nullptr, nullptr, nullptr); DCHECK_EQ(MOJO_RESULT_OK, rv); MojoDestroyMessage(handle); return base::WrapUnique(reinterpret_cast<T*>(context)); @@ -76,18 +77,19 @@ class TestMessageBase { if (num_handles) message->SerializeHandles(handles.data()); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; void* buffer; uint32_t buffer_size; - MojoResult rv = MojoAttachSerializedMessageBuffer( + MojoResult rv = MojoAppendMessageData( message_handle, base::checked_cast<uint32_t>(num_bytes), handles.data(), - base::checked_cast<uint32_t>(num_handles), &buffer, &buffer_size); + base::checked_cast<uint32_t>(num_handles), &options, &buffer, + &buffer_size); DCHECK_EQ(MOJO_RESULT_OK, rv); DCHECK_GE(buffer_size, base::checked_cast<uint32_t>(num_bytes)); if (num_bytes) message->SerializePayload(buffer); - rv = MojoCommitSerializedMessageContents( - message_handle, base::checked_cast<uint32_t>(num_bytes), &buffer, - &buffer_size); } static void DestroyMessageContext(uintptr_t context) { @@ -165,36 +167,21 @@ TEST_F(MessageTest, InvalidMessageObjects) { MojoDestroyMessage(MOJO_MESSAGE_HANDLE_INVALID)); ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoCommitSerializedMessageContents(MOJO_MESSAGE_HANDLE_INVALID, 0, - nullptr, nullptr)); + MojoAppendMessageData(MOJO_MESSAGE_HANDLE_INVALID, 0, nullptr, 0, + nullptr, nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoGetSerializedMessageContents( - MOJO_MESSAGE_HANDLE_INVALID, nullptr, nullptr, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(MOJO_MESSAGE_HANDLE_INVALID, nullptr, nullptr, + nullptr, nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoSerializeMessage(MOJO_MESSAGE_HANDLE_INVALID)); + MojoSerializeMessage(MOJO_MESSAGE_HANDLE_INVALID, nullptr)); MojoMessageHandle message_handle; - void* buffer; - uint32_t buffer_size; - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCreateMessage(nullptr)); - ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message_handle)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoAttachMessageContext(message_handle, 0, nullptr, nullptr)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoAttachSerializedMessageBuffer(message_handle, 0, nullptr, 0, - &buffer, nullptr)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoAttachSerializedMessageBuffer(message_handle, 0, nullptr, 0, - nullptr, &buffer_size)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoAttachSerializedMessageBuffer(message_handle, 0, nullptr, 0, - nullptr, nullptr)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer(message_handle, 0, nullptr, 0, - &buffer, &buffer_size)); + ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCreateMessage(nullptr, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message_handle)); + ASSERT_EQ(MOJO_RESULT_OK, MojoSetMessageContext(message_handle, 0, nullptr, + nullptr, nullptr)); ASSERT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); } @@ -260,19 +247,21 @@ TEST_F(MessageTest, SerializeSimpleMessageNoHandlesWithContext) { TEST_F(MessageTest, SerializeDynamicallySizedMessage) { RunTestClient("ReceiveMessageNoHandles", [&](MojoHandle h) { MojoMessageHandle message; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); void* buffer; uint32_t buffer_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer(message, 0, nullptr, 0, &buffer, - &buffer_size)); - EXPECT_EQ(MOJO_RESULT_OK, MojoExtendSerializedMessagePayload( - message, sizeof(kTestMessageWithContext1) - 1, - nullptr, 0, &buffer, &buffer_size)); - EXPECT_EQ(MOJO_RESULT_OK, MojoCommitSerializedMessageContents( + MojoAppendMessageData(message, 0, nullptr, 0, nullptr, &buffer, + &buffer_size)); + + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData( message, sizeof(kTestMessageWithContext1) - 1, - &buffer, &buffer_size)); + nullptr, 0, &options, &buffer, &buffer_size)); + memcpy(buffer, kTestMessageWithContext1, sizeof(kTestMessageWithContext1) - 1); MojoWriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE); @@ -396,6 +385,53 @@ TEST_F(MessageTest, DropUnreadLocalMessageWithContext) { MOJO_HANDLE_SIGNAL_PEER_CLOSED)); } +TEST_F(MessageTest, GetMessageDataWithHandles) { + MojoHandle h[2]; + CreateMessagePipe(&h[0], &h[1]); + + MojoMessageHandle message_handle; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message_handle)); + + MojoAppendMessageDataOptions append_data_options; + append_data_options.struct_size = sizeof(append_data_options); + append_data_options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + const std::string kTestMessage = "hello"; + void* buffer; + uint32_t buffer_size; + ASSERT_EQ(MOJO_RESULT_OK, + MojoAppendMessageData( + message_handle, static_cast<uint32_t>(kTestMessage.size()), h, + 2, &append_data_options, &buffer, &buffer_size)); + memcpy(buffer, kTestMessage.data(), kTestMessage.size()); + + // Ignore handles the first time around. This should mean a subsequent call is + // allowed to grab the handles. + MojoGetMessageDataOptions get_data_options; + get_data_options.struct_size = sizeof(get_data_options); + get_data_options.flags = MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES; + EXPECT_EQ(MOJO_RESULT_OK, + MojoGetMessageData(message_handle, &get_data_options, &buffer, + &buffer_size, nullptr, nullptr)); + + // Now grab the handles. + uint32_t num_handles = 2; + EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageData(message_handle, nullptr, &buffer, + &buffer_size, h, &num_handles)); + EXPECT_EQ(2u, num_handles); + + // Should still be callable as long as we ignore handles. + EXPECT_EQ(MOJO_RESULT_OK, + MojoGetMessageData(message_handle, &get_data_options, &buffer, + &buffer_size, nullptr, nullptr)); + + // But not if we don't. + EXPECT_EQ(MOJO_RESULT_NOT_FOUND, + MojoGetMessageData(message_handle, nullptr, &buffer, &buffer_size, + h, &num_handles)); + + EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); +} + TEST_F(MessageTest, ReadMessageWithContextAsSerializedMessage) { bool message_was_destroyed = false; std::unique_ptr<TestMessageBase> message = @@ -421,9 +457,8 @@ TEST_F(MessageTest, ReadMessageWithContextAsSerializedMessage) { void* buffer; uint32_t num_handles = 0; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoGetSerializedMessageContents( - message_handle, &buffer, &num_bytes, nullptr, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes, + nullptr, &num_handles)); EXPECT_FALSE(message_was_destroyed); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); @@ -444,8 +479,7 @@ TEST_F(MessageTest, ReadSerializedMessageAsMessageWithContext) { MojoReadMessage(b, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE)); uintptr_t context; EXPECT_EQ(MOJO_RESULT_NOT_FOUND, - MojoGetMessageContext(message_handle, &context, - MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE)); + MojoGetMessageContext(message_handle, nullptr, &context)); MojoClose(a); MojoClose(b); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); @@ -459,7 +493,7 @@ TEST_F(MessageTest, ForceSerializeMessageWithContext) { base::Bind([](bool* was_destroyed) { *was_destroyed = true; }, &message_was_destroyed)); auto message_handle = TestMessageBase::MakeMessageHandle(std::move(message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle)); + EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr)); EXPECT_TRUE(message_was_destroyed); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); @@ -473,7 +507,7 @@ TEST_F(MessageTest, ForceSerializeMessageWithContext) { MessagePipe pipe1; message->AddMessagePipe(std::move(pipe1.handle0)); message_handle = TestMessageBase::MakeMessageHandle(std::move(message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle)); + EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr)); EXPECT_TRUE(message_was_destroyed); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(pipe1.handle1.get().value(), @@ -488,20 +522,18 @@ TEST_F(MessageTest, ForceSerializeMessageWithContext) { MessagePipe pipe2; message->AddMessagePipe(std::move(pipe2.handle0)); message_handle = TestMessageBase::MakeMessageHandle(std::move(message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle)); + EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr)); EXPECT_TRUE(message_was_destroyed); uint32_t num_bytes = 0; void* buffer = nullptr; uint32_t num_handles = 0; MojoHandle extracted_handle; EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - MojoGetSerializedMessageContents( - message_handle, &buffer, &num_bytes, nullptr, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes, + nullptr, &num_handles)); EXPECT_EQ(MOJO_RESULT_OK, - MojoGetSerializedMessageContents( - message_handle, &buffer, &num_bytes, &extracted_handle, - &num_handles, MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes, + &extracted_handle, &num_handles)); EXPECT_EQ(std::string(kTestMessageWithContext1).size(), num_bytes); EXPECT_EQ(std::string(kTestMessageWithContext1), base::StringPiece(static_cast<char*>(buffer), num_bytes)); @@ -528,10 +560,10 @@ TEST_F(MessageTest, DoubleSerialize) { // Ensure we can safely call |MojoSerializeMessage()| twice on the same // message handle. - EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle)); + EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr)); EXPECT_TRUE(message_was_destroyed); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoSerializeMessage(message_handle)); + MojoSerializeMessage(message_handle, nullptr)); // And also check that we can call it again after we've written and read the // message object from a pipe. @@ -545,22 +577,22 @@ TEST_F(MessageTest, DoubleSerialize) { MojoReadMessage(pipe.handle1->value(), &message_handle, MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoSerializeMessage(message_handle)); + MojoSerializeMessage(message_handle, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle)); } TEST_F(MessageTest, ExtendMessagePayload) { MojoMessageHandle message; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); const std::string kTestMessagePart1("hello i am message."); void* buffer; uint32_t buffer_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer( + MojoAppendMessageData( message, static_cast<uint32_t>(kTestMessagePart1.size()), - nullptr, 0, &buffer, &buffer_size)); + nullptr, 0, nullptr, &buffer, &buffer_size)); ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size())); memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size()); @@ -568,9 +600,9 @@ TEST_F(MessageTest, ExtendMessagePayload) { const std::string kTestMessageCombined1 = kTestMessagePart1 + kTestMessagePart2; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload( - message, static_cast<uint32_t>(kTestMessageCombined1.size()), - nullptr, 0, &buffer, &buffer_size)); + MojoAppendMessageData( + message, static_cast<uint32_t>(kTestMessagePart2.size()), + nullptr, 0, nullptr, &buffer, &buffer_size)); memcpy(static_cast<uint8_t*>(buffer) + kTestMessagePart1.size(), kTestMessagePart2.data(), kTestMessagePart2.size()); @@ -578,28 +610,27 @@ TEST_F(MessageTest, ExtendMessagePayload) { const std::string kTestMessageCombined2 = kTestMessageCombined1 + kTestMessagePart3; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload( - message, static_cast<uint32_t>(kTestMessageCombined2.size()), - nullptr, 0, &buffer, &buffer_size)); + MojoAppendMessageData( + message, static_cast<uint32_t>(kTestMessagePart3.size()), + nullptr, 0, nullptr, &buffer, &buffer_size)); memcpy(static_cast<uint8_t*>(buffer) + kTestMessageCombined1.size(), kTestMessagePart3.data(), kTestMessagePart3.size()); void* payload; uint32_t payload_size; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoGetSerializedMessageContents( - message, &payload, &payload_size, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message, nullptr, &payload, &payload_size, + nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCommitSerializedMessageContents( - message, static_cast<uint32_t>(kTestMessageCombined2.size()), - &buffer, &buffer_size)); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0, + &options, nullptr, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, - MojoGetSerializedMessageContents( - message, &payload, &payload_size, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message, nullptr, &payload, &payload_size, + nullptr, nullptr)); EXPECT_EQ(kTestMessageCombined2.size(), payload_size); EXPECT_EQ(0, memcmp(payload, kTestMessageCombined2.data(), kTestMessageCombined2.size())); @@ -609,7 +640,7 @@ TEST_F(MessageTest, ExtendMessagePayload) { TEST_F(MessageTest, ExtendMessageWithHandlesPayload) { MojoMessageHandle message; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); MojoHandle handles[2]; CreateMessagePipe(&handles[0], &handles[1]); @@ -618,34 +649,31 @@ TEST_F(MessageTest, ExtendMessageWithHandlesPayload) { void* buffer; uint32_t buffer_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer( + MojoAppendMessageData( message, static_cast<uint32_t>(kTestMessagePart1.size()), - handles, 2, &buffer, &buffer_size)); + handles, 2, nullptr, &buffer, &buffer_size)); ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size())); memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size()); const std::string kTestMessagePart2 = " in ur computer."; const std::string kTestMessageCombined1 = kTestMessagePart1 + kTestMessagePart2; + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload( - message, static_cast<uint32_t>(kTestMessageCombined1.size()), - nullptr, 0, &buffer, &buffer_size)); + MojoAppendMessageData( + message, static_cast<uint32_t>(kTestMessagePart2.size()), + nullptr, 0, &options, &buffer, &buffer_size)); memcpy(static_cast<uint8_t*>(buffer) + kTestMessagePart1.size(), kTestMessagePart2.data(), kTestMessagePart2.size()); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCommitSerializedMessageContents( - message, static_cast<uint32_t>(kTestMessageCombined1.size()), - &buffer, &buffer_size)); - void* payload; uint32_t payload_size; uint32_t num_handles = 2; EXPECT_EQ(MOJO_RESULT_OK, - MojoGetSerializedMessageContents( - message, &payload, &payload_size, handles, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message, nullptr, &payload, &payload_size, + handles, &num_handles)); EXPECT_EQ(2u, num_handles); EXPECT_EQ(kTestMessageCombined1.size(), payload_size); EXPECT_EQ(0, memcmp(payload, kTestMessageCombined1.data(), @@ -662,7 +690,7 @@ TEST_F(MessageTest, ExtendMessagePayloadLarge) { constexpr size_t kTestChunkSizes[] = {1, 2, 3, 64, 509, 4096, 16384, 65535}; for (const size_t kChunkSize : kTestChunkSizes) { MojoMessageHandle message; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); MojoHandle handles[2]; CreateMessagePipe(&handles[0], &handles[1]); @@ -671,17 +699,17 @@ TEST_F(MessageTest, ExtendMessagePayloadLarge) { void* buffer; uint32_t buffer_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer( + MojoAppendMessageData( message, static_cast<uint32_t>(kTestMessageHeader.size()), - handles, 2, &buffer, &buffer_size)); + handles, 2, nullptr, &buffer, &buffer_size)); ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessageHeader.size())); memcpy(buffer, kTestMessageHeader.data(), kTestMessageHeader.size()); - // 5 MB should be well beyond any reasonable default buffer size for the + // 512 kB should be well beyond any reasonable default buffer size for the // system implementation to choose, meaning that this test should guarantee // several reallocations of the serialized message buffer as we // progressively extend the payload to this size. - constexpr size_t kTestMessagePayloadSize = 5 * 1024 * 1024; + constexpr size_t kTestMessagePayloadSize = 512 * 1024; std::vector<uint8_t> test_payload(kTestMessagePayloadSize); base::RandBytes(test_payload.data(), kTestMessagePayloadSize); @@ -697,28 +725,27 @@ TEST_F(MessageTest, ExtendMessagePayloadLarge) { const size_t current_total_size = kTestMessageHeader.size() + current_payload_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload( - message, static_cast<uint32_t>(current_total_size), nullptr, - 0, &buffer, &buffer_size)); + MojoAppendMessageData( + message, static_cast<uint32_t>(current_chunk_size), nullptr, + 0, nullptr, &buffer, &buffer_size)); EXPECT_GE(buffer_size, static_cast<uint32_t>(current_total_size)); memcpy(static_cast<uint8_t*>(buffer) + previous_total_size, &test_payload[previous_payload_size], current_chunk_size); } + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; EXPECT_EQ(MOJO_RESULT_OK, - MojoCommitSerializedMessageContents( - message, - static_cast<uint32_t>(kTestMessageHeader.size() + - kTestMessagePayloadSize), - &buffer, &buffer_size)); + MojoAppendMessageData(message, 0, nullptr, 0, &options, nullptr, + nullptr)); void* payload; uint32_t payload_size; uint32_t num_handles = 2; EXPECT_EQ(MOJO_RESULT_OK, - MojoGetSerializedMessageContents( - message, &payload, &payload_size, handles, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE)); + MojoGetMessageData(message, nullptr, &payload, &payload_size, + handles, &num_handles)); EXPECT_EQ(static_cast<uint32_t>(kTestMessageHeader.size() + kTestMessagePayloadSize), payload_size); @@ -742,22 +769,21 @@ TEST_F(MessageTest, CorrectPayloadBufferBoundaries) { MojoMessageHandle message; void* buffer = nullptr; uint32_t buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoAttachSerializedMessageBuffer( - message, 0, nullptr, 0, &buffer, &buffer_size)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoAppendMessageData(message, 0, nullptr, 0, nullptr, &buffer, + &buffer_size)); // Fill the buffer end-to-end. memset(buffer, 'x', buffer_size); // Continuously grow and fill the message buffer several more times. Should // not crash. - uint32_t payload_size = 0; constexpr uint32_t kChunkSize = 4096; constexpr size_t kNumIterations = 1000; for (size_t i = 0; i < kNumIterations; ++i) { - payload_size += kChunkSize; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload(message, payload_size, nullptr, - 0, &buffer, &buffer_size)); + MojoAppendMessageData(message, kChunkSize, nullptr, 0, nullptr, + &buffer, &buffer_size)); memset(buffer, 'x', buffer_size); } @@ -768,23 +794,20 @@ TEST_F(MessageTest, CommitInvalidMessageContents) { // Regression test for https://crbug.com/755127. Ensures that we don't crash // if we attempt to commit the contents of an unserialized message. MojoMessageHandle message; - void* buffer; - uint32_t buffer_size; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - MojoCommitSerializedMessageContents(message, 0, &buffer, &buffer_size)); - EXPECT_EQ(MOJO_RESULT_OK, MojoAttachSerializedMessageBuffer( - message, 0, nullptr, 0, &buffer, &buffer_size)); - + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0, + nullptr, nullptr, nullptr)); MojoHandle a, b; CreateMessagePipe(&a, &b); - EXPECT_EQ(MOJO_RESULT_OK, MojoExtendSerializedMessagePayload( - message, 0, &a, 1, &buffer, &buffer_size)); + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, &a, 1, nullptr, + nullptr, nullptr)); UserMessageImpl::FailHandleSerializationForTesting(true); - EXPECT_EQ(MOJO_RESULT_OK, MojoCommitSerializedMessageContents( - message, 0, &buffer, &buffer_size)); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0, + nullptr, nullptr, nullptr)); UserMessageImpl::FailHandleSerializationForTesting(false); EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message)); } @@ -808,25 +831,25 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) { MojoMessageHandle message; void* buffer = nullptr; uint32_t buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoAttachSerializedMessageBuffer( - message, 0, handles, 5, &buffer, &buffer_size)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoAppendMessageData(message, 0, handles, 5, nullptr, &buffer, + &buffer_size)); // Force buffer reallocation by extending the payload beyond the original // buffer size. This should typically result in a relocation of the buffer as // well -- at least often enough that breakage will be caught by automated // tests. - uint32_t new_buffer_size = 0; + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; uint32_t payload_size = buffer_size * 64; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload(message, payload_size, nullptr, - 0, &buffer, &new_buffer_size)); + MojoAppendMessageData(message, payload_size, nullptr, 0, &options, + &buffer, &buffer_size)); + ASSERT_GE(buffer_size, payload_size); memset(buffer, 'x', payload_size); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCommitSerializedMessageContents(message, payload_size, &buffer, - &new_buffer_size)); - RunTestClient("ReadAndIgnoreMessage", [&](MojoHandle h) { // Send the message out of process to exercise the regression path where // internally cached, stale payload pointers may be dereferenced and written @@ -858,29 +881,25 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttachedViaExtension) { MojoMessageHandle message; void* buffer = nullptr; uint32_t buffer_size = 0; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoAttachSerializedMessageBuffer( - message, 0, handles, 1, &buffer, &buffer_size)); - uint32_t new_buffer_size = 0; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoAppendMessageData(message, 0, handles, 1, nullptr, &buffer, + &buffer_size)); uint32_t payload_size = buffer_size * 64; EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload(message, payload_size, nullptr, - 0, &buffer, &new_buffer_size)); + MojoAppendMessageData(message, payload_size, nullptr, 0, nullptr, + &buffer, nullptr)); // Add more handles. - EXPECT_EQ(MOJO_RESULT_OK, MojoExtendSerializedMessagePayload( - message, payload_size, handles + 1, 1, &buffer, - &new_buffer_size)); - EXPECT_EQ(MOJO_RESULT_OK, MojoExtendSerializedMessagePayload( - message, payload_size, handles + 2, 3, &buffer, - &new_buffer_size)); - + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, handles + 1, 1, + nullptr, &buffer, nullptr)); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, handles + 2, 3, + &options, &buffer, nullptr)); memset(buffer, 'x', payload_size); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCommitSerializedMessageContents(message, payload_size, &buffer, - &new_buffer_size)); - RunTestClient("ReadMessageAndCheckPipe", [&](MojoHandle h) { // Send the message out of process to exercise the regression path where // internally cached, stale payload pointers may be dereferenced and written @@ -907,7 +926,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadMessageAndCheckPipe, MessageTest, h) { TEST_F(MessageTest, PartiallySerializedMessagesDontLeakHandles) { MojoMessageHandle message; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); MojoHandle handles[2]; CreateMessagePipe(&handles[0], &handles[1]); @@ -916,16 +935,15 @@ TEST_F(MessageTest, PartiallySerializedMessagesDontLeakHandles) { void* buffer; uint32_t buffer_size; EXPECT_EQ(MOJO_RESULT_OK, - MojoAttachSerializedMessageBuffer( + MojoAppendMessageData( message, static_cast<uint32_t>(kTestMessagePart1.size()), - nullptr, 0, &buffer, &buffer_size)); + nullptr, 0, nullptr, &buffer, &buffer_size)); ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size())); memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size()); EXPECT_EQ(MOJO_RESULT_OK, - MojoExtendSerializedMessagePayload( - message, static_cast<uint32_t>(kTestMessagePart1.size()), - handles, 1, &buffer, &buffer_size)); + MojoAppendMessageData(message, 0, handles, 1, nullptr, &buffer, + &buffer_size)); // This must close |handles[0]|, which we can detect by observing the // signal state of |handles[1]. diff --git a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 8da4cc4c817..c9a00de91d3 100644 --- a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -338,6 +338,11 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) { MojoHandle shared_buffer; ASSERT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(&options, 100, &shared_buffer)); + MojoSharedBufferInfo buffer_info; + buffer_info.struct_size = sizeof(buffer_info); + ASSERT_EQ(MOJO_RESULT_OK, + MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info)); + EXPECT_EQ(100U, buffer_info.size); // Send the shared buffer. const std::string go1("go 1"); @@ -346,6 +351,10 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) { ASSERT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(shared_buffer, nullptr, &duplicated_shared_buffer)); + buffer_info.size = 0; + ASSERT_EQ(MOJO_RESULT_OK, + MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info)); + EXPECT_EQ(100U, buffer_info.size); MojoHandle handles[1]; handles[0] = duplicated_shared_buffer; ASSERT_EQ(MOJO_RESULT_OK, @@ -1284,7 +1293,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient, // Wait on handle 1 using a SimpleWatcher. { base::RunLoop run_loop; - SimpleWatcher watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); + SimpleWatcher watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()); watcher.Watch(Handle(handles[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, base::Bind( [](base::RunLoop* loop, MojoResult result) { diff --git a/chromium/mojo/edk/system/node_channel.h b/chromium/mojo/edk/system/node_channel.h index 657534f930a..864ed1c45bf 100644 --- a/chromium/mojo/edk/system/node_channel.h +++ b/chromium/mojo/edk/system/node_channel.h @@ -17,7 +17,7 @@ #include "base/task_runner.h" #include "build/build_config.h" #include "mojo/edk/embedder/connection_params.h" -#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/process_error_callback.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/ports/name.h" diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/edk/system/node_controller.cc index b014703735f..b8638a55f08 100644 --- a/chromium/mojo/edk/system/node_controller.cc +++ b/chromium/mojo/edk/system/node_controller.cc @@ -19,7 +19,6 @@ #include "base/rand_util.h" #include "base/time/time.h" #include "base/timer/elapsed_timer.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/named_platform_channel_pair.h" #include "mojo/edk/embedder/named_platform_handle.h" #include "mojo/edk/embedder/platform_channel_pair.h" diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/edk/system/node_controller.h index 1e929bb3acb..853442da197 100644 --- a/chromium/mojo/edk/system/node_controller.h +++ b/chromium/mojo/edk/system/node_controller.h @@ -28,6 +28,7 @@ #include "mojo/edk/system/ports/name.h" #include "mojo/edk/system/ports/node.h" #include "mojo/edk/system/ports/node_delegate.h" +#include "mojo/edk/system/system_impl_export.h" namespace base { class PortProvider; @@ -42,8 +43,8 @@ class MachPortRelay; // The owner of ports::Node which facilitates core EDK implementation. All // public interface methods are safe to call from any thread. -class NodeController : public ports::NodeDelegate, - public NodeChannel::Delegate { +class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate, + public NodeChannel::Delegate { public: class PortObserver : public ports::UserData { public: diff --git a/chromium/mojo/edk/system/ports/BUILD.gn b/chromium/mojo/edk/system/ports/BUILD.gn index 42fd523147e..1a5ba79279c 100644 --- a/chromium/mojo/edk/system/ports/BUILD.gn +++ b/chromium/mojo/edk/system/ports/BUILD.gn @@ -4,7 +4,9 @@ import("//testing/test.gni") -source_set("ports") { +component("ports") { + output_name = "mojo_edk_ports" + sources = [ "event.cc", "event.h", @@ -27,6 +29,8 @@ source_set("ports") { "user_message.h", ] + defines = [ "IS_MOJO_EDK_PORTS_IMPL" ] + public_deps = [ "//base", ] diff --git a/chromium/mojo/edk/system/ports/event.h b/chromium/mojo/edk/system/ports/event.h index 27dc4fdda86..ab8a4d80113 100644 --- a/chromium/mojo/edk/system/ports/event.h +++ b/chromium/mojo/edk/system/ports/event.h @@ -9,6 +9,7 @@ #include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "mojo/edk/system/ports/name.h" @@ -24,7 +25,7 @@ using ScopedEvent = std::unique_ptr<Event>; // A Event is the fundamental unit of operation and communication within and // between Nodes. -class Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) Event { public: enum Type : uint32_t { // A user message event contains arbitrary user-specified payload data @@ -102,7 +103,7 @@ class Event { DISALLOW_COPY_AND_ASSIGN(Event); }; -class UserMessageEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessageEvent : public Event { public: explicit UserMessageEvent(size_t num_ports); ~UserMessageEvent() override; @@ -152,7 +153,7 @@ class UserMessageEvent : public Event { DISALLOW_COPY_AND_ASSIGN(UserMessageEvent); }; -class PortAcceptedEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortAcceptedEvent : public Event { public: explicit PortAcceptedEvent(const PortName& port_name); ~PortAcceptedEvent() override; @@ -168,7 +169,7 @@ class PortAcceptedEvent : public Event { DISALLOW_COPY_AND_ASSIGN(PortAcceptedEvent); }; -class ObserveProxyEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyEvent : public Event { public: ObserveProxyEvent(const PortName& port_name, const NodeName& proxy_node_name, @@ -203,7 +204,7 @@ class ObserveProxyEvent : public Event { DISALLOW_COPY_AND_ASSIGN(ObserveProxyEvent); }; -class ObserveProxyAckEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyAckEvent : public Event { public: ObserveProxyAckEvent(const PortName& port_name, uint64_t last_sequence_num); ~ObserveProxyAckEvent() override; @@ -224,7 +225,7 @@ class ObserveProxyAckEvent : public Event { DISALLOW_COPY_AND_ASSIGN(ObserveProxyAckEvent); }; -class ObserveClosureEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveClosureEvent : public Event { public: ObserveClosureEvent(const PortName& port_name, uint64_t last_sequence_num); ~ObserveClosureEvent() override; @@ -248,7 +249,7 @@ class ObserveClosureEvent : public Event { DISALLOW_COPY_AND_ASSIGN(ObserveClosureEvent); }; -class MergePortEvent : public Event { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) MergePortEvent : public Event { public: MergePortEvent(const PortName& port_name, const PortName& new_port_name, diff --git a/chromium/mojo/edk/system/ports/message_queue.h b/chromium/mojo/edk/system/ports/message_queue.h index 3dc62267eb5..829d217213e 100644 --- a/chromium/mojo/edk/system/ports/message_queue.h +++ b/chromium/mojo/edk/system/ports/message_queue.h @@ -11,6 +11,7 @@ #include <memory> #include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "mojo/edk/system/ports/event.h" @@ -27,7 +28,7 @@ class MessageFilter; // known sequence number and can indicate whether the next sequential message is // available. Thus the queue enforces message ordering for the consumer without // enforcing it for the producer (see AcceptMessage() below.) -class MessageQueue { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) MessageQueue { public: explicit MessageQueue(); explicit MessageQueue(uint64_t next_sequence_num); diff --git a/chromium/mojo/edk/system/ports/name.h b/chromium/mojo/edk/system/ports/name.h index 72e41b92ab6..80d7ffc38d5 100644 --- a/chromium/mojo/edk/system/ports/name.h +++ b/chromium/mojo/edk/system/ports/name.h @@ -10,13 +10,14 @@ #include <ostream> #include <tuple> +#include "base/component_export.h" #include "base/hash.h" namespace mojo { namespace edk { namespace ports { -struct Name { +struct COMPONENT_EXPORT(MOJO_EDK_PORTS) Name { Name(uint64_t v1, uint64_t v2) : v1(v1), v2(v2) {} uint64_t v1, v2; }; @@ -33,21 +34,22 @@ inline bool operator<(const Name& a, const Name& b) { return std::tie(a.v1, a.v2) < std::tie(b.v1, b.v2); } +COMPONENT_EXPORT(MOJO_EDK_PORTS) std::ostream& operator<<(std::ostream& stream, const Name& name); -struct PortName : Name { +struct COMPONENT_EXPORT(MOJO_EDK_PORTS) PortName : Name { PortName() : Name(0, 0) {} PortName(uint64_t v1, uint64_t v2) : Name(v1, v2) {} }; -extern const PortName kInvalidPortName; +extern COMPONENT_EXPORT(MOJO_EDK_PORTS) const PortName kInvalidPortName; -struct NodeName : Name { +struct COMPONENT_EXPORT(MOJO_EDK_PORTS) NodeName : Name { NodeName() : Name(0, 0) {} NodeName(uint64_t v1, uint64_t v2) : Name(v1, v2) {} }; -extern const NodeName kInvalidNodeName; +extern COMPONENT_EXPORT(MOJO_EDK_PORTS) const NodeName kInvalidNodeName; } // namespace ports } // namespace edk @@ -56,14 +58,14 @@ extern const NodeName kInvalidNodeName; namespace std { template <> -struct hash<mojo::edk::ports::PortName> { +struct COMPONENT_EXPORT(MOJO_EDK_PORTS) hash<mojo::edk::ports::PortName> { std::size_t operator()(const mojo::edk::ports::PortName& name) const { return base::HashInts64(name.v1, name.v2); } }; template <> -struct hash<mojo::edk::ports::NodeName> { +struct COMPONENT_EXPORT(MOJO_EDK_PORTS) hash<mojo::edk::ports::NodeName> { std::size_t operator()(const mojo::edk::ports::NodeName& name) const { return base::HashInts64(name.v1, name.v2); } diff --git a/chromium/mojo/edk/system/ports/node.cc b/chromium/mojo/edk/system/ports/node.cc index 76787aaa4da..78365e4d856 100644 --- a/chromium/mojo/edk/system/ports/node.cc +++ b/chromium/mojo/edk/system/ports/node.cc @@ -345,6 +345,10 @@ int Node::GetMessage(const PortRef& port_ref, DCHECK(locker.port()->state == Port::kReceiving); locker.port()->message_queue.set_signalable(true); } + + // The user may retransmit this message from another port. We reset the + // sequence number so that the message will get a new one if that happens. + (*message)->set_sequence_num(0); } return OK; diff --git a/chromium/mojo/edk/system/ports/node.h b/chromium/mojo/edk/system/ports/node.h index 5bc8a12b737..ec4bbbcd439 100644 --- a/chromium/mojo/edk/system/ports/node.h +++ b/chromium/mojo/edk/system/ports/node.h @@ -11,6 +11,7 @@ #include <queue> #include <unordered_map> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -61,7 +62,7 @@ class NodeDelegate; // by Nodes to coordinate Port behavior and lifetime within and across Nodes. // See Event documentation for description of different types of events used by // a Node to coordinate behavior. -class Node { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) Node { public: enum class ShutdownPolicy { DONT_ALLOW_LOCAL_PORTS, diff --git a/chromium/mojo/edk/system/ports/port_ref.h b/chromium/mojo/edk/system/ports/port_ref.h index dce317e63d7..9bafe38f474 100644 --- a/chromium/mojo/edk/system/ports/port_ref.h +++ b/chromium/mojo/edk/system/ports/port_ref.h @@ -5,6 +5,7 @@ #ifndef MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_ #define MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_ +#include "base/component_export.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "mojo/edk/system/ports/name.h" @@ -16,7 +17,7 @@ namespace ports { class Port; class PortLocker; -class PortRef { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortRef { public: ~PortRef(); PortRef(); diff --git a/chromium/mojo/edk/system/ports/ports_unittest.cc b/chromium/mojo/edk/system/ports/ports_unittest.cc index e74e7c8069f..f04ac49f609 100644 --- a/chromium/mojo/edk/system/ports/ports_unittest.cc +++ b/chromium/mojo/edk/system/ports/ports_unittest.cc @@ -1601,6 +1601,43 @@ TEST_F(PortsTest, RemotePeerStatusAfterRemotePortMerge) { EXPECT_TRUE(node1.node().CanShutdownCleanly()); } +TEST_F(PortsTest, RetransmitUserMessageEvents) { + // Ensures that user message events can be retransmitted properly. + TestNode node0(0); + AddNode(&node0); + + PortRef a, b; + node0.node().CreatePortPair(&a, &b); + + // Ping. + const char* kMessage = "hey"; + ScopedMessage message; + EXPECT_EQ(OK, node0.SendStringMessage(a, kMessage)); + ASSERT_TRUE(node0.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage)); + + // Pong. + EXPECT_EQ(OK, node0.node().SendUserMessage(b, std::move(message))); + EXPECT_FALSE(message); + ASSERT_TRUE(node0.ReadMessage(a, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage)); + + // Ping again. + EXPECT_EQ(OK, node0.node().SendUserMessage(a, std::move(message))); + EXPECT_FALSE(message); + ASSERT_TRUE(node0.ReadMessage(b, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage)); + + // Pong again! + EXPECT_EQ(OK, node0.node().SendUserMessage(b, std::move(message))); + EXPECT_FALSE(message); + ASSERT_TRUE(node0.ReadMessage(a, &message)); + EXPECT_TRUE(MessageEquals(message, kMessage)); + + EXPECT_EQ(OK, node0.node().ClosePort(a)); + EXPECT_EQ(OK, node0.node().ClosePort(b)); +} + } // namespace test } // namespace ports } // namespace edk diff --git a/chromium/mojo/edk/system/ports/user_message.h b/chromium/mojo/edk/system/ports/user_message.h index 435e203cec7..b4414b2de21 100644 --- a/chromium/mojo/edk/system/ports/user_message.h +++ b/chromium/mojo/edk/system/ports/user_message.h @@ -5,6 +5,7 @@ #ifndef MOJO_EDK_SYSTEM_PORTS_USER_MESSAGE_H_ #define MOJO_EDK_SYSTEM_PORTS_USER_MESSAGE_H_ +#include "base/component_export.h" #include "base/macros.h" namespace mojo { @@ -21,7 +22,7 @@ namespace ports { // |kUserMessageTypeInfo| and pass its address down to the UserMessage // constructor. The type of a UserMessage can then be dynamically inspected by // comparing |type_info()| to any subclass's |&kUserMessageTypeInfo|. -class UserMessage { +class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessage { public: struct TypeInfo {}; diff --git a/chromium/mojo/edk/system/request_context.cc b/chromium/mojo/edk/system/request_context.cc index 5de65d7b641..4de4343fa2b 100644 --- a/chromium/mojo/edk/system/request_context.cc +++ b/chromium/mojo/edk/system/request_context.cc @@ -36,9 +36,9 @@ RequestContext::~RequestContext() { // since we're starting over at the bottom of the stack. tls_context_->Set(nullptr); - MojoWatcherNotificationFlags flags = MOJO_WATCHER_NOTIFICATION_FLAG_NONE; - if (source_ == Source::SYSTEM) - flags |= MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM; + MojoTrapEventFlags flags = MOJO_TRAP_EVENT_FLAG_NONE; + if (source_ == Source::LOCAL_API_CALL) + flags |= MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL; // We send all cancellation notifications first. This is necessary because // it's possible that cancelled watches have other pending notifications diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc index f65fd88e36e..ca9a1a84359 100644 --- a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc @@ -12,7 +12,6 @@ #include <utility> #include "base/logging.h" -#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/options_validation.h" @@ -240,6 +239,15 @@ MojoResult SharedBufferDispatcher::MapBuffer( return MOJO_RESULT_OK; } +MojoResult SharedBufferDispatcher::GetBufferInfo(MojoSharedBufferInfo* info) { + if (!info) + return MOJO_RESULT_INVALID_ARGUMENT; + + base::AutoLock lock(lock_); + info->size = shared_buffer_->GetNumBytes(); + return MOJO_RESULT_OK; +} + void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, uint32_t* num_ports, uint32_t* num_platform_handles) { diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.h b/chromium/mojo/edk/system/shared_buffer_dispatcher.h index 351a7d19d37..fcaf5c19139 100644 --- a/chromium/mojo/edk/system/shared_buffer_dispatcher.h +++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.h @@ -76,6 +76,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher { uint64_t num_bytes, MojoMapBufferFlags flags, std::unique_ptr<PlatformSharedBufferMapping>* mapping) override; + MojoResult GetBufferInfo(MojoSharedBufferInfo* info) override; void StartSerialize(uint32_t* num_bytes, uint32_t* num_ports, uint32_t* num_platform_handles) override; diff --git a/chromium/mojo/edk/system/signals_unittest.cc b/chromium/mojo/edk/system/signals_unittest.cc index 4c43379d2e0..becba29e6ff 100644 --- a/chromium/mojo/edk/system/signals_unittest.cc +++ b/chromium/mojo/edk/system/signals_unittest.cc @@ -7,6 +7,7 @@ #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/functions.h" #include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" namespace mojo { @@ -130,24 +131,28 @@ TEST_F(SignalsTest, RemotePeers) { EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_NOT_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_NOT_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); RunTestClient("RemotePeersClient", [&](MojoHandle h) { // The bootstrap pipe should eventually signal remoteness. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); // And so should |a| after we send its peer. WriteMessageWithHandles(h, ":)", &b, 1); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); @@ -155,8 +160,9 @@ TEST_F(SignalsTest, RemotePeers) { MojoHandle c, d; CreateMessagePipe(&c, &d); EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(d, a)); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(c, &state)); EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); @@ -172,7 +178,7 @@ TEST_F(SignalsTest, RemotePeers) { // Wait for |a| to see its peer as local again. EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_NOT_SATISFIED)); + MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); }); @@ -180,15 +186,17 @@ TEST_F(SignalsTest, RemotePeers) { DEFINE_TEST_CLIENT_TEST_WITH_PIPE(RemotePeersClient, SignalsTest, h) { // The bootstrap pipe should eventually signal remoteness. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); MojoHandle b; EXPECT_EQ(":)", ReadMessageWithHandles(h, &b, 1)); // And so should |b|. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, - MOJO_WATCH_CONDITION_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); // Wait for the test to signal that it's ready to read |b| back. EXPECT_EQ("OK!", ReadMessage(h)); diff --git a/chromium/mojo/edk/system/watcher_unittest.cc b/chromium/mojo/edk/system/trap_unittest.cc index d541e9204e5..3081a223019 100644 --- a/chromium/mojo/edk/system/watcher_unittest.cc +++ b/chromium/mojo/edk/system/trap_unittest.cc @@ -19,14 +19,39 @@ #include "base/time/time.h" #include "mojo/edk/test/mojo_test_base.h" #include "mojo/public/c/system/data_pipe.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { namespace edk { namespace { +// TODO(https://crbug.com/819046): These are temporary wrappers to reduce +// changes necessary during the API rename. Remove them. + +MojoResult MojoWatch(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context) { + return MojoAddTrigger(trap_handle, handle, signals, condition, context, + nullptr); +} + +MojoResult MojoCancelWatch(MojoHandle trap_handle, uintptr_t context) { + return MojoRemoveTrigger(trap_handle, context, nullptr); +} + +MojoResult MojoArmWatcher(MojoHandle trap_handle, + uint32_t* num_ready_contexts, + uintptr_t* ready_contexts, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals) { + return MojoArmTrap(trap_handle, nullptr, num_ready_contexts, ready_contexts, + ready_results, ready_signals); +} + using WatcherTest = test::MojoTestBase; class WatchHelper { @@ -38,7 +63,7 @@ class WatchHelper { ~WatchHelper() {} MojoResult CreateWatcher(MojoHandle* handle) { - return MojoCreateWatcher(&Notify, handle); + return MojoCreateTrap(&Notify, nullptr, handle); } uintptr_t CreateContext(const ContextCallback& callback) { @@ -85,11 +110,9 @@ class WatchHelper { DISALLOW_COPY_AND_ASSIGN(NotificationContext); }; - static void Notify(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - reinterpret_cast<NotificationContext*>(context)->Notify(result, state); + static void Notify(const MojoTrapEvent* event) { + reinterpret_cast<NotificationContext*>(event->trigger_context) + ->Notify(event->result, event->signals_state); } DISALLOW_COPY_AND_ASSIGN(WatchHelper); @@ -109,25 +132,19 @@ class ThreadedRunner : public base::SimpleThread { DISALLOW_COPY_AND_ASSIGN(ThreadedRunner); }; -void ExpectNoNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { +void ExpectNoNotification(const MojoTrapEvent* event) { NOTREACHED(); } -void ExpectOnlyCancel(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - EXPECT_EQ(result, MOJO_RESULT_CANCELLED); +void ExpectOnlyCancel(const MojoTrapEvent* event) { + EXPECT_EQ(event->result, MOJO_RESULT_CANCELLED); } TEST_F(WatcherTest, InvalidArguments) { EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoCreateWatcher(&ExpectNoNotification, nullptr)); + MojoCreateTrap(&ExpectNoNotification, nullptr, nullptr)); MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w)); // Try to watch unwatchable handles. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, @@ -698,7 +715,7 @@ TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandlePeer) { TEST_F(WatcherTest, ArmWithNoWatches) { MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w)); EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); @@ -709,7 +726,7 @@ TEST_F(WatcherTest, WatchDuplicateContext) { CreateMessagePipe(&a, &b); MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, MOJO_WATCH_CONDITION_SATISFIED, 0)); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, @@ -723,7 +740,7 @@ TEST_F(WatcherTest, WatchDuplicateContext) { TEST_F(WatcherTest, CancelUnknownWatch) { MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w)); EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoCancelWatch(w, 1234)); } @@ -732,7 +749,7 @@ TEST_F(WatcherTest, ArmWithWatchAlreadySatisfied) { CreateMessagePipe(&a, &b); MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_WATCH_CONDITION_SATISFIED, 0)); @@ -759,7 +776,7 @@ TEST_F(WatcherTest, ArmWithWatchAlreadyUnsatisfiable) { CreateMessagePipe(&a, &b); MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, MOJO_WATCH_CONDITION_SATISFIED, 0)); @@ -1638,7 +1655,7 @@ TEST_F(WatcherTest, ArmFailureCirculation) { // Create a watcher and watch all of them. MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w)); for (size_t i = 0; i < kNumTestHandles; ++i) { EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, handles[i], MOJO_HANDLE_SIGNAL_READABLE, @@ -1725,12 +1742,9 @@ TEST_F(WatcherTest, WatchNotSatisfied) { base::Closure g_do_random_thing_callback; -void ReadAllMessages(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - if (result == MOJO_RESULT_OK) { - MojoHandle handle = static_cast<MojoHandle>(context); +void ReadAllMessages(const MojoTrapEvent* event) { + if (event->result == MOJO_RESULT_OK) { + MojoHandle handle = static_cast<MojoHandle>(event->trigger_context); MojoMessageHandle message; while (MojoReadMessage(handle, &message, MOJO_READ_MESSAGE_FLAG_NONE) == MOJO_RESULT_OK) { @@ -1762,9 +1776,9 @@ void DoRandomThing(MojoHandle* watchers, case 3: case 4: { MojoMessageHandle message; - ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message)); ASSERT_EQ(MOJO_RESULT_OK, - MojoAttachMessageContext(message, 1, nullptr, nullptr)); + MojoSetMessageContext(message, 1, nullptr, nullptr, nullptr)); MojoWriteMessage(RandomHandle(watched_handles, num_watched_handles), message, MOJO_WRITE_MESSAGE_FLAG_NONE); break; @@ -1787,7 +1801,13 @@ void DoRandomThing(MojoHandle* watchers, &num_ready_contexts, &ready_context, &ready_result, &ready_state) == MOJO_RESULT_FAILED_PRECONDITION && ready_result == MOJO_RESULT_OK) { - ReadAllMessages(ready_context, ready_result, ready_state, 0); + MojoTrapEvent event; + event.struct_size = sizeof(event); + event.trigger_context = ready_context; + event.result = ready_result; + event.signals_state = ready_state; + event.flags = MOJO_TRAP_EVENT_FLAG_NONE; + ReadAllMessages(&event); } break; } @@ -1822,7 +1842,7 @@ TEST_F(WatcherTest, ConcurrencyStressTest) { kNumWatchedHandles); for (size_t i = 0; i < kNumWatchers; ++i) - MojoCreateWatcher(&ReadAllMessages, &watchers[i]); + MojoCreateTrap(&ReadAllMessages, nullptr, &watchers[i]); for (size_t i = 0; i < kNumWatchedHandles; i += 2) CreateMessagePipe(&watched_handles[i], &watched_handles[i + 1]); diff --git a/chromium/mojo/edk/system/user_message_impl.cc b/chromium/mojo/edk/system/user_message_impl.cc index f9659bd740a..c894aa5e740 100644 --- a/chromium/mojo/edk/system/user_message_impl.cc +++ b/chromium/mojo/edk/system/user_message_impl.cc @@ -7,18 +7,23 @@ #include <algorithm> #include <vector> +#include "base/atomicops.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros_local.h" +#include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" -#include "mojo/edk/embedder/embedder_internal.h" +#include "base/trace_event/memory_allocator_dump.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_provider.h" +#include "base/trace_event/trace_event.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/node_channel.h" #include "mojo/edk/system/node_controller.h" #include "mojo/edk/system/ports/event.h" #include "mojo/edk/system/ports/message_filter.h" #include "mojo/edk/system/ports/node.h" -#include "mojo/public/cpp/system/handle.h" +#include "mojo/public/c/system/types.h" namespace mojo { namespace edk { @@ -28,7 +33,7 @@ namespace { // The minimum amount of memory to allocate for a new serialized message buffer. // This should be sufficiently large such that most seiralized messages do not // incur any reallocations as they're expanded to full size. -const uint32_t kMinimumPayloadBufferSize = 4096; +const uint32_t kMinimumPayloadBufferSize = 128; // Indicates whether handle serialization failure should be emulated in testing. bool g_always_fail_handle_serialization = false; @@ -254,6 +259,47 @@ MojoResult CreateOrExtendSerializedEventMessage( return MOJO_RESULT_OK; } +base::subtle::Atomic32 g_message_count = 0; + +void IncrementMessageCount() { + base::subtle::NoBarrier_AtomicIncrement(&g_message_count, 1); +} + +void DecrementMessageCount() { + base::subtle::NoBarrier_AtomicIncrement(&g_message_count, -1); +} + +class MessageMemoryDumpProvider : public base::trace_event::MemoryDumpProvider { + public: + MessageMemoryDumpProvider() { + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + this, "MojoMessages", nullptr); + } + + ~MessageMemoryDumpProvider() override { + base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( + this); + } + + private: + // base::trace_event::MemoryDumpProvider: + bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) override { + auto* dump = pmd->CreateAllocatorDump("mojo/messages"); + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount, + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + base::subtle::NoBarrier_Load(&g_message_count)); + return true; + } + + DISALLOW_COPY_AND_ASSIGN(MessageMemoryDumpProvider); +}; + +void EnsureMemoryDumpProviderExists() { + static base::NoDestructor<MessageMemoryDumpProvider> provider; + ALLOW_UNUSED_LOCAL(provider); +} + } // namespace // static @@ -273,17 +319,19 @@ UserMessageImpl::~UserMessageImpl() { if (result == MOJO_RESULT_OK) { for (auto handle : handles) { if (handle != MOJO_HANDLE_INVALID) - MojoClose(handle); + Core::Get()->Close(handle); } } if (!pending_handle_attachments_.empty()) { - internal::g_core->ReleaseDispatchersForTransit( - pending_handle_attachments_, false); + Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_, + false); for (const auto& dispatcher : pending_handle_attachments_) - MojoClose(dispatcher.local_handle); + Core::Get()->Close(dispatcher.local_handle); } } + + DecrementMessageCount(); } // static @@ -365,12 +413,6 @@ Channel::MessagePtr UserMessageImpl::FinalizeEventMessage( return channel_message; } -uintptr_t UserMessageImpl::ReleaseContext() { - uintptr_t context = context_; - context_ = 0; - return context; -} - size_t UserMessageImpl::user_payload_capacity() const { DCHECK(IsSerialized()); const size_t user_payload_offset = @@ -387,11 +429,13 @@ size_t UserMessageImpl::num_handles() const { return static_cast<const MessageHeader*>(header_)->num_dispatchers; } -MojoResult UserMessageImpl::AttachContext( +MojoResult UserMessageImpl::SetContext( uintptr_t context, MojoMessageContextSerializer serializer, MojoMessageContextDestructor destructor) { - if (HasContext()) + if (!context && (serializer || destructor)) + return MOJO_RESULT_INVALID_ARGUMENT; + if (context && HasContext()) return MOJO_RESULT_ALREADY_EXISTS; if (IsSerialized()) return MOJO_RESULT_FAILED_PRECONDITION; @@ -401,97 +445,82 @@ MojoResult UserMessageImpl::AttachContext( return MOJO_RESULT_OK; } -MojoResult UserMessageImpl::AttachSerializedMessageBuffer( - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles) { +MojoResult UserMessageImpl::AppendData(uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles) { + if (HasContext()) + return MOJO_RESULT_FAILED_PRECONDITION; + std::vector<Dispatcher::DispatcherInTransit> dispatchers; if (num_handles > 0) { - MojoResult acquire_result = internal::g_core->AcquireDispatchersForTransit( + MojoResult acquire_result = Core::Get()->AcquireDispatchersForTransit( handles, num_handles, &dispatchers); if (acquire_result != MOJO_RESULT_OK) return acquire_result; } - Channel::MessagePtr channel_message; - MojoResult rv = CreateOrExtendSerializedEventMessage( - message_event_, payload_size, - std::max(payload_size, kMinimumPayloadBufferSize), dispatchers.data(), - num_handles, &channel_message, &header_, &header_size_, &user_payload_); - if (num_handles > 0) { - internal::g_core->ReleaseDispatchersForTransit(dispatchers, - rv == MOJO_RESULT_OK); - } - if (rv != MOJO_RESULT_OK) - return MOJO_RESULT_ABORTED; - user_payload_size_ = payload_size; - channel_message_ = std::move(channel_message); - has_serialized_handles_ = true; - return MOJO_RESULT_OK; -} - -MojoResult UserMessageImpl::ExtendSerializedMessagePayload( - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles) { - if (!IsSerialized()) - return MOJO_RESULT_FAILED_PRECONDITION; - if (new_payload_size < user_payload_size_) - return MOJO_RESULT_OUT_OF_RANGE; - if (num_handles > 0) { - // In order to avoid rather expensive message resizing on every individual - // handle attachment operation, we merely lock and prepare the handle for - // transit here, deferring serialization until FinalizeEventMessage(). - MojoResult acquire_result = internal::g_core->AcquireDispatchersForTransit( - handles, num_handles, &pending_handle_attachments_); - if (acquire_result != MOJO_RESULT_OK) - return acquire_result; - } + if (!IsSerialized()) { + // First data for this message. + Channel::MessagePtr channel_message; + MojoResult rv = CreateOrExtendSerializedEventMessage( + message_event_, additional_payload_size, + std::max(additional_payload_size, kMinimumPayloadBufferSize), + dispatchers.data(), num_handles, &channel_message, &header_, + &header_size_, &user_payload_); + if (num_handles > 0) { + Core::Get()->ReleaseDispatchersForTransit(dispatchers, + rv == MOJO_RESULT_OK); + } + if (rv != MOJO_RESULT_OK) + return MOJO_RESULT_ABORTED; - if (new_payload_size > user_payload_size_) { - size_t header_offset = - static_cast<uint8_t*>(header_) - - static_cast<const uint8_t*>(channel_message_->payload()); - size_t user_payload_offset = - static_cast<uint8_t*>(user_payload_) - - static_cast<const uint8_t*>(channel_message_->payload()); - channel_message_->ExtendPayload(user_payload_offset + new_payload_size); - header_ = static_cast<uint8_t*>(channel_message_->mutable_payload()) + - header_offset; - user_payload_ = static_cast<uint8_t*>(channel_message_->mutable_payload()) + - user_payload_offset; - user_payload_size_ = new_payload_size; + user_payload_size_ = additional_payload_size; + channel_message_ = std::move(channel_message); + has_serialized_handles_ = true; + } else { + // Extend the existing message payload. + + // In order to avoid rather expensive message resizing on every handle + // attachment operation, we merely lock and prepare the handle for transit + // here, deferring serialization until |CommitSize()|. + std::copy(dispatchers.begin(), dispatchers.end(), + std::back_inserter(pending_handle_attachments_)); + + if (additional_payload_size) { + size_t header_offset = + static_cast<uint8_t*>(header_) - + static_cast<const uint8_t*>(channel_message_->payload()); + size_t user_payload_offset = + static_cast<uint8_t*>(user_payload_) - + static_cast<const uint8_t*>(channel_message_->payload()); + channel_message_->ExtendPayload(user_payload_offset + user_payload_size_ + + additional_payload_size); + header_ = static_cast<uint8_t*>(channel_message_->mutable_payload()) + + header_offset; + user_payload_ = + static_cast<uint8_t*>(channel_message_->mutable_payload()) + + user_payload_offset; + user_payload_size_ += additional_payload_size; + } } return MOJO_RESULT_OK; } -MojoResult UserMessageImpl::CommitSerializedContents( - uint32_t final_payload_size) { +MojoResult UserMessageImpl::CommitSize() { if (!IsSerialized()) return MOJO_RESULT_FAILED_PRECONDITION; - if (final_payload_size > user_payload_capacity() || - final_payload_size < user_payload_size_) { - return MOJO_RESULT_OUT_OF_RANGE; - } - if (is_committed_) return MOJO_RESULT_OK; - size_t user_payload_offset = - static_cast<uint8_t*>(user_payload_) - - static_cast<const uint8_t*>(channel_message_->payload()); - user_payload_size_ = final_payload_size; - channel_message_->ExtendPayload(user_payload_offset + user_payload_size_); - if (!pending_handle_attachments_.empty()) { CreateOrExtendSerializedEventMessage( message_event_, user_payload_size_, user_payload_size_, pending_handle_attachments_.data(), pending_handle_attachments_.size(), &channel_message_, &header_, &header_size_, &user_payload_); - internal::g_core->ReleaseDispatchersForTransit(pending_handle_attachments_, - true); + Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_, + true); pending_handle_attachments_.clear(); } @@ -508,7 +537,8 @@ MojoResult UserMessageImpl::SerializeIfNecessary() { if (!context_serializer_) return MOJO_RESULT_NOT_FOUND; - uintptr_t context = ReleaseContext(); + uintptr_t context = context_; + context_ = 0; context_serializer_(reinterpret_cast<MojoMessageHandle>(message_event_), context); @@ -598,7 +628,7 @@ MojoResult UserMessageImpl::ExtractSerializedHandles( platform_handle_index = next_platform_handle_index.ValueOrDie(); } - if (!internal::g_core->AddDispatchersFromTransit(dispatchers, handles)) + if (!Core::Get()->AddDispatchersFromTransit(dispatchers, handles)) return MOJO_RESULT_ABORTED; return MOJO_RESULT_OK; @@ -610,8 +640,10 @@ void UserMessageImpl::FailHandleSerializationForTesting(bool fail) { } UserMessageImpl::UserMessageImpl(ports::UserMessageEvent* message_event) - : ports::UserMessage(&kUserMessageTypeInfo), - message_event_(message_event) {} + : ports::UserMessage(&kUserMessageTypeInfo), message_event_(message_event) { + EnsureMemoryDumpProviderExists(); + IncrementMessageCount(); +} UserMessageImpl::UserMessageImpl(ports::UserMessageEvent* message_event, Channel::MessagePtr channel_message, @@ -627,7 +659,10 @@ UserMessageImpl::UserMessageImpl(ports::UserMessageEvent* message_event, header_(header), header_size_(header_size), user_payload_(user_payload), - user_payload_size_(user_payload_size) {} + user_payload_size_(user_payload_size) { + EnsureMemoryDumpProviderExists(); + IncrementMessageCount(); +} bool UserMessageImpl::WillBeRoutedExternally() { MojoResult result = SerializeIfNecessary(); diff --git a/chromium/mojo/edk/system/user_message_impl.h b/chromium/mojo/edk/system/user_message_impl.h index a282c453562..dc974c31077 100644 --- a/chromium/mojo/edk/system/user_message_impl.h +++ b/chromium/mojo/edk/system/user_message_impl.h @@ -21,7 +21,6 @@ #include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/handle.h" namespace mojo { namespace edk { @@ -83,7 +82,6 @@ class MOJO_SYSTEM_IMPL_EXPORT UserMessageImpl : public ports::UserMessage { std::unique_ptr<ports::UserMessageEvent> event); bool HasContext() const { return context_ != 0; } - uintptr_t ReleaseContext(); uintptr_t context() const { return context_; } @@ -120,16 +118,13 @@ class MOJO_SYSTEM_IMPL_EXPORT UserMessageImpl : public ports::UserMessage { void set_source_node(const ports::NodeName& name) { source_node_ = name; } const ports::NodeName& source_node() const { return source_node_; } - MojoResult AttachContext(uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor); - MojoResult AttachSerializedMessageBuffer(uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles); - MojoResult ExtendSerializedMessagePayload(uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles); - MojoResult CommitSerializedContents(uint32_t final_payload_size); + MojoResult SetContext(uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor); + MojoResult AppendData(uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles); + MojoResult CommitSize(); // If this message is not already serialized, this serializes it. MojoResult SerializeIfNecessary(); diff --git a/chromium/mojo/edk/system/watch.cc b/chromium/mojo/edk/system/watch.cc index 63d8beb56b1..bc1d84337e4 100644 --- a/chromium/mojo/edk/system/watch.cc +++ b/chromium/mojo/edk/system/watch.cc @@ -14,7 +14,7 @@ Watch::Watch(const scoped_refptr<WatcherDispatcher>& watcher, const scoped_refptr<Dispatcher>& dispatcher, uintptr_t context, MojoHandleSignals signals, - MojoWatchCondition condition) + MojoTriggerCondition condition) : watcher_(watcher), dispatcher_(dispatcher), context_(context), @@ -31,15 +31,15 @@ bool Watch::NotifyState(const HandleSignalsState& state, RequestContext* const request_context = RequestContext::current(); const bool notify_success = (state.satisfies_any(signals_) && - condition_ == MOJO_WATCH_CONDITION_SATISFIED) || + condition_ == MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED) || (!state.satisfies_all(signals_) && - condition_ == MOJO_WATCH_CONDITION_NOT_SATISFIED); + condition_ == MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED); if (notify_success) { rv = MOJO_RESULT_OK; if (allowed_to_call_callback && rv != last_known_result_) { request_context->AddWatchNotifyFinalizer(this, MOJO_RESULT_OK, state); } - } else if (condition_ == MOJO_WATCH_CONDITION_SATISFIED && + } else if (condition_ == MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED && !state.can_satisfy_any(signals_)) { rv = MOJO_RESULT_FAILED_PRECONDITION; if (allowed_to_call_callback && rv != last_known_result_) { @@ -60,7 +60,7 @@ void Watch::Cancel() { void Watch::InvokeCallback(MojoResult result, const HandleSignalsState& state, - MojoWatcherNotificationFlags flags) { + MojoTrapEventFlags flags) { // We hold the lock through invocation to ensure that only one notification // callback runs for this context at any given time. base::AutoLock lock(notification_lock_); diff --git a/chromium/mojo/edk/system/watch.h b/chromium/mojo/edk/system/watch.h index e706e915500..07d6169379a 100644 --- a/chromium/mojo/edk/system/watch.h +++ b/chromium/mojo/edk/system/watch.h @@ -10,6 +10,7 @@ #include "base/synchronization/lock.h" #include "mojo/edk/system/atomic_flag.h" #include "mojo/edk/system/handle_signals_state.h" +#include "mojo/public/c/system/trap.h" namespace mojo { namespace edk { @@ -31,7 +32,7 @@ class Watch : public base::RefCountedThreadSafe<Watch> { const scoped_refptr<Dispatcher>& dispatcher, uintptr_t context, MojoHandleSignals signals, - MojoWatchCondition condition); + MojoTriggerCondition condition); // Notifies the Watch of a potential state change. // @@ -60,7 +61,7 @@ class Watch : public base::RefCountedThreadSafe<Watch> { // down into the WatcherDispatcher to do the actual notification call. void InvokeCallback(MojoResult result, const HandleSignalsState& state, - MojoWatcherNotificationFlags flags); + MojoTrapEventFlags flags); const scoped_refptr<Dispatcher>& dispatcher() const { return dispatcher_; } uintptr_t context() const { return context_; } @@ -96,7 +97,7 @@ class Watch : public base::RefCountedThreadSafe<Watch> { const scoped_refptr<Dispatcher> dispatcher_; const uintptr_t context_; const MojoHandleSignals signals_; - const MojoWatchCondition condition_; + const MojoTriggerCondition condition_; // The result code with which this Watch would notify if currently armed, // based on the last known signaling state of |dispatcher_|. Guarded by the diff --git a/chromium/mojo/edk/system/watcher_dispatcher.cc b/chromium/mojo/edk/system/watcher_dispatcher.cc index f84db482980..6e8a44280ef 100644 --- a/chromium/mojo/edk/system/watcher_dispatcher.cc +++ b/chromium/mojo/edk/system/watcher_dispatcher.cc @@ -15,8 +15,8 @@ namespace mojo { namespace edk { -WatcherDispatcher::WatcherDispatcher(MojoWatcherCallback callback) - : callback_(callback) {} +WatcherDispatcher::WatcherDispatcher(MojoTrapEventHandler handler) + : handler_(handler) {} void WatcherDispatcher::NotifyHandleState(Dispatcher* dispatcher, const HandleSignalsState& state) { @@ -58,11 +58,17 @@ void WatcherDispatcher::NotifyHandleClosed(Dispatcher* dispatcher) { watch->Cancel(); } -void WatcherDispatcher::InvokeWatchCallback( - uintptr_t context, - MojoResult result, - const HandleSignalsState& state, - MojoWatcherNotificationFlags flags) { +void WatcherDispatcher::InvokeWatchCallback(uintptr_t context, + MojoResult result, + const HandleSignalsState& state, + MojoTrapEventFlags flags) { + MojoTrapEvent event; + event.struct_size = sizeof(event); + event.trigger_context = context; + event.result = result; + event.signals_state = static_cast<MojoHandleSignalsState>(state); + event.flags = flags; + { // We avoid holding the lock during dispatch. It's OK for notification // callbacks to close this watcher, and it's OK for notifications to race @@ -81,7 +87,7 @@ void WatcherDispatcher::InvokeWatchCallback( return; } - callback_(context, result, static_cast<MojoHandleSignalsState>(state), flags); + handler_(&event); } Dispatcher::Type WatcherDispatcher::GetType() const { @@ -113,7 +119,7 @@ MojoResult WatcherDispatcher::Close() { MojoResult WatcherDispatcher::WatchDispatcher( scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, uintptr_t context) { // NOTE: Because it's critical to avoid acquiring any other dispatcher locks // while |lock_| is held, we defer adding oursevles to the dispatcher until diff --git a/chromium/mojo/edk/system/watcher_dispatcher.h b/chromium/mojo/edk/system/watcher_dispatcher.h index 4b681f743d3..3048a58833e 100644 --- a/chromium/mojo/edk/system/watcher_dispatcher.h +++ b/chromium/mojo/edk/system/watcher_dispatcher.h @@ -16,7 +16,7 @@ #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/watcher.h" +#include "mojo/public/c/system/trap.h" namespace mojo { namespace edk { @@ -26,9 +26,9 @@ class Watch; // The dispatcher type which backs watcher handles. class WatcherDispatcher : public Dispatcher { public: - // Constructs a new WatcherDispatcher which invokes |callback| when a + // Constructs a new WatcherDispatcher which invokes |handler| when a // registered watch observes some relevant state change. - explicit WatcherDispatcher(MojoWatcherCallback callback); + explicit WatcherDispatcher(MojoTrapEventHandler handler); // Methods used by watched dispatchers to notify watchers of events. void NotifyHandleState(Dispatcher* dispatcher, @@ -40,14 +40,14 @@ class WatcherDispatcher : public Dispatcher { void InvokeWatchCallback(uintptr_t context, MojoResult result, const HandleSignalsState& state, - MojoWatcherNotificationFlags flags); + MojoTrapEventFlags flags); // Dispatcher: Type GetType() const override; MojoResult Close() override; MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, uintptr_t context) override; MojoResult CancelWatch(uintptr_t context) override; MojoResult Arm(uint32_t* num_ready_contexts, @@ -62,7 +62,7 @@ class WatcherDispatcher : public Dispatcher { ~WatcherDispatcher() override; - const MojoWatcherCallback callback_; + const MojoTrapEventHandler handler_; // Guards access to the fields below. // diff --git a/chromium/mojo/edk/test/BUILD.gn b/chromium/mojo/edk/test/BUILD.gn index 1b4f996b4da..427492c11ea 100644 --- a/chromium/mojo/edk/test/BUILD.gn +++ b/chromium/mojo/edk/test/BUILD.gn @@ -27,7 +27,7 @@ static_library("test_support") { deps = [ "//base", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/public/cpp/system", "//testing/gtest", ] @@ -44,7 +44,7 @@ source_set("run_all_unittests") { ":test_support_impl", "//base", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/public/c/test_support", "//testing/gtest", ] @@ -60,7 +60,7 @@ source_set("run_all_perftests") { ":test_support_impl", "//base", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/edk/test:test_support", "//mojo/public/c/test_support", ] diff --git a/chromium/mojo/public/c/system/BUILD.gn b/chromium/mojo/public/c/system/BUILD.gn index 08185c75141..360789a9e22 100644 --- a/chromium/mojo/public/c/system/BUILD.gn +++ b/chromium/mojo/public/c/system/BUILD.gn @@ -6,6 +6,22 @@ component("system") { output_name = "mojo_public_system" sources = [ + "thunks.cc", + ] + + defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] + + public_deps = [ + ":headers", + ] + + deps = [ + "//base", + ] +} + +source_set("headers") { + public = [ "buffer.h", "core.h", "data_pipe.h", @@ -14,24 +30,8 @@ component("system") { "message_pipe.h", "platform_handle.h", "system_export.h", - "thunks.cc", "thunks.h", + "trap.h", "types.h", - "watcher.h", - ] - - defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] -} - -# This should ONLY be depended upon directly by shared_library targets which -# need to export the MojoSetSystemThunks symbol, like targets generated by the -# mojo_native_application template in //services/service_manager/public/cpp/service.gni. -source_set("set_thunks_for_app") { - sources = [ - "set_thunks_for_app.cc", - ] - - public_deps = [ - ":system", ] } diff --git a/chromium/mojo/public/c/system/README.md b/chromium/mojo/public/c/system/README.md index 847eb2dcb83..7107d66f6bf 100644 --- a/chromium/mojo/public/c/system/README.md +++ b/chromium/mojo/public/c/system/README.md @@ -133,30 +133,43 @@ create a new message object as follows: ``` c MojoMessageHandle message; -MojoResult result = MojoCreateMessage(&message); +MojoResult result = MojoCreateMessage(nullptr, &message); ``` Note that we have a special `MojoMessageHandle` type for message objects. -Messages may be serialized or unserialized. Unserialized messages may support -lazy serialization, meaning they can be serialized if and only if necessary -(e.g. if the message needs to cross a process boundary.) +Messages may be serialized with attached data or unserialized with an +opaque context value. Unserialized messages support lazy serialization, allowing +custom serialization logic to be invoked only if and when serialization is +required, e.g. when the message needs to cross a process or language boundary. To make a serialized message, you might write something like: ``` c void* buffer; uint32_t buffer_size; -MojoResult result = MojoAttachSerializedMessageBuffer( - message, 6, nullptr, 0, &buffer, &buffer_size); +MojoResult result = MojoAppendMessageData(message, nullptr, 6, nullptr, 0, + &buffer, &buffer_size); +memcpy(buffer, "hello", 6); ``` -This attaches a serialized message buffer to `message` with at least `6` bytes -of storage capacity. The results stored in `buffer` and `buffer_size` give more -information about the payload's storage. +This attaches a data buffer to `message` with at least `6` bytes of storage +capacity. The outputs returned in `buffer` and `buffer_size` can be used by the +caller to fill in the message contents. + +Multiple calls to `MojoAppendMessageData` may be made on a single message +object, and each call appends to any payload and handles accumulated so far. +Before you can transmit a message carrying data you must commit to never calling +`MojoAppendMessageData` again. You do this by passing the +`MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE` flag: -If you want to increase the size of the payload layer, you can use -`MojoExtendSerializedMessagePayload`. +``` c +MojoAppendMessageDataOptions options; +options.struct_size = sizeof(options); +options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; +MojoResult result = MojoAppendMessageData(message, &options, 0, nullptr, 0, + &buffer, &buffer_size); +``` Creating lazily-serialized messages is also straightforward: @@ -168,26 +181,28 @@ struct MyMessage { void SerializeMessage(MojoMessageHandle message, uintptr_t context) { struct MyMessage* my_message = (struct MyMessage*)context; - MojoResult result = MojoAttachSerializedMessageBuffer(message, ...); + MojoResult result = MojoAppendMessageData(message, ...); // Serialize however you like. +} - free(my_message); +void DestroyMessage(uintptr_t context) { + free((void*)context); } MyMessage* data = malloc(sizeof(MyMessage)); // initialize *data... -MojoResult result = MojoAttachMessageContext(message, (uintptr_t)data, - &SerializeMessage); +MojoResult result = MojoSetMessageContext( + message, (uintptr_t)data, &SerializeMessage, &DestroyMessage, nullptr); ``` -If we change our mind and decide not to send a message, we can destroy it: +If we change our mind and decide not to send the message, we can destroy it: ``` c MojoResult result = MojoDestroyMessage(message); ``` -Note that attempting to write a message transfers ownership of the message +Note that attempting to write a message will transfer ownership of the message object (and any attached handles) into the message pipe, and there is therefore no need to subsequently call `MojoDestroyMessage` on that message. @@ -225,14 +240,13 @@ MojoMessageHandle message; MojoResult result = MojoReadMessage(b, &message, MOJO_READ_MESSAGE_FLAG_NONE); ``` -and extract its serialized contents: +and extract its data: ``` c void* buffer = NULL; uint32_t num_bytes; -MojoResult result = MojoGetSerializedMessageContents( - message, &buffer, &num_bytes, nullptr, nullptr, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); +MojoResult result = MojoGetMessageData(message, nullptr, &buffer, &num_bytes, + nullptr, nullptr); printf("Pipe says: %s", (const char*)buffer); ``` @@ -249,10 +263,11 @@ MojoResult result = MojoReadMessage(b, &message, MOJO_READ_MESSAGE_FLAG_NONE); We'll get a `result` of `MOJO_RESULT_SHOULD_WAIT`, indicating that the pipe is not yet readable. -Note that message also may not have been serialized if they came from within the -same process. In that case, `MojoGetSerializedMessageContents` will return -`MOJO_RESULT_FAILED_PRECONDITION`. The message's unserialized context can -instead be retrieved using `MojoGetMessageContext`. +Note that message also may not have been serialized if it came from within the +same process, in which case it may have no attached data and +`MojoGetMessageData` will return `MOJO_RESULT_FAILED_PRECONDITION`. The +message's unserialized context can instead be retrieved using +`MojoGetMessageContext`. Messages read from a message pipe are owned by the caller and must be subsequently destroyed using `MojoDestroyMessage` (or, in theory, written to @@ -280,44 +295,45 @@ MojoCreateMessagePipe(NULL, &c, &d); MojoMessageHandle message; void* buffer; uint32_t buffer_size; -MojoCreateMessage(&message); -MojoAttachSerializedMessageBuffer(message, "hi", 2, &c, 1, &buffer, - &buffer_size); +MojoCreateMessage(nullptr, &message); + +MojoAppendMessageDataOptions options; +options.struct_size = sizeof(options); +options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; +MojoAppendMessageData(message, &options, 2, &c, 1, &buffer, &buffer_size); +memcpy(buffer, "hi", 2); MojoWriteMessage(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE); // Some time later... MojoHandle e; uint32_t num_handles = 1; MojoReadMessage(b, &message, MOJO_READ_MESSAGE_FLAG_NONE); -MojoGetSerializedMessageContents( - message, &buffer, &buffer_size, &e, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); +MojoGetMessageData(message, nullptr, &buffer, &buffer_size, &e, &num_handles); ``` At this point the handle in `e` is now referencing the same message pipe endpoint which was originally referenced by `c`. Note that `num_handles` above is initialized to 1 before we pass its address to -`MojoGetSerializedMessageContents`. This is to indicate how much `MojoHandle` -storage is available at the output buffer we gave it (`&e` above). +`MojoGetMessageData`. This is to indicate how much `MojoHandle` storage is +available at the output buffer we gave it (`&e` above). If we didn't know how many handles to expect in an incoming message -- which is -often the case -- we can use `MojoGetSerializedMessageContents` to query for -this information first: +often the case -- we can use `MojoGetMessageData` to query for this information +first: ``` c MojoMessageHandle message; void* buffer; uint32_t num_bytes = 0; uint32_t num_handles = 0; -MojoResult result = MojoGetSerializedMessageContents( - message, &buffer, &num_bytes, NULL, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); +MojoResult result = MojoGetMessageData(message, nullptr, &buffer, &num_bytes, + nullptr, &num_handles); ``` If `message` has some non-zero number of handles, `result` will be -`MOJO_RESULT_RESOURCE_EXHAUSTED`, and both `num_bytes` and `num_handles` would -be updated to reflect the payload size and number of attached handles in the +`MOJO_RESULT_RESOURCE_EXHAUSTED`, and both `num_bytes` and `num_handles` will be +updated to reflect the payload size and number of attached handles in the message. ## Data Pipes diff --git a/chromium/mojo/public/c/system/buffer.h b/chromium/mojo/public/c/system/buffer.h index 09f6d285f3e..0e086fc3a28 100644 --- a/chromium/mojo/public/c/system/buffer.h +++ b/chromium/mojo/public/c/system/buffer.h @@ -43,6 +43,35 @@ struct MOJO_ALIGNAS(8) MojoCreateSharedBufferOptions { MOJO_STATIC_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8, "MojoCreateSharedBufferOptions has wrong size"); +// Flags passed to |MojoGetBufferInfo()| via |MojoSharedBufferOptions|. +typedef uint32_t MojoSharedBufferOptionsFlags; + +#ifdef __cplusplus +const MojoSharedBufferOptionsFlags MOJO_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0; +#else +#define MOJO_SHARED_BUFFER_OPTIONS_FLAG_NONE ((MojoSharedBufferOptionsFlags)0) +#endif + +struct MOJO_ALIGNAS(8) MojoSharedBufferOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoSharedBufferOptionsFlags|. + MojoSharedBufferOptionsFlags flags; +}; +MOJO_STATIC_ASSERT(sizeof(MojoSharedBufferOptions) == 8, + "MojoSharedBufferOptions has wrong size"); + +struct MOJO_ALIGNAS(8) MojoSharedBufferInfo { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // The size of the shared buffer. + uint64_t size; +}; +MOJO_STATIC_ASSERT(sizeof(MojoSharedBufferInfo) == 16, + "MojoSharedBufferInfo has wrong size"); + // |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating // access to a shared buffer to |MojoDuplicateBufferHandle()|. // @@ -181,6 +210,21 @@ MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle, // result of |MojoMapBuffer()| or has already been unmapped). MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer); // In. +// Retrieve information about |buffer_handle| into |info|. |options| is optional +// and reserved for future use. +// +// Returns: +// |MOJO_RESULT_OK| on success. +// |MOJO_RESULT_INVALID_ARGUMENT| if |buffer_handle| is invalid or if |info| +// is NULL. +// +// On success, |info->size| will be set to the size of the buffer. On failure it +// is not modified. +MOJO_SYSTEM_EXPORT MojoResult +MojoGetBufferInfo(MojoHandle buffer_handle, + const struct MojoSharedBufferOptions* options, // Optional. + struct MojoSharedBufferInfo* info); // Out. + #ifdef __cplusplus } // extern "C" #endif diff --git a/chromium/mojo/public/c/system/core.h b/chromium/mojo/public/c/system/core.h index 03c0652a574..bc6ef8c6462 100644 --- a/chromium/mojo/public/c/system/core.h +++ b/chromium/mojo/public/c/system/core.h @@ -16,7 +16,7 @@ #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/platform_handle.h" #include "mojo/public/c/system/system_export.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" #endif // MOJO_PUBLIC_C_SYSTEM_CORE_H_ diff --git a/chromium/mojo/public/c/system/functions.h b/chromium/mojo/public/c/system/functions.h index d0656c67fc4..30bfb3aac9c 100644 --- a/chromium/mojo/public/c/system/functions.h +++ b/chromium/mojo/public/c/system/functions.h @@ -26,6 +26,22 @@ extern "C" { // operation's success/failure. E.g., a separate |flags| parameter may control // whether a given "in/out" parameter is used for input, output, or both.) +// Initializes Mojo in the calling application. +// +// With the exception of EDK embedders, applications using Mojo APIs must call +// this function before any others. +// +// |options| may be null. +// +// Returns: +// |MOJO_RESULT_OK| if Mojo intiailization was successful. +// |MOJO_RESULT_INVALID_ARGUMENT| if |options| was null or invalid. +// |MOJO_RESULT_FAILED_PRECONDITION| if |MojoInitialize()| was already called +// once or if the application already explicitly initialized a Mojo EDK +// environment. +MOJO_SYSTEM_EXPORT MojoResult +MojoInitialize(const struct MojoInitializeOptions* options); + // Returns the time, in microseconds, since some undefined point in the past. // The values are only meaningful relative to other values that were obtained // from the same device without an intervening system restart. Such values are @@ -42,7 +58,7 @@ MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void); // // Concurrent operations on |handle| may succeed (or fail as usual) if they // happen before the close, be cancelled with result |MOJO_RESULT_CANCELLED| if -// they properly overlap (this is likely the case with watchers), or fail with +// they properly overlap (this is likely the case with traps), or fail with // |MOJO_RESULT_INVALID_ARGUMENT| if they happen after. MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle); diff --git a/chromium/mojo/public/c/system/message_pipe.h b/chromium/mojo/public/c/system/message_pipe.h index f0f69d1025f..c97e71c33fb 100644 --- a/chromium/mojo/public/c/system/message_pipe.h +++ b/chromium/mojo/public/c/system/message_pipe.h @@ -76,43 +76,126 @@ const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0; #define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags)0) #endif -// |MojoGetMessageContextFlags|: Used to specify different options for -// |MojoGetMessageContext|. -// |MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE| - No flags; default mode. -// |MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE| - Causes the message object to -// release its reference to its own context before returning. +// Flags passed to |MojoCreateMessage()| via |MojoCreateMessageOptions|. +typedef uint32_t MojoCreateMessageFlags; -typedef uint32_t MojoGetMessageContextFlags; +#ifdef __cplusplus +const MojoCreateMessageFlags MOJO_CREATE_MESSAGE__FLAG_NONE = 0; +#else +#define MOJO_CREATE_MESSAGE_FLAG_NONE ((MojoCreateMessageFlags)0) +#endif + +// Options passed to |MojoCreateMessage()|. +struct MOJO_ALIGNAS(8) MojoCreateMessageOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoCreateMessageFlags|. + MojoCreateMessageFlags flags; +}; + +// Flags passed to |MojoSerializeMessage()| via |MojoSerializeMessageOptions|. +typedef uint32_t MojoSerializeMessageFlags; #ifdef __cplusplus -const MojoGetMessageContextFlags MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE = 0; -const MojoGetMessageContextFlags MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE = 1; +const MojoSerializeMessageFlags MOJO_SERIALIZE_MESSAGE_FLAG_NONE = 0; #else -#define MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE ((MojoGetMessageContextFlags)0) -#define MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE ((MojoGetMessageContextFlags)1) +#define MOJO_SERIALIZE_MESSAGE_FLAG_NONE ((MojoSerializeMessageFlags)0) +#endif + +// Options passed to |MojoSerializeMessage()|. +struct MOJO_ALIGNAS(8) MojoSerializeMessageOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoSerializeMessageFlags|. + MojoSerializeMessageFlags flags; +}; + +// Flags passed to |MojoAppendMessageData()| via |MojoAppendMessageDataOptions|. +typedef uint32_t MojoAppendMessageDataFlags; + +#ifdef __cplusplus +const MojoAppendMessageDataFlags MOJO_APPEND_MESSAGE_DATA_FLAG_NONE = 0; +const MojoAppendMessageDataFlags MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE = 1; +#else +#define MOJO_APPEND_MESSAGE_DATA_FLAG_NONE ((MojoAppendMessageDataFlags)0) +#define MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE \ + ((MojoAppendMessageDataFlags)1) +#endif + +// Options passed to |MojoAppendMessageData()|. +struct MOJO_ALIGNAS(8) MojoAppendMessageDataOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoAppendMessageDataFlags|. + MojoAppendMessageDataFlags flags; +}; + +// Flags passed to |MojoGetMessageData()| via |MojoGetMessageDataOptions|. +typedef uint32_t MojoGetMessageDataFlags; + +#ifdef __cplusplus +const MojoGetMessageDataFlags MOJO_GET_MESSAGE_DATA_FLAG_NONE = 0; +const MojoGetMessageDataFlags MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES = 1; +#else +#define MOJO_GET_MESSAGE_DATA_FLAG_NONE ((MojoGetMessageDataFlags)0) +#define MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES ((MojoGetMessageDataFlags)1); +#endif + +// Options passed to |MojoGetMessageData()|. +struct MOJO_ALIGNAS(8) MojoGetMessageDataOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoGetMessageDataFlags|. + MojoGetMessageDataFlags flags; +}; + +// Flags passed to |MojoSetMessageContext()| via |MojoSetMessageContextOptions|. +typedef uint32_t MojoSetMessageContextFlags; + +#ifdef __cplusplus +const MojoSetMessageContextFlags MOJO_SET_MESSAGE_CONTEXT_FLAG_NONE = 0; +#else +#define MOJO_SET_MESSAGE_CONTEXT_FLAG_NONE ((MojoSetMessageContextFlags)0) #endif -// |MojoGetSerializedMessageContentsFlags|: Used to specify different options -// for |MojoGetSerializedMessageContents()|. -// |MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE| - No flags; default mode. +// Options passed to |MojoSetMessageContext()|. +struct MOJO_ALIGNAS(8) MojoSetMessageContextOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; -typedef uint32_t MojoGetSerializedMessageContentsFlags; + // See |MojoSetMessageContextFlags|. + MojoSetMessageContextFlags flags; +}; + +// Flags passed to |MojoGetMessageContext()| via |MojoGetMessageContextOptions|. +typedef uint32_t MojoGetMessageContextFlags; #ifdef __cplusplus -const MojoGetSerializedMessageContentsFlags - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE = 0; +const MojoGetMessageContextFlags MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE = 0; #else -#define MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE \ - ((MojoGetSerializedMessageContentsFlags)0) +#define MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE ((MojoGetMessageContextFlags)0) #endif +// Options passed to |MojoGetMessageContext()|. +struct MOJO_ALIGNAS(8) MojoGetMessageContextOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoGetMessageContextFlags|. + MojoGetMessageContextFlags flags; +}; + #ifdef __cplusplus extern "C" { #endif // A callback which can serialize a message given some context. Passed to -// MojoAttachMessageContext along with a context it knows how to serialize. -// See |MojoAttachMessageContext()| for more details. +// |MojoSetMessageContext()| along with a context it knows how to serialize. +// See |MojoSetMessageContext()| for more details. // // |message| is a message object which had |context| attached. // |context| the context which was attached to |message|. @@ -174,8 +257,9 @@ MOJO_SYSTEM_EXPORT MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, // message handle. The returned message must eventually be destroyed using // |MojoDestroyMessage()|. // -// Message payload and handles can be accessed using -// |MojoGetSerializedMessageContents()|. +// Message payload and handles can be accessed using |MojoGetMessageData()|. For +// Unserialized messages, context may be accessed using +// |MojoGetMessageContext()|. // // |message| must be non-null. // @@ -218,19 +302,21 @@ MOJO_SYSTEM_EXPORT MojoResult // |*message|. // // In its initial state the message object cannot be successfully written to a -// message pipe, but must first have either a context or serialized buffer -// attached (see |MojoAttachContext()| and |MojoAttachSerializedMessageBuffer()| -// below.) +// message pipe, but must first have either an opaque context or some serialized +// data attached (see |MojoSetMessageContext()| and +// |MojoAppendMessageData()|). // -// NOTE: Unlike |MojoHandle|, a |MojoMessageHandle| is NOT thread-safe and thus -// callers of message-related APIs must be careful to restrict usage of any -// given |MojoMessageHandle| to a single thread at a time. +// NOTE: Unlike other types of Mojo API objects, messages are NOT thread-safe +// and thus callers of message-related APIs must be careful to restrict usage of +// any given |MojoMessageHandle| to a single thread at a time. // // Returns: // |MOJO_RESULT_OK| if a new message was created. |*message| contains a handle // to the new message object upon return. // |MOJO_RESULT_INVALID_ARGUMENT| if |message| is null. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessage(MojoMessageHandle* message); +MOJO_SYSTEM_EXPORT MojoResult +MojoCreateMessage(const struct MojoCreateMessageOptions* options, + MojoMessageHandle* message); // Destroys a message object created by |MojoCreateMessage()| or // |MojoReadMessage()|. @@ -250,7 +336,7 @@ MOJO_SYSTEM_EXPORT MojoResult MojoDestroyMessage(MojoMessageHandle message); // |MOJO_RESULT_OK| if |message| was not serialized and is now serialized. // In this case its thunks were invoked to perform serialization and // ultimately destroy its associated context. The message may still be -// written to a pipe or decomposed by MojoGetSerializedMessageContents(). +// written to a pipe or decomposed by |MojoGetMessageData()|. // |MOJO_RESULT_FAILED_PRECONDITION| if |message| was already serialized. // |MOJO_RESULT_NOT_FOUND| if |message| cannot be serialized (i.e. it was // created with null |MojoMessageContextSerializer|.) @@ -265,151 +351,69 @@ MOJO_SYSTEM_EXPORT MojoResult MojoDestroyMessage(MojoMessageHandle message); // Note that unserialized messages may be successfully transferred from one // message pipe endpoint to another without ever being serialized. This function // allows callers to coerce eager serialization. -MOJO_SYSTEM_EXPORT MojoResult MojoSerializeMessage(MojoMessageHandle message); - -// Attaches a serialized message buffer to a message object. -// -// |message|: The message to which a buffer is to be attached. -// |payload_size|: The initial expected payload size of the message. If this -// call succeeds, the attached buffer will be at least this large. -// |handles|: The handles to attach to the serialized message. The set of -// attached handles may be augmented by one or more calls to -// |MojoExtendSerializedMessagePayload|. May be null iff |num_handles| is 0. -// |num_handles|: The number of handles provided by |handles|. -// -// Note that while a serialized message buffer's size may exceed the size of the -// payload, when a serialized message is transmitted (or its contents retrieved -// with |MojoGetSerializedMessageContents()|), only the extent of the payload -// is transmitted and/or exposed. Use |MojoExtendSerializedMessagePayload()| to -// extend the portion of the buffer which is designated as valid payload and -// (if necessary) expand the available capacity. -// -// It is legal to write past |payload_size| (up to |*buffer_size|) within -// |*buffer| upon return, but a future call to -// |MojoExtendSerializedMessagePayload()| or -// |MojoCommitSerializedMessageContents()| must be issued to account for the new -// desired payload boundary and ensure that those bytes are transmitted in the -// message. +MOJO_SYSTEM_EXPORT MojoResult +MojoSerializeMessage(MojoMessageHandle message, + const struct MojoSerializeMessageOptions* options); + +// Appends data to a message object. +// +// |message|: The message. +// |additional_payload_size|: The number of bytes by which to extend the payload +// of the message. +// |handles|: Handles to be appended to the message. May be null iff +// |num_handles| is 0. +// |num_handles|: The number of handles to be appended to the message. +// +// |options| may be null. +// +// If this call succeeds, |*buffer| will contain the address of the data's +// storage if |buffer| was non-null, and if |buffer_size| was non-null then +// |*buffer_size| will contain the storage capacity. The caller may write +// message contents here. +// +// Note that while the size of the returned buffer may exceed the total +// requested size accumulated over one or more calls to +// |MojoAppendMessageData()|, only the extent of caller's requested capacity is +// considered to be part of the message. +// +// A message with attached data must have its capacity finalized before it can +// be transmitted by calling this function with +// |MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE| set in |options->flags|. Note +// that even after this happens, the returned |*buffer| remains valid and +// writable until the message is passed to either |MojoWriteMessage()| or +// |MojoDestroyMessage()|. // // Ownership of all handles in |handles| is transferred to the message object if // and ONLY if this operation succeeds and returns |MOJO_RESULT_OK|. Otherwise // the caller retains ownership. // // Returns: -// |MOJO_RESULT_OK| upon success. A new serialized message buffer has been -// attached to |message|. The address of the buffer's storage is output in -// |*buffer| and its size is in |*buffer_size|. The message is considered -// to be in a partially serialized state and is not transmittable until -// |MojoCommitSerializedMessageContents()| is called. +// |MOJO_RESULT_OK| upon success. The message's data buffer and size are +// stored to |*buffer| and |*buffer_size| respectively. Any previously +// appended data remains intact but may be moved in the event that +// |*buffer| itself is moved. If +// |MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE| was set in +// |options->flags|, the message is ready for transmission. // |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object; -// if |num_handles| is non-zero but |handles| is null; if either -// |buffer| or |buffer_size| is null; or if any handle in |handles| is -// invalid. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if |payload_size| or |num_handles| exceeds -// some implementation- or embedder-defined maximum. +// if |num_handles| is non-zero but |handles| is null; or if any handle in +// |handles| is invalid. +// |MOJO_RESULT_RESOURCE_EXHAUSTED| if |additional_payload_size| or +// |num_handles| exceeds some implementation- or embedder-defined maximum. // |MOJO_RESULT_FAILED_PRECONDITION| if |message| has a context attached. -// |MOJO_RESULT_ALREADY_EXISTS| if |message| already has a serialized buffer -// attached. -// |MOJO_RESULT_BUSY| if one or more handles in |handles| is currently busy -// and unable to be serialized. -MOJO_SYSTEM_EXPORT MojoResult -MojoAttachSerializedMessageBuffer(MojoMessageHandle message, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size); - -// Extends the contents of a partially serialized message with additional -// payload bytes and/or handle attachments. If the underlying message buffer is -// not large enough to accomodate the additional payload size, this will attempt -// to expand the buffer before returning. -// -// May only be called on partially serialized messages, i.e. between a call -// to |MojoAttachSerializedMessageBuffer()| and -// |MojoCommitSerializedMessageContents()|. -// -// |message|: The message getting additional payload. -// |new_payload_size|: The new total of the payload. Must be at least as large -// as the message's current payload size. -// |handles|: Handles to be added to the serialized message. These are amended -// to the message's current set of serialized handles, if any. May be null -// iff |num_handles| is 0. -// |num_handles|: The number of handles in |handles|. -// -// As with |MojoAttachSerializedMessageBuffer|, it is legal to write past -// |payload_size| (up to |*buffer_size|) within |*buffer| upon return, but a -// future call to |MojoExtendSerializedMessagePayload()| or -// |MojoCommitSerializedMessageContents()| must be issued to account for the new -// desired payload boundary and ensure that those bytes are transmitted in the -// message. -// -// Ownership of all handles in |handles| is transferred to the message object if -// and ONLY if this operation succeeds and returns |MOJO_RESULT_OK|. Otherwise -// the caller retains ownership. -// -// Returns: -// |MOJO_RESULT_OK| if the new payload size has been committed to the message. -// If necessary, the message's buffer may have been reallocated to -// accommodate additional capacity. |*buffer| and |*buffer_size| contain -// the (possibly changed) address and size of the serialized message -// buffer's storage. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object, -// or either |buffer| or |buffer_size| is null. -// |MOJO_RESULT_OUT_OF_RANGE| if |payload_size| is not at least as large as -// the message's current payload size. -// |MOJO_RESULT_FAILED_PRECONDITION| if |message| does not have a serialized -// message buffer attached or is already fully serialized (i.e. -// |MojoCommitSerializedMessageContents()| has been called). // |MOJO_RESULT_BUSY| if one or more handles in |handles| is currently busy // and unable to be serialized. MOJO_SYSTEM_EXPORT MojoResult -MojoExtendSerializedMessagePayload(MojoMessageHandle message, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** new_buffer, - uint32_t* new_buffer_size); - -// Prepares a partially serialized message for transmission. MUST be called on -// a partially serialized message before it is legal to either write the message -// to a message pipe or call |MojoGetSerializedMessageContents()|. -// -// |message|: The message whose contents are to be committed. -// |final_payload_size|: The total number of bytes of meaningful payload to -// treat as the full message body. -// -// Note that upon return, because no further calls to -// |MojoExtendSerializedMessagePayload()| are allowed on |message|, the payload -// may not be extended further and no more handles may be attached. -// -// The message's payload buffer (returned and potentially relocated by this -// call) however is still valid and mutable until the message is either -// destroyed or written to a pipe. -// -// Returns: -// |MOJO_RESULT_OK| if the message contents are committed. The message is -// fully serialized and it is now legal to write it to a pipe or extract -// its contents via |MojoGetSerializedMessageContents()|. |*buffer| and -// |*buffer_size| on output will contain the address and size of the -// payload buffer, which may be relocated one final time by this call. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object. -// |MOJO_RESULT_OUT_OF_RANGE| if |final_payload_size| is larger than the -// message's available buffer size as indicated by the most recent call -// to |MojoAttachSerializedMessageBuffer()| or -// |MojoExtendSerializedMessagePayload()|, or smaller than the most -// recently requested payload size given to either call. -// |MOJO_RESULT_FAILED_PRECONDITION| if |message| is not a (partially or -// fully) serialized message object. -MOJO_SYSTEM_EXPORT MojoResult -MojoCommitSerializedMessageContents(MojoMessageHandle message, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size); +MojoAppendMessageData(MojoMessageHandle message, + uint32_t payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const struct MojoAppendMessageDataOptions* options, + void** buffer, + uint32_t* buffer_size); -// Retrieves the contents of a serialized message. +// Retrieves data attached to a message object. // -// |message|: The message whose contents are to be retrieved. +// |message|: The message. // |num_bytes|: An output parameter which will receive the total size in bytes // of the message's payload. // |buffer|: An output parameter which will receive the address of a buffer @@ -422,44 +426,49 @@ MojoCommitSerializedMessageContents(MojoMessageHandle message, // the actual number of handles available in the serialized message. // |handles|: A buffer to contain up to (input) |*num_handles| handles. May be // null if |num_handles| is null or |*num_handles| is 0. -// |flags|: Flags to affect the behavior of this API. +// +// |options| may be null. // // Returns: -// |MOJO_RESULT_OK| if |message| is a serialized message and the provided -// handle storage is sufficient to contain all handles attached to the -// message. In this case all non-null output parameters are filled in and -// ownership of any attached handles is transferred to the caller. It is -// no longer legal to call MojoGetSerializedMessageContents on this -// message handle. +// |MOJO_RESULT_OK| if |message| is a message with data attached and the +// provided handle storage is sufficient to contain all handles attached +// to the message. If |MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES| was set +// in |options->flags|, any attached handles in the message are left +// intact and both |handles| and |num_handles| are ignored. Otherwise +// ownership of any attached handles is transferred to the caller, and +// |MojoGetMessageData()| may no longer be called on |message| unless +// |MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES| is used. // |MOJO_RESULT_INVALID_ARGUMENT| if |num_handles| is non-null and // |*num_handles| is non-zero, but |handles| is null; or if |message| is // not a valid message handle. // |MOJO_RESULT_FAILED_PRECONDITION| if |message| is not a fully serialized -// message. The caller may either use |MojoSerializeMessage()| and try -// again, |MojoCommitSerializedMessageContents()| to complete a partially -// serialized |message|, or |MojoGetMessageContext()| to extract -// |message|'s unserialized context, depending on the message's state. -// |MOJO_RESULT_NOT_FOUND| if the message's serialized contents have already -// been extracted (or have failed to be extracted) by a previous call to -// |MojoGetSerializedMessageContents()|. +// message. The caller may use |MojoSerializeMessage()| and try again, +// or |MojoAppendMessageData()| with the +// |MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE| flag set to complete a +// partially serialized |message|. +// |MOJO_RESULT_NOT_FOUND| if the message's handles (if any) contents have +// already been extracted (or have failed to be extracted) by a previous +// call to |MojoGetMessageData()|. // |MOJO_RESULT_RESOURCE_EXHAUSTED| if |num_handles| is null and there are // handles attached to the message, or if |*num_handles| on input is less // than the number of handles attached to the message. Also may be // returned if |num_bytes| or |buffer| is null and the message has a non- -// empty payload. -// |MOJO_RESULT_ARBORTED| if the serialized message could not be parsed or -// its attached handles could not be decoded properly. The message is left -// intact but is effectively useless: future calls to this API on the same -// message handle will yield the same result. +// empty payload. Note that if |MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES| +// is set in |options->flags| any current or previously attached handles +// are ignored. +// |MOJO_RESULT_ARBORTED| if the message is in an invalid state and its data +// and/or handles are unrecoverable. The message is left in this state but +// future calls to this API will yield the same result. MOJO_SYSTEM_EXPORT MojoResult -MojoGetSerializedMessageContents(MojoMessageHandle message, - void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags); +MojoGetMessageData(MojoMessageHandle message, + const struct MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles); -// Attachs an unserialized message context to a message. +// Sets an opaque context value on a message object. The presence of an opaque +// context is mutually exclusive to the presence of message data. // // |context| is the context value to associate with this message, and // |serializer| is a function which may be called at some later time to convert @@ -470,10 +479,9 @@ MojoGetSerializedMessageContents(MojoMessageHandle message, // without ever being serialized. // // Typically a caller will use |context| as an opaque pointer to some heap -// object which is effectively owned by the newly created message once this -// returns. In this way, messages can be sent over a message pipe to a peer -// endpoint in the same process as the sender without ever performing a -// serialization step. +// object which is effectively owned by the message once this returns. In this +// way, messages can be sent over a message pipe to a peer endpoint in the same +// process as the sender without performing a serialization step. // // If the message does need to cross a process boundary or is otherwise // forced to serialize (see |MojoSerializeMessage()| below), it will be @@ -486,38 +494,42 @@ MojoGetSerializedMessageContents(MojoMessageHandle message, // If |destructor| is null, it is assumed that no cleanup is required after // serializing or destroying a message with |context| attached. // +// A |context| value of zero is invalid, and setting this on a message +// effectively removes its context. This is necessary if the caller wishes to +// attach data to the message or if the caller wants to destroy the message +// object without triggering |destructor|. +// +// |options| may be null. +// // Returns: -// |MOJO_RESULT_OK| if the context was successfully attached. -// |MOJO_RESULT_INVALID_ARGUMENT| if |context| is 0 or |message| is not a -// valid message object. -// |MOJO_RESULT_ALREADY_EXISTS| if |message| already has a context attached. -// |MOJO_RESULT_FAILED_PRECONDITION| if |message| already has a serialized -// buffer attached. +// |MOJO_RESULT_OK| if the opaque context value was successfully set. +// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object; +// |options| is non-null and |*options| contains one or more malformed +// fields; or |context| is zero but either |serializer| or |destructor| is +// non-null. +// |MOJO_RESULT_ALREADY_EXISTS| if |message| already has a non-zero context. +// |MOJO_RESULT_FAILED_PRECONDITION| if |message| has data attached. MOJO_SYSTEM_EXPORT MojoResult -MojoAttachMessageContext(MojoMessageHandle message, - uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor); +MojoSetMessageContext(MojoMessageHandle message, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const struct MojoSetMessageContextOptions* options); -// Extracts the user-provided context from a message and returns it to the -// caller. +// Retrieves a message object's opaque context value. // -// |flags|: Flags to alter the behavior of this call. See -// |MojoGetMessageContextFlags| for details. +// |options| may be null. // // Returns: -// |MOJO_RESULT_OK| if |message| is a valid message object which has a -// |context| attached. Upon return, |*context| contains the value of the -// attached context. If |flags| contains -// |MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE|, the |context| is detached from -// |message|. -// |MOJO_RESULT_NOT_FOUND| if |message| is a valid message object which has no -// attached context. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object. +// |MOJO_RESULT_OK| if |message| is a valid message object. |*context| +// contains its opaque context value, which may be zero. +// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object +// or |options| is non-null and |*options| contains one or more malformed +// fields. MOJO_SYSTEM_EXPORT MojoResult MojoGetMessageContext(MojoMessageHandle message, - uintptr_t* context, - MojoGetMessageContextFlags flags); + const struct MojoGetMessageContextOptions* options, + uintptr_t* context); // Notifies the system that a bad message was received on a message pipe, // according to whatever criteria the caller chooses. This ultimately tries to diff --git a/chromium/mojo/public/c/system/set_thunks_for_app.cc b/chromium/mojo/public/c/system/set_thunks_for_app.cc deleted file mode 100644 index 335cc02b794..00000000000 --- a/chromium/mojo/public/c/system/set_thunks_for_app.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/c/system/thunks.h" - -extern "C" { - -#if defined(WIN32) -#define THUNKS_EXPORT __declspec(dllexport) -#else -#define THUNKS_EXPORT __attribute__((visibility("default"))) -#endif - -THUNKS_EXPORT size_t MojoSetSystemThunks( - const MojoSystemThunks* system_thunks) { - return MojoEmbedderSetSystemThunks(system_thunks); -} - -} // extern "C" diff --git a/chromium/mojo/public/c/system/thunks.cc b/chromium/mojo/public/c/system/thunks.cc index f735c33fbc8..12dc79a7a50 100644 --- a/chromium/mojo/public/c/system/thunks.cc +++ b/chromium/mojo/public/c/system/thunks.cc @@ -4,35 +4,118 @@ #include "mojo/public/c/system/thunks.h" -#include <assert.h> -#include <stddef.h> -#include <stdint.h> +#include <cstddef> +#include <cstdint> +#include <cstring> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/no_destructor.h" +#include "build/build_config.h" +#include "mojo/public/c/system/core.h" + +#if defined(OS_CHROMEOS) || defined(OS_LINUX) +#include "base/environment.h" +#include "base/files/file_path.h" +#include "base/optional.h" +#include "base/scoped_native_library.h" +#include "base/threading/thread_restrictions.h" +#endif + +namespace { + +MojoSystemThunks g_thunks = {0}; + +} // namespace + +namespace mojo { + +// NOTE: This is defined within the global mojo namespace so that it can be +// referenced as a friend to base::ScopedAllowBlocking when library support is +// enabled. +class CoreLibraryInitializer { + public: + typedef void (*MojoGetSystemThunksFunction)(MojoSystemThunks* thunks); + + CoreLibraryInitializer() { +#if defined(OS_CHROMEOS) || defined(OS_LINUX) + auto environment = base::Environment::Create(); + + base::FilePath library_path; + std::string library_path_value; + const char kLibraryPathEnvironmentVar[] = "MOJO_CORE_LIBRARY_PATH"; + if (environment->GetVar(kLibraryPathEnvironmentVar, &library_path_value)) { + library_path = base::FilePath::FromUTF8Unsafe(library_path_value); + } else { + // Default to looking for the library in the current working directory. + const base::FilePath::CharType kDefaultLibraryPathValue[] = + FILE_PATH_LITERAL("./libmojo_core.so"); + library_path = base::FilePath(kDefaultLibraryPathValue); + } + + base::ScopedAllowBlocking allow_blocking; + library_.emplace(library_path); + CHECK(library_->is_valid()) + << "Unable to load the mojo_core library. Make sure the library is in " + << "the working directory or is correctly pointed to by the " + << "MOJO_CORE_LIBRARY_PATH environment variable."; + + const char kGetThunksFunctionName[] = "MojoGetSystemThunks"; + MojoGetSystemThunksFunction get_thunks = + reinterpret_cast<MojoGetSystemThunksFunction>( + library_->GetFunctionPointer(kGetThunksFunctionName)); + CHECK(get_thunks) << "Invalid mojo_core library"; + + DCHECK_EQ(g_thunks.size, 0u); + g_thunks.size = sizeof(g_thunks); + get_thunks(&g_thunks); + + CHECK_GT(g_thunks.size, 0u) << "Invalid mojo_core library"; +#else // defined(OS_CHROMEOS) || defined(OS_LINUX) + NOTREACHED() + << "Dynamic mojo_core loading is not supported on this platform."; +#endif // defined(OS_CHROMEOS) || defined(OS_LINUX) + } + + ~CoreLibraryInitializer() = default; + + private: +#if defined(OS_CHROMEOS) || defined(OS_LINUX) + base::Optional<base::ScopedNativeLibrary> library_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CoreLibraryInitializer); +}; + +} // namespace mojo extern "C" { -static MojoSystemThunks g_thunks = {0}; +MojoResult MojoInitialize(const struct MojoInitializeOptions* options) { + static base::NoDestructor<mojo::CoreLibraryInitializer> initializer; + ALLOW_UNUSED_LOCAL(initializer); + DCHECK(g_thunks.Initialize); + + return g_thunks.Initialize(options); +} MojoTimeTicks MojoGetTimeTicksNow() { - assert(g_thunks.GetTimeTicksNow); return g_thunks.GetTimeTicksNow(); } MojoResult MojoClose(MojoHandle handle) { - assert(g_thunks.Close); return g_thunks.Close(handle); } MojoResult MojoQueryHandleSignalsState( MojoHandle handle, struct MojoHandleSignalsState* signals_state) { - assert(g_thunks.QueryHandleSignalsState); return g_thunks.QueryHandleSignalsState(handle, signals_state); } MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, MojoHandle* message_pipe_handle0, MojoHandle* message_pipe_handle1) { - assert(g_thunks.CreateMessagePipe); return g_thunks.CreateMessagePipe(options, message_pipe_handle0, message_pipe_handle1); } @@ -40,7 +123,6 @@ MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, MojoMessageHandle message_handle, MojoWriteMessageFlags flags) { - assert(g_thunks.WriteMessage); return g_thunks.WriteMessage(message_pipe_handle, message_handle, flags); } @@ -54,7 +136,6 @@ MojoResult MojoReadMessage(MojoHandle message_pipe_handle, MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options, MojoHandle* data_pipe_producer_handle, MojoHandle* data_pipe_consumer_handle) { - assert(g_thunks.CreateDataPipe); return g_thunks.CreateDataPipe(options, data_pipe_producer_handle, data_pipe_consumer_handle); } @@ -63,7 +144,6 @@ MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle, const void* elements, uint32_t* num_elements, MojoWriteDataFlags flags) { - assert(g_thunks.WriteData); return g_thunks.WriteData(data_pipe_producer_handle, elements, num_elements, flags); } @@ -72,14 +152,12 @@ MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle, void** buffer, uint32_t* buffer_num_elements, MojoWriteDataFlags flags) { - assert(g_thunks.BeginWriteData); return g_thunks.BeginWriteData(data_pipe_producer_handle, buffer, buffer_num_elements, flags); } MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle, uint32_t num_elements_written) { - assert(g_thunks.EndWriteData); return g_thunks.EndWriteData(data_pipe_producer_handle, num_elements_written); } @@ -87,7 +165,6 @@ MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle, void* elements, uint32_t* num_elements, MojoReadDataFlags flags) { - assert(g_thunks.ReadData); return g_thunks.ReadData(data_pipe_consumer_handle, elements, num_elements, flags); } @@ -96,14 +173,12 @@ MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle, const void** buffer, uint32_t* buffer_num_elements, MojoReadDataFlags flags) { - assert(g_thunks.BeginReadData); return g_thunks.BeginReadData(data_pipe_consumer_handle, buffer, buffer_num_elements, flags); } MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle, uint32_t num_elements_read) { - assert(g_thunks.EndReadData); return g_thunks.EndReadData(data_pipe_consumer_handle, num_elements_read); } @@ -111,7 +186,6 @@ MojoResult MojoCreateSharedBuffer( const struct MojoCreateSharedBufferOptions* options, uint64_t num_bytes, MojoHandle* shared_buffer_handle) { - assert(g_thunks.CreateSharedBuffer); return g_thunks.CreateSharedBuffer(options, num_bytes, shared_buffer_handle); } @@ -119,7 +193,6 @@ MojoResult MojoDuplicateBufferHandle( MojoHandle buffer_handle, const struct MojoDuplicateBufferHandleOptions* options, MojoHandle* new_buffer_handle) { - assert(g_thunks.DuplicateBufferHandle); return g_thunks.DuplicateBufferHandle(buffer_handle, options, new_buffer_handle); } @@ -129,135 +202,115 @@ MojoResult MojoMapBuffer(MojoHandle buffer_handle, uint64_t num_bytes, void** buffer, MojoMapBufferFlags flags) { - assert(g_thunks.MapBuffer); return g_thunks.MapBuffer(buffer_handle, offset, num_bytes, buffer, flags); } MojoResult MojoUnmapBuffer(void* buffer) { - assert(g_thunks.UnmapBuffer); return g_thunks.UnmapBuffer(buffer); } -MojoResult MojoCreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { - assert(g_thunks.CreateWatcher); - return g_thunks.CreateWatcher(callback, watcher_handle); +MojoResult MojoGetBufferInfo(MojoHandle buffer_handle, + const struct MojoSharedBufferOptions* options, + struct MojoSharedBufferInfo* info) { + assert(g_thunks.GetBufferInfo); + return g_thunks.GetBufferInfo(buffer_handle, options, info); +} + +MojoResult MojoCreateTrap(MojoTrapEventHandler handler, + const MojoCreateTrapOptions* options, + MojoHandle* trap_handle) { + return g_thunks.CreateTrap(handler, options, trap_handle); } -MojoResult MojoWatch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context) { - assert(g_thunks.Watch); - return g_thunks.Watch(watcher_handle, handle, signals, condition, context); +MojoResult MojoAddTrigger(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const MojoAddTriggerOptions* options) { + return g_thunks.AddTrigger(trap_handle, handle, signals, condition, context, + options); } -MojoResult MojoCancelWatch(MojoHandle watcher_handle, uintptr_t context) { - assert(g_thunks.CancelWatch); - return g_thunks.CancelWatch(watcher_handle, context); +MojoResult MojoRemoveTrigger(MojoHandle trap_handle, + uintptr_t context, + const MojoRemoveTriggerOptions* options) { + return g_thunks.RemoveTrigger(trap_handle, context, options); } -MojoResult MojoArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - assert(g_thunks.ArmWatcher); - return g_thunks.ArmWatcher(watcher_handle, num_ready_contexts, ready_contexts, - ready_results, ready_signals_states); +MojoResult MojoArmTrap(MojoHandle trap_handle, + const MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals_states) { + return g_thunks.ArmTrap(trap_handle, options, num_ready_triggers, + ready_triggers, ready_results, ready_signals_states); } MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { - assert(g_thunks.FuseMessagePipes); return g_thunks.FuseMessagePipes(handle0, handle1); } -MojoResult MojoCreateMessage(MojoMessageHandle* message) { - assert(g_thunks.CreateMessage); - return g_thunks.CreateMessage(message); +MojoResult MojoCreateMessage(const MojoCreateMessageOptions* options, + MojoMessageHandle* message) { + return g_thunks.CreateMessage(options, message); } MojoResult MojoDestroyMessage(MojoMessageHandle message) { - assert(g_thunks.DestroyMessage); return g_thunks.DestroyMessage(message); } -MojoResult MojoSerializeMessage(MojoMessageHandle message) { - assert(g_thunks.SerializeMessage); - return g_thunks.SerializeMessage(message); -} - -MojoResult MojoAttachSerializedMessageBuffer(MojoMessageHandle message, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size) { - assert(g_thunks.AttachSerializedMessageBuffer); - return g_thunks.AttachSerializedMessageBuffer( - message, payload_size, handles, num_handles, buffer, buffer_size); +MojoResult MojoSerializeMessage(MojoMessageHandle message, + const MojoSerializeMessageOptions* options) { + return g_thunks.SerializeMessage(message, options); } -MojoResult MojoExtendSerializedMessagePayload(MojoMessageHandle message, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size) { - assert(g_thunks.ExtendSerializedMessagePayload); - return g_thunks.ExtendSerializedMessagePayload( - message, new_payload_size, handles, num_handles, buffer, buffer_size); +MojoResult MojoAppendMessageData(MojoMessageHandle message, + uint32_t payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const MojoAppendMessageDataOptions* options, + void** buffer, + uint32_t* buffer_size) { + return g_thunks.AppendMessageData(message, payload_size, handles, num_handles, + options, buffer, buffer_size); } -MojoResult MojoCommitSerializedMessageContents(MojoMessageHandle message, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size) { - assert(g_thunks.CommitSerializedMessageContents); - return g_thunks.CommitSerializedMessageContents(message, final_payload_size, - buffer, buffer_size); -} - -MojoResult MojoGetSerializedMessageContents( - MojoMessageHandle message, - void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags) { - assert(g_thunks.GetSerializedMessageContents); - return g_thunks.GetSerializedMessageContents(message, buffer, num_bytes, - handles, num_handles, flags); +MojoResult MojoGetMessageData(MojoMessageHandle message, + const MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles) { + return g_thunks.GetMessageData(message, options, buffer, num_bytes, handles, + num_handles); } -MojoResult MojoAttachMessageContext(MojoMessageHandle message, - uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor) { - assert(g_thunks.AttachMessageContext); - return g_thunks.AttachMessageContext(message, context, serializer, - destructor); +MojoResult MojoSetMessageContext(MojoMessageHandle message, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const MojoSetMessageContextOptions* options) { + return g_thunks.SetMessageContext(message, context, serializer, destructor, + options); } MojoResult MojoGetMessageContext(MojoMessageHandle message, - uintptr_t* context, - MojoGetMessageContextFlags flags) { - assert(g_thunks.GetMessageContext); - return g_thunks.GetMessageContext(message, context, flags); + const MojoGetMessageContextOptions* options, + uintptr_t* context) { + return g_thunks.GetMessageContext(message, options, context); } MojoResult MojoWrapPlatformHandle( const struct MojoPlatformHandle* platform_handle, MojoHandle* mojo_handle) { - assert(g_thunks.WrapPlatformHandle); return g_thunks.WrapPlatformHandle(platform_handle, mojo_handle); } MojoResult MojoUnwrapPlatformHandle( MojoHandle mojo_handle, struct MojoPlatformHandle* platform_handle) { - assert(g_thunks.UnwrapPlatformHandle); return g_thunks.UnwrapPlatformHandle(mojo_handle, platform_handle); } @@ -267,7 +320,6 @@ MojoResult MojoWrapPlatformSharedBufferHandle( const struct MojoSharedBufferGuid* guid, MojoPlatformSharedBufferHandleFlags flags, MojoHandle* mojo_handle) { - assert(g_thunks.WrapPlatformSharedBufferHandle); return g_thunks.WrapPlatformSharedBufferHandle(platform_handle, num_bytes, guid, flags, mojo_handle); } @@ -278,7 +330,6 @@ MojoResult MojoUnwrapPlatformSharedBufferHandle( size_t* num_bytes, struct MojoSharedBufferGuid* guid, MojoPlatformSharedBufferHandleFlags* flags) { - assert(g_thunks.UnwrapPlatformSharedBufferHandle); return g_thunks.UnwrapPlatformSharedBufferHandle(mojo_handle, platform_handle, num_bytes, guid, flags); } @@ -286,19 +337,25 @@ MojoResult MojoUnwrapPlatformSharedBufferHandle( MojoResult MojoNotifyBadMessage(MojoMessageHandle message, const char* error, size_t error_num_bytes) { - assert(g_thunks.NotifyBadMessage); return g_thunks.NotifyBadMessage(message, error, error_num_bytes); } MojoResult MojoGetProperty(MojoPropertyType type, void* value) { - assert(g_thunks.GetProperty); return g_thunks.GetProperty(type, value); } } // extern "C" -size_t MojoEmbedderSetSystemThunks(const MojoSystemThunks* system_thunks) { - if (system_thunks->size >= sizeof(g_thunks)) - g_thunks = *system_thunks; - return sizeof(g_thunks); +void MojoEmbedderSetSystemThunks(const MojoSystemThunks* thunks) { + // Assume embedders will always use matching versions of the EDK and public + // APIs. + DCHECK_EQ(thunks->size, sizeof(g_thunks)); + + // This should only have to check that the |g_thunks.size| is zero, but we + // have multiple EDK initializations in some test suites still. For now we + // allow double calls as long as they're the same thunks as before. + DCHECK(g_thunks.size == 0 || !memcmp(&g_thunks, thunks, sizeof(g_thunks))) + << "Cannot set embedder thunks after Mojo API calls have been made."; + + g_thunks = *thunks; } diff --git a/chromium/mojo/public/c/system/thunks.h b/chromium/mojo/public/c/system/thunks.h index 6c0720fc8d8..968e1c168fc 100644 --- a/chromium/mojo/public/c/system/thunks.h +++ b/chromium/mojo/public/c/system/thunks.h @@ -20,6 +20,7 @@ #pragma pack(push, 8) struct MojoSystemThunks { size_t size; // Should be set to sizeof(MojoSystemThunks). + MojoResult (*Initialize)(const struct MojoInitializeOptions* options); MojoTimeTicks (*GetTimeTicksNow)(); MojoResult (*Close)(MojoHandle handle); MojoResult (*QueryHandleSignalsState)( @@ -72,53 +73,58 @@ struct MojoSystemThunks { void** buffer, MojoMapBufferFlags flags); MojoResult (*UnmapBuffer)(void* buffer); - MojoResult (*CreateWatcher)(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - MojoResult (*Watch)(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context); - MojoResult (*CancelWatch)(MojoHandle watcher_handle, uintptr_t context); - MojoResult (*ArmWatcher)(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states); + MojoResult (*GetBufferInfo)(MojoHandle buffer_handle, + const struct MojoSharedBufferOptions* options, + struct MojoSharedBufferInfo* info); + MojoResult (*CreateTrap)(MojoTrapEventHandler handler, + const struct MojoCreateTrapOptions* options, + MojoHandle* trap_handle); + MojoResult (*AddTrigger)(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const struct MojoAddTriggerOptions* options); + MojoResult (*RemoveTrigger)(MojoHandle trap_handle, + uintptr_t context, + const struct MojoRemoveTriggerOptions* options); + MojoResult (*ArmTrap)(MojoHandle trap_handle, + const struct MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + MojoHandleSignalsState* ready_signals_states); MojoResult (*FuseMessagePipes)(MojoHandle handle0, MojoHandle handle1); - MojoResult (*CreateMessage)(MojoMessageHandle* message); + MojoResult (*CreateMessage)(const struct MojoCreateMessageOptions* options, + MojoMessageHandle* message); MojoResult (*DestroyMessage)(MojoMessageHandle message); - MojoResult (*SerializeMessage)(MojoMessageHandle message); - MojoResult (*AttachSerializedMessageBuffer)(MojoMessageHandle message, - uint32_t payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size); - MojoResult (*ExtendSerializedMessagePayload)(MojoMessageHandle message, - uint32_t new_payload_size, - const MojoHandle* handles, - uint32_t num_handles, - void** buffer, - uint32_t* buffer_size); - MojoResult (*CommitSerializedMessageContents)(MojoMessageHandle message, - uint32_t final_payload_size, - void** buffer, - uint32_t* buffer_size); - MojoResult (*GetSerializedMessageContents)( + MojoResult (*SerializeMessage)( MojoMessageHandle message, + const struct MojoSerializeMessageOptions* options); + MojoResult (*AppendMessageData)( + MojoMessageHandle message, + uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const struct MojoAppendMessageDataOptions* options, void** buffer, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoGetSerializedMessageContentsFlags flags); - MojoResult (*AttachMessageContext)(MojoMessageHandle message, - uintptr_t context, - MojoMessageContextSerializer serializer, - MojoMessageContextDestructor destructor); - MojoResult (*GetMessageContext)(MojoMessageHandle message, - uintptr_t* context, - MojoGetMessageContextFlags flags); + uint32_t* buffer_size); + MojoResult (*GetMessageData)(MojoMessageHandle message, + const struct MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles); + MojoResult (*SetMessageContext)( + MojoMessageHandle message, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const struct MojoSetMessageContextOptions* options); + MojoResult (*GetMessageContext)( + MojoMessageHandle message, + const struct MojoGetMessageContextOptions* options, + uintptr_t* context); MojoResult (*WrapPlatformHandle)( const struct MojoPlatformHandle* platform_handle, MojoHandle* mojo_handle); @@ -144,19 +150,9 @@ struct MojoSystemThunks { }; #pragma pack(pop) -// Use this type for the function found by dynamically discovering it in -// a DSO linked with mojo_system. For example: -// MojoSetSystemThunksFn mojo_set_system_thunks_fn = -// reinterpret_cast<MojoSetSystemThunksFn>(app_library.GetFunctionPointer( -// "MojoSetSystemThunks")); -// The expected size of |system_thunks| is returned. -// The contents of |system_thunks| are copied. -typedef size_t (*MojoSetSystemThunksFn)( - const struct MojoSystemThunks* system_thunks); - // A function for setting up the embedder's own system thunks. This should only // be called by Mojo embedder code. -MOJO_SYSTEM_EXPORT size_t -MojoEmbedderSetSystemThunks(const struct MojoSystemThunks* system_thunks); +MOJO_SYSTEM_EXPORT void MojoEmbedderSetSystemThunks( + const struct MojoSystemThunks* system_thunks); #endif // MOJO_PUBLIC_C_SYSTEM_THUNKS_H_ diff --git a/chromium/mojo/public/c/system/trap.h b/chromium/mojo/public/c/system/trap.h new file mode 100644 index 00000000000..7c65af31fa2 --- /dev/null +++ b/chromium/mojo/public/c/system/trap.h @@ -0,0 +1,320 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_C_SYSTEM_TRAP_H_ +#define MOJO_PUBLIC_C_SYSTEM_TRAP_H_ + +#include <stdint.h> + +#include "mojo/public/c/system/macros.h" +#include "mojo/public/c/system/system_export.h" +#include "mojo/public/c/system/types.h" + +// Flags passed to trap event handlers within |MojoTrapEvent|. +typedef uint32_t MojoTrapEventFlags; + +#ifdef __cplusplus +const MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_NONE = 0; +const MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL = 1 << 0; +#else +#define MOJO_TRAP_EVENT_FLAG_NONE ((MojoTrapEventFlags)0) +#define MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL ((MojoTrapEventFlags)1 << 0) +#endif + +// Structure passed to trap event handlers when invoked by a tripped trap. +struct MOJO_ALIGNAS(8) MojoTrapEvent { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // May take on some combination of the following values: + // + // |MOJO_TRAP_EVENT_FLAG_NONE|: No flags. + // + // |MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL|: The trap was tripped within the + // extent of a user call to some Mojo API. This means that the event + // handler itself is re-entering user code. May happen, for example, if + // user code writes to an intra-process pipe and the receiving end trips + // a trap as a result. In that case the event handler executes within + // the extent of the |MojoWriteMessage()| call. + MojoTrapEventFlags flags; + + // The context for the trigger which tripped the trap. + uintptr_t trigger_context; + + // A result code indicating the cause of the event. May take on any of the + // following values: + // + // |MOJO_RESULT_OK|: The trigger's conditions were met. + // |MOJO_RESULT_FAILED_PRECONDITION|: The trigger's observed handle has + // changed state in such a way that the trigger's conditions can never + // be met again. + // |MOJO_RESULT_CANCELLED|: The trigger has been removed and will never + // cause another event to fire. This is always the last event fired by + // a trigger and it will fire when: the trigger is explicitly removed + // with |MojoRemoteTrigger()|, the trigger's owning trap handle is + // closed, or the handle observed by the trigger is closed. + // + // Unlike the other result types above |MOJO_RESULT_CANCELLED| can + // fire even when the trap is disarmed. + MojoResult result; + + // The last known signalling state of the trigger's observed handle at the + // time the trap was tripped. + struct MojoHandleSignalsState signals_state; +}; + +// Value given to |MojoAddTrigger| to configure what condition should cause it +// to trip its trap. May be one of the following values: +// +// |MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED| - A trigger added with this +// condition will trip its trap when any of its observed signals +// transition from being satisfied to being unsatisfied. +// |MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED| - A triger added with this +// condition will trip its trap when any of its observed signals +// transition from being unsatisfied to being satisfied, or when none of +// the observed signals can ever be satisfied again. +typedef uint32_t MojoTriggerCondition; + +#ifdef __cplusplus +const MojoTriggerCondition MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED = 0; +const MojoTriggerCondition MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED = 1; +#else +#define MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED ((MojoTriggerCondition)0) +#define MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED ((MojoTriggerCondition)1) +#endif + +// Flags passed to |MojoCreateTrap()| via |MojoCreateTrapOptions|. +typedef uint32_t MojoCreateTrapFlags; + +#ifdef __cplusplus +const MojoCreateTrapFlags MOJO_CREATE_TRAP_FLAG_NONE = 0; +#else +#define MOJO_CREATE_TRAP_FLAG_NONE ((MojoCreateTrapFlags)0) +#endif + +// Options passed to |MojoCreateTrap()|. +struct MOJO_ALIGNAS(8) MojoCreateTrapOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // Flags. Currently unused. + MojoCreateTrapFlags flags; +}; + +// Flags passed to |MojoAddTrigger()| via |MojoAddTriggerOptions|. +typedef uint32_t MojoAddTriggerFlags; + +#ifdef __cplusplus +const MojoAddTriggerFlags MOJO_ADD_TRIGGER_FLAG_NONE = 0; +#else +#define MOJO_ADD_TRIGGER_FLAG_NONE ((MojoAddTriggerFlags)0) +#endif + +// Options passed to |MojoAddTrigger()|. +struct MOJO_ALIGNAS(8) MojoAddTriggerOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // Flags. Currently unused. + MojoAddTriggerFlags flags; +}; + +// Flags passed to |MojoRemoveTrigger()| via |MojoRemoveTriggerOptions|. +typedef uint32_t MojoRemoveTriggerFlags; + +#ifdef __cplusplus +const MojoRemoveTriggerFlags MOJO_REMOVE_TRIGGER_FLAG_NONE = 0; +#else +#define MOJO_REMOVE_TRIGGER_FLAG_NONE ((MojoRemoveTriggerFlags)0) +#endif + +// Options passed to |MojoRemoveTrigger()|. +struct MOJO_ALIGNAS(8) MojoRemoveTriggerOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // Flags. Currently unused. + MojoRemoveTriggerFlags flags; +}; + +// Flags passed to |MojoArmTrap()| via |MojoArmTrapOptions|. +typedef uint32_t MojoArmTrapFlags; + +#ifdef __cplusplus +const MojoArmTrapFlags MOJO_ARM_TRAP_FLAG_NONE = 0; +#else +#define MOJO_ARM_TRAP_FLAG_NONE ((MojoArmTrapFlags)0) +#endif + +// Options passed to |MojoArmTrap()|. +struct MOJO_ALIGNAS(8) MojoArmTrapOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // Flags. Currently unused. + MojoArmTrapFlags flags; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +// A user-provided callback to handle trap events. Passed to |MojoCreateTrap()|. +typedef void (*MojoTrapEventHandler)(const struct MojoTrapEvent* event); + +// Creates a new trap which can be used to detect signal changes on a handle. +// Traps execute arbitrary user code when tripped. +// +// Traps can trip only while armed**, and new traps are created in a disarmed +// state. Traps may be armed using |MojoArmTrap()|. +// +// Arming a trap is only possible when the trap has one or more triggers +// attached to it. Triggers can be added or removed using |MojoAddTrigger()| and +// |MojoRemoveTrigger()|. +// +// If a trap is tripped by any of its triggers, it is disarmed immediately and +// the traps |MojoTrapEventHandler| is invoked once for every relevant trigger. +// +// |options| may be null. +// +// ** An unarmed trap will still fire an event when a trigger is removed. This +// event will always convey the result |MOJO_RESULT_CANCELLED|. +// +// Parameters: +// |handler|: The |MojoTrapEventHandler| to invoke any time this trap is +// tripped. Note that this may be called from any arbitrary thread. +// |trap_handle|: The address at which to store the MojoHandle corresponding +// to the new trap if successfully created. +// +// Returns: +// |MOJO_RESULT_OK| if the trap has been successfully created. +// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for +// this trap. +MOJO_SYSTEM_EXPORT MojoResult +MojoCreateTrap(MojoTrapEventHandler handler, + const struct MojoCreateTrapOptions* options, + MojoHandle* trap_handle); + +// Adds a trigger to a trap. This configures the trap to invoke its event +// handler if the specified conditions are met (or can no longer be met) while +// the trap is armed. +// +// Note that event handler invocations for a given trigger are mutually +// exclusive in execution: the handler will never be entered for a trigger while +// another thread is executing it for the same trigger. Similarly, event +// handlers are never re-entered. If an event handler changes the state of the +// system such that another event would fire, that event is deferred until the +// first handler returns. +// +// Parameters: +// |trap_handle|: The trap to which this trigger is to be added. +// |handle|: The handle whose signals this trigger will observe. Must be a +// message pipe or data pipe handle. +// |signals|: The specific signal(s) this trigger will observe on |handle|. +// |condition|: The signaling condition this trigger will observe. i.e. +// whether to trip the trap when |signals| become satisfied or when they +// become unsatisfied. +// |context|: An arbitrary context value to be passed to the trap's event +// handler when this trigger was responsible for tripping the trap. See +// the |trigger_context| field in |MojoTrapEvent|. This value must be +// unique among all triggers on the trap. +// +// |options| may be null. +// +// Returns: +// |MOJO_RESULT_OK| if the handle is now being observed by the trigger. +// |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle, +// |handle| is not a valid message pipe or data pipe handle, or |signals| +// or |condition| are an invalid value. +// |MOJO_RESULT_ALREADY_EXISTS| if the trap already has a trigger associated +// with |context| or |handle|. +MOJO_SYSTEM_EXPORT MojoResult +MojoAddTrigger(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const struct MojoAddTriggerOptions* options); + +// Removes a trigger from a trap. +// +// This ensures that the trigger is removed as soon as possible. Removal may +// block an arbitrarily long time if the trap is already executing its handler. +// +// When removal is complete, the trap's handler is invoked one final time for +// time for |context|, with the result |MOJO_RESULT_CANCELLED|. +// +// The same behavior can be elicted by either closing the watched handle +// associated with this trigger, or by closing |trap_handle| itself. +// +// Parameters: +// |trap_handle|: The handle of the trap from which to remove a trigger. +// |context|: The context of the trigger to be removed. +// +// Returns: +// |MOJO_RESULT_OK| if the trigger has been removed. +// |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle. +// |MOJO_RESULT_NOT_FOUND| if there is no trigger registered on this trap for +// the given value of |context|. +MOJO_SYSTEM_EXPORT MojoResult +MojoRemoveTrigger(MojoHandle trap_handle, + uintptr_t context, + const struct MojoRemoveTriggerOptions* options); + +// Arms a trap, allowing it to invoke its event handler the next time any of its +// triggers' conditions are met. +// +// Parameters: +// |trap_handle|: The handle of the trap to be armed. +// |num_ready_triggers|: An address pointing to the number of elements +// available for storage in the following output buffer parameters. +// Optional and only used when |MOJO_RESULT_FAILED_PRECONDITION| is +// returned. See below. +// |ready_triggers|: An output buffer for contexts of triggers that would have +// tripped the trap immediately if it were armed. Optional and used only +// when |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below. +// |ready_results|: An output buffer for |MojoResult| values corresponding to +// each trigger in |ready_triggers|. Optional and only used when +// |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below. +// |ready_signals_states|: An output buffer for |MojoHandleSignalsState| +// structures corresponding to the handle observed by each respective +// trigger in |ready_triggers|. Optional and only used when +// |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below. +// +// Returns: +// |MOJO_RESULT_OK| if the trap has been successfully armed. All arguments +// other than |trap_handle| are ignored in this case. +// |MOJO_RESULT_NOT_FOUND| if the trap does not have any triggers. All +// arguments other than |trap_handle| are ignored. +// |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a valid trap handle, +// or if |num_ready_triggers| is non-null and any of the output buffer +// paramters is null. +// |MOJO_RESULT_FAILED_PRECONDITION| if one or more triggers would have +// tripped the trap immediately upon arming. If |num_handles| is non-null, +// this assumes there is enough space for |*num_handles| entries in each +// of the subsequent output buffer parameters. +// +// At most |*num_handles| entries are populated in the output buffers, +// with each entry corresponding to one of the triggers which would have +// tripped the trap. The actual number of entries populated is written to +// |*num_handles| before returning. +// +// If there are more ready triggers than available provided storage, the +// subset presented to thecaller is arbitrary. The runtime makes an effort +// to circulate triggers returned by consecutive failed |MojoArmTrap()| +// calls so that callers may avoid handle starvation when observing a +// large number of active handles with a single trap. +MOJO_SYSTEM_EXPORT MojoResult +MojoArmTrap(MojoHandle trap_handle, + const struct MojoArmTrapOptions* options, + uint32_t* num_ready_triggers, + uintptr_t* ready_triggers, + MojoResult* ready_results, + struct MojoHandleSignalsState* ready_signals_states); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // MOJO_PUBLIC_C_SYSTEM_TRAP_H_ diff --git a/chromium/mojo/public/c/system/types.h b/chromium/mojo/public/c/system/types.h index 84e35b74ac9..2a6cdbcb4b0 100644 --- a/chromium/mojo/public/c/system/types.h +++ b/chromium/mojo/public/c/system/types.h @@ -77,7 +77,7 @@ const MojoHandle MOJO_HANDLE_INVALID = 0; // the resource being invalidated. // |MOJO_RESULT_SHOULD_WAIT| - The request cannot currently be completed // (e.g., if the data requested is not yet available). The caller should -// wait for it to be feasible using a watcher. +// wait for it to be feasible using a trap. // // The codes from |MOJO_RESULT_OK| to |MOJO_RESULT_DATA_LOSS| come from // Google3's canonical error codes. @@ -136,6 +136,21 @@ const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1); #define MOJO_DEADLINE_INDEFINITE ((MojoDeadline)-1) #endif +// Flags passed to |MojoInitialize()| via |MojoInitializeOptions|. +typedef uint32_t MojoInitializeFlags; + +// No flags. +#define MOJO_INITIALIZE_FLAG_NONE ((MojoInitializeFlags)0) + +// Options passed to |MojoInitialize()|. +struct MOJO_ALIGNAS(8) MojoInitializeOptions { + // The size of this structure, used for versioning. + uint32_t struct_size; + + // See |MojoInitializeFlags|. + MojoInitializeFlags flags; +}; + // |MojoHandleSignals|: Used to specify signals that can be watched for on a // handle (and which can be triggered), e.g., the ability to read or write to // the handle. @@ -191,49 +206,6 @@ struct MOJO_ALIGNAS(4) MojoHandleSignalsState { MOJO_STATIC_ASSERT(sizeof(MojoHandleSignalsState) == 8, "MojoHandleSignalsState has wrong size"); -// |MojoWatcherNotificationFlags|: Passed to a callback invoked by a watcher -// when some observed signals are raised or a watched handle is closed. May take -// on any combination of the following values: -// -// |MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM| - The callback is being -// invoked as a result of a system-level event rather than a direct API -// call from user code. This may be used as an indication that user code -// is safe to call without fear of reentry. - -typedef uint32_t MojoWatcherNotificationFlags; - -#ifdef __cplusplus -const MojoWatcherNotificationFlags MOJO_WATCHER_NOTIFICATION_FLAG_NONE = 0; -const MojoWatcherNotificationFlags MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM = - 1 << 0; -#else -#define MOJO_WATCHER_NOTIFICATION_FLAG_NONE ((MojoWatcherNotificationFlags)0) -#define MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM \ - ((MojoWatcherNotificationFlags)1 << 0); -#endif - -// |MojoWatchCondition|: Given to |MojoWatch()| to indicate whether the -// watched signals should trigger a notification when becoming satisfied or -// becoming not-satisfied. -// -// |MOJO_WATCH_CONDITION_NOT_SATISFIED| - A watch added with this setting will -// trigger a notification when any of the watched signals transition from -// being not-satisfied to being satisfied. -// |MOJO_WATCH_CONDITION_SATISFIED| - A watch added with this setting will -// trigger a notification when any of the watched signals transition from -// being satisfied to being not-satisfied, or when none of the watched -// signals can ever be satisfied again. - -typedef uint32_t MojoWatchCondition; - -#ifdef __cplusplus -const MojoWatchCondition MOJO_WATCH_CONDITION_NOT_SATISFIED = 0; -const MojoWatchCondition MOJO_WATCH_CONDITION_SATISFIED = 1; -#else -#define MOJO_WATCH_CONDITION_NOT_SATISFIED ((MojoWatchCondition)0) -#define MOJO_WATCH_CONDITION_SATISFIED ((MojoWatchCondition)1) -#endif - // |MojoPropertyType|: Property types that can be passed to |MojoGetProperty()| // to retrieve system properties. May take the following values: // |MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED| - Whether making synchronous calls @@ -248,4 +220,9 @@ const MojoPropertyType MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED = 0; #define MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED ((MojoPropertyType)0) #endif +// TODO(https://crbug.com/819046): Remove these aliases. +#define MOJO_WATCH_CONDITION_SATISFIED MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED +#define MOJO_WATCH_CONDITION_NOT_SATISFIED \ + MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED + #endif // MOJO_PUBLIC_C_SYSTEM_TYPES_H_ diff --git a/chromium/mojo/public/c/system/watcher.h b/chromium/mojo/public/c/system/watcher.h deleted file mode 100644 index 10b9168810a..00000000000 --- a/chromium/mojo/public/c/system/watcher.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ -#define MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ - -#include <stdint.h> - -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// A callback used to notify watchers about events on their watched handles. -// -// See documentation for |MojoWatcherNotificationFlags| for details regarding -// the possible values of |flags|. -// -// See documentation for |MojoWatch()| for details regarding the other arguments -// this callback receives when called. -typedef void (*MojoWatcherCallback)(uintptr_t context, - MojoResult result, - struct MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags); - -// Creates a new watcher. -// -// Watchers are used to trigger arbitrary code execution when one or more -// handles change state to meet certain conditions. -// -// A newly registered watcher is initially disarmed and may be armed using -// |MojoArmWatcher()|. A watcher is also always disarmed immediately before any -// invocation of one or more notification callbacks in response to a single -// handle's state changing in some relevant way. -// -// Parameters: -// |callback|: The |MojoWatcherCallback| to invoke any time the watcher is -// notified of an event. See |MojoWatch()| for details regarding arguments -// passed to the callback. Note that this may be called from any arbitrary -// thread. -// |watcher_handle|: The address at which to store the MojoHandle -// corresponding to the new watcher if successfully created. -// -// Returns: -// |MOJO_RESULT_OK| if the watcher has been successfully created. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for -// this watcher. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - -// Adds a watch to a watcher. This allows the watcher to fire notifications -// regarding state changes on the handle corresponding to the arguments given. -// -// Note that notifications for a given watch context are guaranteed to be -// mutually exclusive in execution: the callback will never be entered for a -// given context while another invocation of the callback is still executing for -// the same context. As a result it is generally a good idea to ensure that -// callbacks do as little work as necessary in order to process the -// notification. -// -// Parameters: -// |watcher_handle|: The watcher to which |handle| is to be added. -// |handle|: The handle to add to the watcher. -// |signals|: The signals to watch for on |handle|. -// |level|: The level to watch for on |signals|. -// |context|: An arbitrary context value given to any invocation of the -// watcher's callback when invoked as a result of some state change -// relevant to this combination of |handle| and |signals|. Must be -// unique within any given watcher. -// -// Callback parameters (see |MojoWatcherNotificationCallback| above): -// When the watcher invokes its callback as a result of some notification -// relevant to this watch operation, |context| receives the value given here -// and |signals_state| receives the last known signals state of this handle. -// -// |result| is one of the following: -// |MOJO_RESULT_OK| if at least one of the watched signals is satisfied. The -// watcher must be armed for this notification to fire. -// |MOJO_RESULT_FAILED_PRECONDITION| if all of the watched signals are -// permanently unsatisfiable. The watcher must be armed for this -// notification to fire. -// |MOJO_RESULT_CANCELLED| if the watch has been cancelled. The may occur if -// the watcher has been closed, the watched handle has been closed, or -// the watch for |context| has been explicitly cancelled. This is always -// the last result received for any given context, and it is guaranteed -// to be received exactly once per watch, regardless of how the watch -// was cancelled. -// -// Returns: -// |MOJO_RESULT_OK| if the handle is now being watched by the watcher. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a watcher handle, -// |handle| is not a valid message pipe or data pipe handle. -// |MOJO_RESULT_ALREADY_EXISTS| if the watcher already has a watch registered -// for the given value of |context| or for the given |handle|. -MOJO_SYSTEM_EXPORT MojoResult MojoWatch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - MojoWatchCondition condition, - uintptr_t context); - -// Removes a watch from a watcher. -// -// This ensures that the watch is cancelled as soon as possible. Cancellation -// may be deferred (or may even block) an aritrarily long time if the watch is -// already dispatching one or more notifications. -// -// When cancellation is complete, the watcher's callback is invoked one final -// time for |context|, with the result |MOJO_RESULT_CANCELLED|. -// -// The same behavior can be elicted by either closing the watched handle -// associated with this context, or by closing |watcher_handle| itself. In the -// lastter case, all registered contexts on the watcher are implicitly cancelled -// in a similar fashion. -// -// Parameters: -// |watcher_handle|: The handle of the watcher from which to remove a watch. -// |context|: The context of the watch to be removed. -// -// Returns: -// |MOJO_RESULT_OK| if the watch has been cancelled. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a watcher handle. -// |MOJO_RESULT_NOT_FOUND| if there is no watch registered on this watcher for -// the given value of |context|. -MOJO_SYSTEM_EXPORT MojoResult MojoCancelWatch(MojoHandle watcher_handle, - uintptr_t context); - -// Arms a watcher, enabling a single future event on one of the watched handles -// to trigger a single notification for each relevant watch context associated -// with that handle. -// -// Parameters: -// |watcher_handle|: The handle of the watcher. -// |num_ready_contexts|: An address pointing to the number of elements -// available for storage in the remaining output buffers. Optional and -// only used on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below for -// more details. -// |ready_contexts|: An output buffer for contexts corresponding to the -// watches which would have notified if the watcher were armed. Optional -// and only uesd on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below -// for more details. -// |ready_results|: An output buffer for MojoResult values corresponding to -// each context in |ready_contexts|. Optional and only used on failure. -// See |MOJO_RESULT_FAILED_PRECONDITION| below for more details. -// |ready_signals_states|: An output buffer for |MojoHandleSignalsState| -// structures corresponding to each context in |ready_contexts|. Optional -// and only used on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below -// for more details. -// -// Returns: -// |MOJO_RESULT_OK| if the watcher has been successfully armed. All arguments -// other than |watcher_handle| are ignored in this case. -// |MOJO_RESULT_NOT_FOUND| if the watcher does not have any registered watch -// contexts. All arguments other than |watcher_handle| are ignored in this -// case. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a valid watcher -// handle, or if |num_ready_contexts| is non-null but any of the output -// buffer paramters is null. -// |MOJO_RESULT_FAILED_PRECONDITION| if one or more watches would have -// notified immediately upon arming the watcher. If |num_handles| is -// non-null, this assumes there is enough space for |*num_handles| entries -// in each of the subsequent output buffer arguments. -// -// At most that many entries are placed in the output buffers, -// corresponding to the watches which would have signalled if the watcher -// had been armed successfully. The actual number of entries placed in the -// output buffers is written to |*num_ready_contexts| before returning. -// -// If more than (input) |*num_ready_contexts| watch contexts were ready to -// notify, the subset presented in output buffers is arbitrary, but the -// implementation makes a best effort to circulate the outputs across -// consecutive calls so that callers may reliably avoid handle starvation. -MOJO_SYSTEM_EXPORT MojoResult -MojoArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - struct MojoHandleSignalsState* ready_signals_states); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ diff --git a/chromium/mojo/public/cpp/base/BUILD.gn b/chromium/mojo/public/cpp/base/BUILD.gn index 095cc22eb1f..8f6c57a4cf4 100644 --- a/chromium/mojo/public/cpp/base/BUILD.gn +++ b/chromium/mojo/public/cpp/base/BUILD.gn @@ -30,12 +30,15 @@ component("shared_typemap_traits") { sources = [ "big_buffer_mojom_traits.cc", "big_buffer_mojom_traits.h", + "values_mojom_traits.cc", + "values_mojom_traits.h", ] defines = [ "IS_MOJO_BASE_SHARED_TRAITS_IMPL" ] public_deps = [ ":base", + "//base:i18n", "//mojo/public/mojom/base:base_shared", ] } @@ -46,16 +49,29 @@ source_set("tests") { sources = [ "big_buffer_unittest.cc", "big_string_unittest.cc", + "file_path_unittest.cc", + "file_unittest.cc", + "memory_allocator_dump_cross_process_uid_unittest.cc", + "process_id_unittest.cc", + "read_only_buffer_unittest.cc", "ref_counted_memory_unittest.cc", + "shared_memory_unittest.cc", "string16_unittest.cc", + "text_direction_unittest.cc", + "thread_priority_unittest.cc", + "time_unittest.cc", + "unguessable_token_unittest.cc", + "values_unittest.cc", ] public_deps = [ ":base", ":shared_typemap_traits", "//base", + "//base/test:test_support", "//mojo/public/cpp/test_support:test_utils", "//mojo/public/mojom/base", + "//mojo/public/mojom/base:read_only_buffer", "//testing/gtest", ] } diff --git a/chromium/mojo/public/cpp/base/big_buffer.cc b/chromium/mojo/public/cpp/base/big_buffer.cc index 8bf1e84b002..5f18359d2bf 100644 --- a/chromium/mojo/public/cpp/base/big_buffer.cc +++ b/chromium/mojo/public/cpp/base/big_buffer.cc @@ -43,23 +43,7 @@ BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes) {} BigBuffer::BigBuffer(BigBuffer&& other) = default; BigBuffer::BigBuffer(base::span<const uint8_t> data) { - if (data.size() > kMaxInlineBytes) { - auto buffer = mojo::SharedBufferHandle::Create(data.size()); - if (buffer.is_valid()) { - storage_type_ = StorageType::kSharedMemory; - shared_memory_.emplace(std::move(buffer), data.size()); - std::copy(data.begin(), data.end(), - static_cast<uint8_t*>(shared_memory_->buffer_mapping_.get())); - return; - } - } - - // Either the data is small enough that we're happy to carry it in an array, - // or shared buffer allocation failed and we fall back on this as a best- - // effort alternative. - storage_type_ = StorageType::kBytes; - bytes_.resize(data.size()); - std::copy(data.begin(), data.end(), bytes_.begin()); + *this = BigBufferView::ToBigBuffer(BigBufferView(data)); } BigBuffer::BigBuffer(const std::vector<uint8_t>& data) @@ -103,4 +87,69 @@ size_t BigBuffer::size() const { } } +BigBufferView::BigBufferView() = default; + +BigBufferView::BigBufferView(BigBufferView&& other) = default; + +BigBufferView::BigBufferView(base::span<const uint8_t> bytes) { + if (bytes.size() > BigBuffer::kMaxInlineBytes) { + auto buffer = mojo::SharedBufferHandle::Create(bytes.size()); + if (buffer.is_valid()) { + storage_type_ = BigBuffer::StorageType::kSharedMemory; + shared_memory_.emplace(std::move(buffer), bytes.size()); + std::copy(bytes.begin(), bytes.end(), + static_cast<uint8_t*>(shared_memory_->buffer_mapping_.get())); + return; + } + } + + // Either the data is small enough or shared memory allocation failed. Either + // way we fall back to directly referencing the input bytes. + storage_type_ = BigBuffer::StorageType::kBytes; + bytes_ = bytes; +} + +BigBufferView::~BigBufferView() = default; + +BigBufferView& BigBufferView::operator=(BigBufferView&& other) = default; + +void BigBufferView::SetBytes(base::span<const uint8_t> bytes) { + DCHECK(bytes_.empty()); + DCHECK(!shared_memory_); + storage_type_ = BigBuffer::StorageType::kBytes; + bytes_ = bytes; +} + +void BigBufferView::SetSharedMemory( + internal::BigBufferSharedMemoryRegion shared_memory) { + DCHECK(bytes_.empty()); + DCHECK(!shared_memory_); + storage_type_ = BigBuffer::StorageType::kSharedMemory; + shared_memory_ = std::move(shared_memory); +} + +base::span<const uint8_t> BigBufferView::data() const { + if (storage_type_ == BigBuffer::StorageType::kBytes) { + return bytes_; + } else { + DCHECK(shared_memory_.has_value()); + return base::make_span(static_cast<const uint8_t*>(const_cast<const void*>( + shared_memory_->memory())), + shared_memory_->size()); + } +} + +// static +BigBuffer BigBufferView::ToBigBuffer(BigBufferView view) { + BigBuffer buffer; + buffer.storage_type_ = view.storage_type_; + if (view.storage_type_ == BigBuffer::StorageType::kBytes) { + std::copy(view.bytes_.begin(), view.bytes_.end(), + std::back_inserter(buffer.bytes_)); + } else { + buffer.shared_memory_ = std::move(*view.shared_memory_); + } + return buffer; +} + } // namespace mojo_base diff --git a/chromium/mojo/public/cpp/base/big_buffer.h b/chromium/mojo/public/cpp/base/big_buffer.h index dbf8ba3be35..eca2ba7e921 100644 --- a/chromium/mojo/public/cpp/base/big_buffer.h +++ b/chromium/mojo/public/cpp/base/big_buffer.h @@ -18,6 +18,7 @@ namespace mojo_base { class BigBuffer; +class BigBufferView; namespace internal { @@ -39,6 +40,7 @@ class COMPONENT_EXPORT(MOJO_BASE) BigBufferSharedMemoryRegion { private: friend class mojo_base::BigBuffer; + friend class mojo_base::BigBufferView; size_t size_; mojo::ScopedSharedBufferHandle buffer_handle_; @@ -111,6 +113,8 @@ class COMPONENT_EXPORT(MOJO_BASE) BigBuffer { } private: + friend class BigBufferView; + StorageType storage_type_; std::vector<uint8_t> bytes_; base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_; @@ -118,6 +122,58 @@ class COMPONENT_EXPORT(MOJO_BASE) BigBuffer { DISALLOW_COPY_AND_ASSIGN(BigBuffer); }; +// Similar to BigBuffer, but doesn't *necessarily* own the buffer storage. +// Namely, if constructed over a small enough span of memory, it will simply +// retain a reference to that memory. This is generally only safe to use for +// serialization and deserialization. +class COMPONENT_EXPORT(MOJO_BASE) BigBufferView { + public: + BigBufferView(); + BigBufferView(BigBufferView&& other); + + // Constructs a BigBufferView over |bytes|. If |bytes| is large enough, this + // will allocate shared memory and copy the contents there. Otherwise this + // will retain an unsafe reference to |bytes| and must therefore not outlive + // |bytes|. + explicit BigBufferView(base::span<const uint8_t> bytes); + ~BigBufferView(); + + BigBufferView& operator=(BigBufferView&& other); + + base::span<const uint8_t> data() const; + + // Explicitly retains a reference to |bytes| as the backing storage for this + // view. Does not copy and therefore |bytes| must remain valid throughout the + // view's lifetime. Used for deserialization. + void SetBytes(base::span<const uint8_t> bytes); + + // Explictly adopts |shared_memory| as the backing storage for this view. Used + // for deserialization. + void SetSharedMemory(internal::BigBufferSharedMemoryRegion shared_memory); + + // Converts to a BigBuffer which owns the viewed data. May have to copy data. + static BigBuffer ToBigBuffer(BigBufferView view) WARN_UNUSED_RESULT; + + BigBuffer::StorageType storage_type() const { return storage_type_; } + + base::span<const uint8_t> bytes() const { + DCHECK_EQ(storage_type_, BigBuffer::StorageType::kBytes); + return bytes_; + } + + internal::BigBufferSharedMemoryRegion& shared_memory() { + DCHECK_EQ(storage_type_, BigBuffer::StorageType::kSharedMemory); + return shared_memory_.value(); + } + + private: + BigBuffer::StorageType storage_type_; + base::span<const uint8_t> bytes_; + base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_; + + DISALLOW_COPY_AND_ASSIGN(BigBufferView); +}; + } // namespace mojo_base #endif // MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_H_ diff --git a/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.cc b/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.cc index 20237396f4d..1e1b8571aeb 100644 --- a/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.cc +++ b/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.cc @@ -89,4 +89,58 @@ bool UnionTraits<mojo_base::mojom::BigBufferDataView, mojo_base::BigBuffer>:: return false; } +// static +mojo_base::mojom::BigBufferDataView::Tag UnionTraits< + mojo_base::mojom::BigBufferDataView, + mojo_base::BigBufferView>::GetTag(const mojo_base::BigBufferView& view) { + switch (view.storage_type()) { + case mojo_base::BigBuffer::StorageType::kBytes: + return mojo_base::mojom::BigBufferDataView::Tag::BYTES; + case mojo_base::BigBuffer::StorageType::kSharedMemory: + return mojo_base::mojom::BigBufferDataView::Tag::SHARED_MEMORY; + } + + NOTREACHED(); + return mojo_base::mojom::BigBufferDataView::Tag::BYTES; +} + +// static +base::span<const uint8_t> UnionTraits< + mojo_base::mojom::BigBufferDataView, + mojo_base::BigBufferView>::bytes(const mojo_base::BigBufferView& view) { + return view.bytes(); +} + +// static +mojo_base::internal::BigBufferSharedMemoryRegion& UnionTraits< + mojo_base::mojom::BigBufferDataView, + mojo_base::BigBufferView>::shared_memory(mojo_base::BigBufferView& view) { + return view.shared_memory(); +} + +// static +bool UnionTraits< + mojo_base::mojom::BigBufferDataView, + mojo_base::BigBufferView>::Read(mojo_base::mojom::BigBufferDataView data, + mojo_base::BigBufferView* out) { + switch (data.tag()) { + case mojo_base::mojom::BigBufferDataView::Tag::BYTES: { + mojo::ArrayDataView<uint8_t> bytes_view; + data.GetBytesDataView(&bytes_view); + out->SetBytes(bytes_view); + return true; + } + + case mojo_base::mojom::BigBufferDataView::Tag::SHARED_MEMORY: { + mojo_base::internal::BigBufferSharedMemoryRegion shared_memory; + if (!data.ReadSharedMemory(&shared_memory)) + return false; + out->SetSharedMemory(std::move(shared_memory)); + return true; + } + } + + return false; +} + } // namespace mojo diff --git a/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.h b/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.h index fcdeb5baf70..b2ca9549922 100644 --- a/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.h +++ b/chromium/mojo/public/cpp/base/big_buffer_mojom_traits.h @@ -9,6 +9,8 @@ #include <vector> #include "base/component_export.h" +#include "base/containers/span.h" +#include "base/macros.h" #include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/bindings/union_traits.h" #include "mojo/public/cpp/system/buffer.h" @@ -43,6 +45,20 @@ struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS) mojo_base::BigBuffer* out); }; +template <> +struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS) + UnionTraits<mojo_base::mojom::BigBufferDataView, mojo_base::BigBufferView> { + static mojo_base::mojom::BigBufferDataView::Tag GetTag( + const mojo_base::BigBufferView& view); + + static base::span<const uint8_t> bytes(const mojo_base::BigBufferView& view); + static mojo_base::internal::BigBufferSharedMemoryRegion& shared_memory( + mojo_base::BigBufferView& view); + + static bool Read(mojo_base::mojom::BigBufferDataView data, + mojo_base::BigBufferView* out); +}; + } // namespace mojo #endif // MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/file.typemap b/chromium/mojo/public/cpp/base/file.typemap new file mode 100644 index 00000000000..85ef6eb2e7c --- /dev/null +++ b/chromium/mojo/public/cpp/base/file.typemap @@ -0,0 +1,14 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//mojo/public/mojom/base/file.mojom" +public_headers = [ "//base/files/file.h" ] +traits_headers = [ "//mojo/public/cpp/base/file_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/file_mojom_traits.cc", + "//mojo/public/cpp/base/file_mojom_traits.h", +] + +type_mappings = + [ "mojo_base.mojom.File=base::File[move_only,nullable_is_same_type]" ] diff --git a/chromium/mojo/public/cpp/base/file_error.typemap b/chromium/mojo/public/cpp/base/file_error.typemap new file mode 100644 index 00000000000..738a9a7c484 --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_error.typemap @@ -0,0 +1,12 @@ +# Copyright 2018 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. + +mojom = "//mojo/public/mojom/base/file_error.mojom" +public_headers = [ "//base/files/file.h" ] +traits_headers = [ "//mojo/public/cpp/base/file_error_mojom_traits.h" ] +public_deps = [ + "//base", + "//mojo/public/cpp/bindings", +] +type_mappings = [ "mojo_base.mojom.FileError=::base::File::Error" ] diff --git a/chromium/mojo/public/cpp/base/file_error_mojom_traits.h b/chromium/mojo/public/cpp/base/file_error_mojom_traits.h new file mode 100644 index 00000000000..941608e31fa --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_error_mojom_traits.h @@ -0,0 +1,120 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_FILE_ERROR_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_FILE_ERROR_MOJOM_TRAITS_H_ + +#include "base/files/file.h" +#include "mojo/public/mojom/base/file_error.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<mojo_base::mojom::FileError, base::File::Error> { + static mojo_base::mojom::FileError ToMojom(base::File::Error error) { + switch (error) { + case base::File::FILE_OK: + return mojo_base::mojom::FileError::OK; + case base::File::FILE_ERROR_FAILED: + return mojo_base::mojom::FileError::FAILED; + case base::File::FILE_ERROR_IN_USE: + return mojo_base::mojom::FileError::IN_USE; + case base::File::FILE_ERROR_EXISTS: + return mojo_base::mojom::FileError::EXISTS; + case base::File::FILE_ERROR_NOT_FOUND: + return mojo_base::mojom::FileError::NOT_FOUND; + case base::File::FILE_ERROR_ACCESS_DENIED: + return mojo_base::mojom::FileError::ACCESS_DENIED; + case base::File::FILE_ERROR_TOO_MANY_OPENED: + return mojo_base::mojom::FileError::TOO_MANY_OPENED; + case base::File::FILE_ERROR_NO_MEMORY: + return mojo_base::mojom::FileError::NO_MEMORY; + case base::File::FILE_ERROR_NO_SPACE: + return mojo_base::mojom::FileError::NO_SPACE; + case base::File::FILE_ERROR_NOT_A_DIRECTORY: + return mojo_base::mojom::FileError::NOT_A_DIRECTORY; + case base::File::FILE_ERROR_INVALID_OPERATION: + return mojo_base::mojom::FileError::INVALID_OPERATION; + case base::File::FILE_ERROR_SECURITY: + return mojo_base::mojom::FileError::SECURITY; + case base::File::FILE_ERROR_ABORT: + return mojo_base::mojom::FileError::ABORT; + case base::File::FILE_ERROR_NOT_A_FILE: + return mojo_base::mojom::FileError::NOT_A_FILE; + case base::File::FILE_ERROR_NOT_EMPTY: + return mojo_base::mojom::FileError::NOT_EMPTY; + case base::File::FILE_ERROR_INVALID_URL: + return mojo_base::mojom::FileError::INVALID_URL; + case base::File::FILE_ERROR_IO: + return mojo_base::mojom::FileError::IO; + case base::File::FILE_ERROR_MAX: + return mojo_base::mojom::FileError::FAILED; + } + NOTREACHED(); + return mojo_base::mojom::FileError::FAILED; + } + + static bool FromMojom(mojo_base::mojom::FileError in, + base::File::Error* out) { + switch (in) { + case mojo_base::mojom::FileError::OK: + *out = base::File::FILE_OK; + return true; + case mojo_base::mojom::FileError::FAILED: + *out = base::File::FILE_ERROR_FAILED; + return true; + case mojo_base::mojom::FileError::IN_USE: + *out = base::File::FILE_ERROR_IN_USE; + return true; + case mojo_base::mojom::FileError::EXISTS: + *out = base::File::FILE_ERROR_EXISTS; + return true; + case mojo_base::mojom::FileError::NOT_FOUND: + *out = base::File::FILE_ERROR_NOT_FOUND; + return true; + case mojo_base::mojom::FileError::ACCESS_DENIED: + *out = base::File::FILE_ERROR_ACCESS_DENIED; + return true; + case mojo_base::mojom::FileError::TOO_MANY_OPENED: + *out = base::File::FILE_ERROR_TOO_MANY_OPENED; + return true; + case mojo_base::mojom::FileError::NO_MEMORY: + *out = base::File::FILE_ERROR_NO_MEMORY; + return true; + case mojo_base::mojom::FileError::NO_SPACE: + *out = base::File::FILE_ERROR_NO_SPACE; + return true; + case mojo_base::mojom::FileError::NOT_A_DIRECTORY: + *out = base::File::FILE_ERROR_NOT_A_DIRECTORY; + return true; + case mojo_base::mojom::FileError::INVALID_OPERATION: + *out = base::File::FILE_ERROR_INVALID_OPERATION; + return true; + case mojo_base::mojom::FileError::SECURITY: + *out = base::File::FILE_ERROR_SECURITY; + return true; + case mojo_base::mojom::FileError::ABORT: + *out = base::File::FILE_ERROR_ABORT; + return true; + case mojo_base::mojom::FileError::NOT_A_FILE: + *out = base::File::FILE_ERROR_NOT_A_FILE; + return true; + case mojo_base::mojom::FileError::NOT_EMPTY: + *out = base::File::FILE_ERROR_NOT_EMPTY; + return true; + case mojo_base::mojom::FileError::INVALID_URL: + *out = base::File::FILE_ERROR_INVALID_URL; + return true; + case mojo_base::mojom::FileError::IO: + *out = base::File::FILE_ERROR_IO; + return true; + } + NOTREACHED(); + return false; + } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_FILE_ERROR_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/common/file_info.typemap b/chromium/mojo/public/cpp/base/file_info.typemap index 77b2ae20146..f6ef16a586c 100644 --- a/chromium/mojo/common/file_info.typemap +++ b/chromium/mojo/public/cpp/base/file_info.typemap @@ -2,11 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//mojo/common/file_info.mojom" +mojom = "//mojo/public/mojom/base/file_info.mojom" public_headers = [ "//base/files/file.h" ] traits_headers = [ "//ipc/ipc_message_utils.h" ] public_deps = [ "//ipc", ] -type_mappings = [ "mojo.common.mojom.FileInfo=base::File::Info" ] +type_mappings = [ "mojo_base.mojom.FileInfo=base::File::Info" ] diff --git a/chromium/mojo/public/cpp/base/file_mojom_traits.cc b/chromium/mojo/public/cpp/base/file_mojom_traits.cc new file mode 100644 index 00000000000..e7fd60590ea --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_mojom_traits.cc @@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/file_mojom_traits.h" +#include "base/files/file.h" +#include "mojo/public/cpp/system/platform_handle.h" + +namespace mojo { + +mojo::ScopedHandle StructTraits<mojo_base::mojom::FileDataView, base::File>::fd( + base::File& file) { + DCHECK(file.IsValid()); + + return mojo::WrapPlatformFile(file.TakePlatformFile()); +} + +bool StructTraits<mojo_base::mojom::FileDataView, base::File>::Read( + mojo_base::mojom::FileDataView data, + base::File* file) { + base::PlatformFile platform_handle = base::kInvalidPlatformFile; + if (mojo::UnwrapPlatformFile(data.TakeFd(), &platform_handle) != + MOJO_RESULT_OK) { + return false; + } + *file = base::File(platform_handle); + return true; +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/base/file_mojom_traits.h b/chromium/mojo/public/cpp/base/file_mojom_traits.h new file mode 100644 index 00000000000..ac2d0d294a9 --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_mojom_traits.h @@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_FILE_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_FILE_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/files/file.h" +#include "mojo/public/mojom/base/file.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::FileDataView, base::File> { + static bool IsNull(const base::File& file) { return !file.IsValid(); } + + static void SetToNull(base::File* file) { *file = base::File(); } + + static mojo::ScopedHandle fd(base::File& file); + static bool Read(mojo_base::mojom::FileDataView data, base::File* file); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_FILE_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/common/file_path.typemap b/chromium/mojo/public/cpp/base/file_path.typemap index 66d8c54da8a..682200f0c5e 100644 --- a/chromium/mojo/common/file_path.typemap +++ b/chromium/mojo/public/cpp/base/file_path.typemap @@ -2,11 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//mojo/common/file_path.mojom" +mojom = "//mojo/public/mojom/base/file_path.mojom" public_headers = [ "//base/files/file_path.h" ] traits_headers = [ "//ipc/ipc_message_utils.h" ] public_deps = [ "//ipc", ] -type_mappings = [ "mojo.common.mojom.FilePath=base::FilePath" ] +type_mappings = [ "mojo_base.mojom.FilePath=base::FilePath" ] diff --git a/chromium/mojo/public/cpp/base/file_path_unittest.cc b/chromium/mojo/public/cpp/base/file_path_unittest.cc new file mode 100644 index 00000000000..9c53bff3c20 --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_path_unittest.cc @@ -0,0 +1,24 @@ +// Copyright 2018 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 "ipc/ipc_message_utils.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/file_path.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace file_path_unittest { + +TEST(FilePathTest, File) { + base::FilePath dir(FILE_PATH_LITERAL("hello")); + base::FilePath file = dir.Append(FILE_PATH_LITERAL("world")); + base::FilePath file_out; + + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::FilePath>(&file, &file_out)); + ASSERT_EQ(file, file_out); +} + +} // namespace file_path_unittest +} // namespace mojo_base diff --git a/chromium/mojo/public/cpp/base/file_unittest.cc b/chromium/mojo/public/cpp/base/file_unittest.cc new file mode 100644 index 00000000000..fb3cff405e1 --- /dev/null +++ b/chromium/mojo/public/cpp/base/file_unittest.cc @@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/scoped_temp_dir.h" +#include "mojo/public/cpp/base/file_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/file.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace file_unittest { + +TEST(FileTest, File) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + base::File file( + temp_dir.GetPath().AppendASCII("test_file.txt"), + base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); + const base::StringPiece test_content = + "A test string to be stored in a test file"; + file.WriteAtCurrentPos(test_content.data(), + base::checked_cast<int>(test_content.size())); + + base::File file_out; + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::File>(&file, &file_out)); + std::vector<char> content(test_content.size()); + ASSERT_TRUE(file_out.IsValid()); + ASSERT_EQ(static_cast<int>(test_content.size()), + file_out.Read(0, content.data(), + base::checked_cast<int>(test_content.size()))); + EXPECT_EQ(test_content, + base::StringPiece(content.data(), test_content.size())); +} + +TEST(FileTest, InvalidFile) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + // Test that |file_out| is set to an invalid file. + base::File file_out( + temp_dir.GetPath().AppendASCII("test_file.txt"), + base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); + + base::File file = base::File(); + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::File>(&file, &file_out)); + EXPECT_FALSE(file_out.IsValid()); +} + +} // namespace file_unittest +} // namespace mojo_base diff --git a/chromium/mojo/common/logfont_win.typemap b/chromium/mojo/public/cpp/base/logfont_win.typemap index 488d22ef248..43cdc1e2c1d 100644 --- a/chromium/mojo/common/logfont_win.typemap +++ b/chromium/mojo/public/cpp/base/logfont_win.typemap @@ -2,11 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//mojo/common/logfont_win.mojom" +mojom = "//mojo/public/mojom/base/logfont_win.mojom" os_whitelist = [ "win" ] public_headers = [ "//base/win/windows_full.h" ] traits_headers = [ "//ipc/ipc_message_utils.h" ] public_deps = [ "//ipc", ] -type_mappings = [ "mojo.common.mojom.LOGFONT=::LOGFONT" ] +type_mappings = [ "mojo_base.mojom.LOGFONT=::LOGFONT" ] diff --git a/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap new file mode 100644 index 00000000000..f839a951615 --- /dev/null +++ b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap @@ -0,0 +1,13 @@ +# Copyright 2017 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. + +mojom = "//mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom" +public_headers = [ "//base/trace_event/memory_allocator_dump_guid.h" ] +traits_headers = [ "//mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.cc", + "//mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h", +] + +type_mappings = [ "mojo_base.mojom.MemoryAllocatorDumpCrossProcessUid=base::trace_event::MemoryAllocatorDumpGuid" ] diff --git a/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.cc b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.cc new file mode 100644 index 00000000000..4a5ed8e1198 --- /dev/null +++ b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.cc @@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits<mojo_base::mojom::MemoryAllocatorDumpCrossProcessUidDataView, + base::trace_event::MemoryAllocatorDumpGuid>:: + Read(mojo_base::mojom::MemoryAllocatorDumpCrossProcessUidDataView data, + base::trace_event::MemoryAllocatorDumpGuid* out) { + // Receiving a zeroed MemoryAllocatorDumpCrossProcessUid is a bug. + if (data.value() == 0) + return false; + + *out = base::trace_event::MemoryAllocatorDumpGuid(data.value()); + return true; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h new file mode 100644 index 00000000000..b99a9c537a0 --- /dev/null +++ b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h @@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_MEMORY_ALLOCATOR_DUMP_CROSS_PROCESS_UID_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_MEMORY_ALLOCATOR_DUMP_CROSS_PROCESS_UID_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/trace_event/memory_allocator_dump_guid.h" +#include "mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::MemoryAllocatorDumpCrossProcessUidDataView, + base::trace_event::MemoryAllocatorDumpGuid> { + static uint64_t value(const base::trace_event::MemoryAllocatorDumpGuid& id) { + return id.ToUint64(); + } + + static bool Read( + mojo_base::mojom::MemoryAllocatorDumpCrossProcessUidDataView data, + base::trace_event::MemoryAllocatorDumpGuid* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_MEMORY_ALLOCATOR_DUMP_CROSS_PROCESS_UID_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_unittest.cc b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_unittest.cc new file mode 100644 index 00000000000..b89781cbd8c --- /dev/null +++ b/chromium/mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_unittest.cc @@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/memory_allocator_dump_cross_process_uid_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace memory_allocator_dump_cross_process_uid_unittest { + +TEST(MemoryAllocatorDumpCrossProcessUidTest, SerializeFailsOnZeroValue) { + base::trace_event::MemoryAllocatorDumpGuid in(0); + base::trace_event::MemoryAllocatorDumpGuid out; + + ASSERT_FALSE(mojo::test::SerializeAndDeserialize< + mojom::MemoryAllocatorDumpCrossProcessUid>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(MemoryAllocatorDumpCrossProcessUidTest, SerializeSucceedsOnValidIntValue) { + base::trace_event::MemoryAllocatorDumpGuid in(12345); + base::trace_event::MemoryAllocatorDumpGuid out; + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize< + mojom::MemoryAllocatorDumpCrossProcessUid>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(MemoryAllocatorDumpCrossProcessUidTest, + SerializeSucceedsOnValidStringValue) { + base::trace_event::MemoryAllocatorDumpGuid in("12345"); + base::trace_event::MemoryAllocatorDumpGuid out; + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize< + mojom::MemoryAllocatorDumpCrossProcessUid>(&in, &out)); + EXPECT_EQ(in, out); +} + +} // namespace memory_allocator_dump_cross_process_uid_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/process_id.typemap b/chromium/mojo/public/cpp/base/process_id.typemap new file mode 100644 index 00000000000..7ba31ffc81b --- /dev/null +++ b/chromium/mojo/public/cpp/base/process_id.typemap @@ -0,0 +1,14 @@ +# Copyright 2017 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. + +mojom = "//mojo/public/mojom/base/process_id.mojom" +public_headers = [ "//base/process/process_handle.h" ] +traits_headers = [ "//mojo/public/cpp/base/process_id_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/process_id_mojom_traits.cc", + "//mojo/public/cpp/base/process_id_mojom_traits.h", +] + +type_mappings = + [ "mojo_base.mojom.ProcessId=base::ProcessId[copyable_pass_by_value]" ] diff --git a/chromium/mojo/public/cpp/base/process_id_mojom_traits.cc b/chromium/mojo/public/cpp/base/process_id_mojom_traits.cc new file mode 100644 index 00000000000..fd49327c1a3 --- /dev/null +++ b/chromium/mojo/public/cpp/base/process_id_mojom_traits.cc @@ -0,0 +1,16 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/process_id_mojom_traits.h" + +namespace mojo { + +bool StructTraits<mojo_base::mojom::ProcessIdDataView, base::ProcessId>::Read( + mojo_base::mojom::ProcessIdDataView data, + base::ProcessId* process_id) { + *process_id = static_cast<base::ProcessId>(data.pid()); + return true; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/process_id_mojom_traits.h b/chromium/mojo/public/cpp/base/process_id_mojom_traits.h new file mode 100644 index 00000000000..ba8a80db478 --- /dev/null +++ b/chromium/mojo/public/cpp/base/process_id_mojom_traits.h @@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_PROCESS_ID_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_PROCESS_ID_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/process/process_handle.h" +#include "mojo/public/mojom/base/process_id.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::ProcessIdDataView, base::ProcessId> { + static uint32_t pid(const base::ProcessId& process_id) { + return static_cast<uint32_t>(process_id); + } + + static bool Read(mojo_base::mojom::ProcessIdDataView data, + base::ProcessId* process_id); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_PROCESS_ID_MOJOM_TRAITS_H_
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/process_id_unittest.cc b/chromium/mojo/public/cpp/base/process_id_unittest.cc new file mode 100644 index 00000000000..d0025320e79 --- /dev/null +++ b/chromium/mojo/public/cpp/base/process_id_unittest.cc @@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/process_id_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/process_id.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace process_id_unittest { + +TEST(ProcessIdTest, ProcessId) { + base::ProcessId pid = base::GetCurrentProcId(); + base::ProcessId out_pid = base::kNullProcessId; + ASSERT_NE(pid, out_pid); + EXPECT_TRUE(mojom::ProcessId::Deserialize(mojom::ProcessId::Serialize(&pid), + &out_pid)); + EXPECT_EQ(pid, out_pid); +} + +} // namespace process_id_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/read_only_buffer.typemap b/chromium/mojo/public/cpp/base/read_only_buffer.typemap new file mode 100644 index 00000000000..b772b729b67 --- /dev/null +++ b/chromium/mojo/public/cpp/base/read_only_buffer.typemap @@ -0,0 +1,13 @@ +# Copyright 2017 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. + +mojom = "//mojo/public/mojom/base/read_only_buffer.mojom" +public_headers = [ "//base/containers/span.h" ] +traits_headers = [ "//mojo/public/cpp/base/read_only_buffer_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/read_only_buffer_mojom_traits.cc", + "//mojo/public/cpp/base/read_only_buffer_mojom_traits.h", +] + +type_mappings = [ "mojo_base.mojom.ReadOnlyBuffer=base::span<const uint8_t>[copyable_pass_by_value,force_serialize]" ] diff --git a/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.cc b/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.cc new file mode 100644 index 00000000000..bd5240e48e8 --- /dev/null +++ b/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.cc @@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/read_only_buffer_mojom_traits.h" + +namespace mojo { + +bool StructTraits<mojo_base::mojom::ReadOnlyBufferDataView, + base::span<const uint8_t>>:: + Read(mojo_base::mojom::ReadOnlyBufferDataView input, + base::span<const uint8_t>* out) { + ArrayDataView<uint8_t> data_view; + input.GetBufferDataView(&data_view); + + // NOTE: This output directly refers to memory owned by the message. + // Therefore, the message must stay valid while the output is passed to the + // user code. + *out = base::span<const uint8_t>(data_view.data(), data_view.size()); + return true; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.h b/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.h new file mode 100644 index 00000000000..ad96e91e078 --- /dev/null +++ b/chromium/mojo/public/cpp/base/read_only_buffer_mojom_traits.h @@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_READ_ONLY_BUFFER_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_READ_ONLY_BUFFER_MOJOM_TRAITS_H_ + +#include "base/containers/span.h" +#include "mojo/public/mojom/base/read_only_buffer.mojom-shared.h" + +namespace mojo { + +template <> +struct StructTraits<mojo_base::mojom::ReadOnlyBufferDataView, + base::span<const uint8_t>> { + static base::span<const uint8_t> buffer(base::span<const uint8_t> input) { + return input; + } + + static bool Read(mojo_base::mojom::ReadOnlyBufferDataView input, + base::span<const uint8_t>* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_READ_ONLY_BUFFER_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/read_only_buffer_unittest.cc b/chromium/mojo/public/cpp/base/read_only_buffer_unittest.cc new file mode 100644 index 00000000000..990cb36a0f5 --- /dev/null +++ b/chromium/mojo/public/cpp/base/read_only_buffer_unittest.cc @@ -0,0 +1,37 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/read_only_buffer_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/read_only_buffer.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace read_only_buffer_unittest { + +TEST(ReadOnlyBufferTest, ReadOnlyBufferEmptySpan) { + base::span<const uint8_t> in; + base::span<const uint8_t> out; + + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::ReadOnlyBuffer>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(ReadOnlyBufferTest, ReadOnlyBufferNonEmptySpan) { + std::vector<uint8_t> v{'1', '2', '3'}; + base::span<const uint8_t> in(v); + base::span<const uint8_t> out; + + // SerializeAndDeserialize doesn't work here: the traits for ReadOnlyBuffer + // returns a span that points into the raw bytes in the mojo::Message;however, + // the stack object will be freed before SerializeAndSerialize returns. + std::vector<uint8_t> data = mojom::ReadOnlyBuffer::Serialize(&in); + + EXPECT_TRUE(mojom::ReadOnlyBuffer::Deserialize(std::move(data), &out)); + EXPECT_EQ(in, out); +} + +} // namespace read_only_buffer_unittest +} // namespace mojo_base diff --git a/chromium/mojo/public/cpp/base/shared_memory.typemap b/chromium/mojo/public/cpp/base/shared_memory.typemap new file mode 100644 index 00000000000..77d44a89f06 --- /dev/null +++ b/chromium/mojo/public/cpp/base/shared_memory.typemap @@ -0,0 +1,27 @@ +# Copyright 2018 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. + +mojom = "//mojo/public/mojom/base/shared_memory.mojom" +public_headers = [ + "//base/memory/platform_shared_memory_region.h", + "//base/memory/read_only_shared_memory_region.h", + "//base/memory/unsafe_shared_memory_region.h", + "//base/memory/writable_shared_memory_region.h", +] +traits_headers = [ "//mojo/public/cpp/base/shared_memory_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/shared_memory_mojom_traits.cc", + "//mojo/public/cpp/base/shared_memory_mojom_traits.h", +] +public_deps = [ + "//base", +] +type_mappings = [ + "mojo_base.mojom.PlatformSharedMemoryHandle=base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle[move_only]", + "mojo_base.mojom.PlatformSharedMemoryRegion=base::subtle::PlatformSharedMemoryRegion[move_only]", + "mojo_base.mojom.PlatformSharedMemoryRegion.Mode=base::subtle::PlatformSharedMemoryRegion::Mode", + "mojo_base.mojom.ReadOnlySharedMemoryRegion=base::ReadOnlySharedMemoryRegion[move_only,nullable_is_same_type]", + "mojo_base.mojom.UnsafeSharedMemoryRegion=base::UnsafeSharedMemoryRegion[move_only,nullable_is_same_type]", + "mojo_base.mojom.WritableSharedMemoryRegion=base::WritableSharedMemoryRegion[move_only,nullable_is_same_type]", +] diff --git a/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.cc b/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.cc new file mode 100644 index 00000000000..8c3917015c4 --- /dev/null +++ b/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.cc @@ -0,0 +1,323 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/shared_memory_mojom_traits.h" + +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" +#include "mojo/public/c/system/platform_handle.h" + +namespace mojo { + +// static +mojo::ScopedHandle +StructTraits<mojo_base::mojom::PlatformSharedMemoryHandleDataView, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle>:: + handle_value(base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle& + handle) { + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(platform_handle); +#if defined(OS_WIN) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; + platform_handle.value = reinterpret_cast<uint64_t>(handle.Take()); +#elif defined(OS_FUCHSIA) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#elif defined(OS_MACOSX) && !defined(OS_IOS) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#elif defined(OS_ANDROID) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#else + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; + platform_handle.value = static_cast<uint64_t>(handle.fd.release()); +#endif + MojoHandle mojo_handle; + MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle); + if (result != MOJO_RESULT_OK) + return mojo::ScopedHandle(); + return mojo::ScopedHandle(mojo::Handle(mojo_handle)); +} + +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \ + (!defined(OS_MACOSX) || defined(OS_IOS)) +// static +mojo::ScopedHandle +StructTraits<mojo_base::mojom::PlatformSharedMemoryHandleDataView, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle>:: + readonly_fd(base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle& + handle) { + if (!handle.readonly_fd.is_valid()) + return mojo::ScopedHandle(); + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(platform_handle); + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; + platform_handle.value = static_cast<uint64_t>(handle.readonly_fd.release()); + + MojoHandle mojo_handle; + MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle); + if (result != MOJO_RESULT_OK) + return mojo::ScopedHandle(); + + return mojo::ScopedHandle(mojo::Handle(mojo_handle)); +} +#endif + +bool StructTraits< + mojo_base::mojom::PlatformSharedMemoryHandleDataView, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle>:: + Read(mojo_base::mojom::PlatformSharedMemoryHandleDataView data, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle* out) { + mojo::ScopedHandle mojo_handle = data.TakeHandleValue(); + if (!mojo_handle.is_valid()) + return false; + + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(platform_handle); + MojoResult result = + MojoUnwrapPlatformHandle(mojo_handle.release().value(), &platform_handle); + if (result != MOJO_RESULT_OK) + return false; + +#if defined(OS_WIN) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) + return false; + out->Set(reinterpret_cast<HANDLE>(platform_handle.value)); +#elif defined(OS_FUCHSIA) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE) + return false; + out->reset(static_cast<zx_handle_t>(platform_handle.value)); +#elif defined(OS_MACOSX) && !defined(OS_IOS) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) + return false; + out->reset(static_cast<mach_port_t>(platform_handle.value)); +#elif defined(OS_ANDROID) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) + return false; + out->reset(static_cast<int>(platform_handle.value)); +#else + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) + return false; + out->fd.reset(static_cast<int>(platform_handle.value)); + + // Other POSIX platforms may have an additional FD to support eventual + // read-only duplication. + mojo::ScopedHandle readonly_mojo_handle = data.TakeReadonlyFd(); + + MojoPlatformHandle readonly_platform_handle; + readonly_platform_handle.struct_size = sizeof(readonly_platform_handle); + readonly_platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_INVALID; + if (readonly_mojo_handle.is_valid()) { + MojoResult result = MojoUnwrapPlatformHandle( + readonly_mojo_handle.release().value(), &readonly_platform_handle); + if (result != MOJO_RESULT_OK || + readonly_platform_handle.type != + MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) { + return false; + } + out->readonly_fd.reset(static_cast<int>(readonly_platform_handle.value)); + } +#endif + + return true; +} + +// static +mojo_base::mojom::PlatformSharedMemoryRegion_Mode +EnumTraits<mojo_base::mojom::PlatformSharedMemoryRegion_Mode, + base::subtle::PlatformSharedMemoryRegion::Mode>:: + ToMojom(base::subtle::PlatformSharedMemoryRegion::Mode input) { + switch (input) { + case base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly: + return mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kReadOnly; + case base::subtle::PlatformSharedMemoryRegion::Mode::kWritable: + return mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kWritable; + case base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe: + return mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kUnsafe; + default: + NOTREACHED(); + return mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kUnsafe; + } +} + +// static +bool EnumTraits<mojo_base::mojom::PlatformSharedMemoryRegion_Mode, + base::subtle::PlatformSharedMemoryRegion::Mode>:: + FromMojom(mojo_base::mojom::PlatformSharedMemoryRegion_Mode input, + base::subtle::PlatformSharedMemoryRegion::Mode* output) { + switch (input) { + case mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kReadOnly: + *output = base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly; + break; + case mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kWritable: + *output = base::subtle::PlatformSharedMemoryRegion::Mode::kWritable; + break; + case mojo_base::mojom::PlatformSharedMemoryRegion_Mode::kUnsafe: + *output = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe; + break; + default: + NOTREACHED(); + return false; + } + return true; +} + +// static +base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle +StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion>:: + platform_handle(base::subtle::PlatformSharedMemoryRegion& region) { + return region.PassPlatformHandle(); +} + +// static +base::subtle::PlatformSharedMemoryRegion::Mode +StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion>:: + mode(const base::subtle::PlatformSharedMemoryRegion& region) { + return region.GetMode(); +} + +// static +uint64_t StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion>:: + size(const base::subtle::PlatformSharedMemoryRegion& region) { + return region.GetSize(); +} + +// static +base::UnguessableToken +StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion>:: + guid(const base::subtle::PlatformSharedMemoryRegion& region) { + return region.GetGUID(); +} + +// static +bool StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion>:: + Read(mojo_base::mojom::PlatformSharedMemoryRegionDataView data, + base::subtle::PlatformSharedMemoryRegion* out) { + if (!base::IsValueInRangeForNumericType<size_t>(data.size())) + return false; + size_t size = static_cast<size_t>(data.size()); + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle; + base::subtle::PlatformSharedMemoryRegion::Mode mode; + base::UnguessableToken guid; + if (!data.ReadPlatformHandle(&handle) || !data.ReadMode(&mode) || + !data.ReadGuid(&guid)) { + return false; + } + *out = base::subtle::PlatformSharedMemoryRegion::Take(std::move(handle), mode, + size, guid); + return out->IsValid(); +} + +// static +bool StructTraits<mojo_base::mojom::ReadOnlySharedMemoryRegionDataView, + base::ReadOnlySharedMemoryRegion>:: + IsNull(const base::ReadOnlySharedMemoryRegion& region) { + return !region.IsValid(); +} + +// static +void StructTraits<mojo_base::mojom::ReadOnlySharedMemoryRegionDataView, + base::ReadOnlySharedMemoryRegion>:: + SetToNull(base::ReadOnlySharedMemoryRegion* region) { + *region = base::ReadOnlySharedMemoryRegion(); +} + +// static +base::subtle::PlatformSharedMemoryRegion StructTraits< + mojo_base::mojom::ReadOnlySharedMemoryRegionDataView, + base::ReadOnlySharedMemoryRegion>::region(base::ReadOnlySharedMemoryRegion& + in_region) { + return base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization( + std::move(in_region)); +} + +// static +bool StructTraits<mojo_base::mojom::ReadOnlySharedMemoryRegionDataView, + base::ReadOnlySharedMemoryRegion>:: + Read(mojo_base::mojom::ReadOnlySharedMemoryRegionDataView data, + base::ReadOnlySharedMemoryRegion* out) { + base::subtle::PlatformSharedMemoryRegion region; + if (!data.ReadRegion(®ion)) + return false; + *out = base::ReadOnlySharedMemoryRegion::Deserialize(std::move(region)); + return out->IsValid(); +} + +// static +bool StructTraits<mojo_base::mojom::UnsafeSharedMemoryRegionDataView, + base::UnsafeSharedMemoryRegion>:: + IsNull(const base::UnsafeSharedMemoryRegion& region) { + return !region.IsValid(); +} + +// static +void StructTraits<mojo_base::mojom::UnsafeSharedMemoryRegionDataView, + base::UnsafeSharedMemoryRegion>:: + SetToNull(base::UnsafeSharedMemoryRegion* region) { + *region = base::UnsafeSharedMemoryRegion(); +} + +// static +base::subtle::PlatformSharedMemoryRegion StructTraits< + mojo_base::mojom::UnsafeSharedMemoryRegionDataView, + base::UnsafeSharedMemoryRegion>::region(base::UnsafeSharedMemoryRegion& + in_region) { + return base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( + std::move(in_region)); +} + +// static +bool StructTraits<mojo_base::mojom::UnsafeSharedMemoryRegionDataView, + base::UnsafeSharedMemoryRegion>:: + Read(mojo_base::mojom::UnsafeSharedMemoryRegionDataView data, + base::UnsafeSharedMemoryRegion* out) { + base::subtle::PlatformSharedMemoryRegion region; + if (!data.ReadRegion(®ion)) + return false; + *out = base::UnsafeSharedMemoryRegion::Deserialize(std::move(region)); + return out->IsValid(); +} + +// static +bool StructTraits<mojo_base::mojom::WritableSharedMemoryRegionDataView, + base::WritableSharedMemoryRegion>:: + IsNull(const base::WritableSharedMemoryRegion& region) { + return !region.IsValid(); +} + +// static +void StructTraits<mojo_base::mojom::WritableSharedMemoryRegionDataView, + base::WritableSharedMemoryRegion>:: + SetToNull(base::WritableSharedMemoryRegion* region) { + *region = base::WritableSharedMemoryRegion(); +} + +// static +base::subtle::PlatformSharedMemoryRegion StructTraits< + mojo_base::mojom::WritableSharedMemoryRegionDataView, + base::WritableSharedMemoryRegion>::region(base::WritableSharedMemoryRegion& + in_region) { + return base::WritableSharedMemoryRegion::TakeHandleForSerialization( + std::move(in_region)); +} + +// static +bool StructTraits<mojo_base::mojom::WritableSharedMemoryRegionDataView, + base::WritableSharedMemoryRegion>:: + Read(mojo_base::mojom::WritableSharedMemoryRegionDataView data, + base::WritableSharedMemoryRegion* out) { + base::subtle::PlatformSharedMemoryRegion region; + if (!data.ReadRegion(®ion)) + return false; + *out = base::WritableSharedMemoryRegion::Deserialize(std::move(region)); + return out->IsValid(); +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.h b/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.h new file mode 100644 index 00000000000..7fa57545049 --- /dev/null +++ b/chromium/mojo/public/cpp/base/shared_memory_mojom_traits.h @@ -0,0 +1,110 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_MOJOM_TRAITS_H_ + +#include <cstdint> + +#include "base/component_export.h" +#include "base/memory/platform_shared_memory_region.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/memory/writable_shared_memory_region.h" +#include "base/unguessable_token.h" +#include "build/build_config.h" +#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h" +#include "mojo/public/cpp/bindings/enum_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "mojo/public/cpp/system/handle.h" +#include "mojo/public/mojom/base/shared_memory.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) StructTraits< + mojo_base::mojom::PlatformSharedMemoryHandleDataView, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle> { + static mojo::ScopedHandle handle_value( + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle& handle); +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \ + (!defined(OS_MACOSX) || defined(OS_IOS)) + static mojo::ScopedHandle readonly_fd( + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle& handle); +#endif + + static bool Read( + mojo_base::mojom::PlatformSharedMemoryHandleDataView data, + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle* out); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + EnumTraits<mojo_base::mojom::PlatformSharedMemoryRegion_Mode, + base::subtle::PlatformSharedMemoryRegion::Mode> { + static mojo_base::mojom::PlatformSharedMemoryRegion_Mode ToMojom( + base::subtle::PlatformSharedMemoryRegion::Mode input); + + static bool FromMojom(mojo_base::mojom::PlatformSharedMemoryRegion_Mode input, + base::subtle::PlatformSharedMemoryRegion::Mode* output); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::PlatformSharedMemoryRegionDataView, + base::subtle::PlatformSharedMemoryRegion> { + static base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle + platform_handle(base::subtle::PlatformSharedMemoryRegion& region); + + static base::subtle::PlatformSharedMemoryRegion::Mode mode( + const base::subtle::PlatformSharedMemoryRegion& region); + + static uint64_t size(const base::subtle::PlatformSharedMemoryRegion& region); + + static base::UnguessableToken guid( + const base::subtle::PlatformSharedMemoryRegion& region); + + static bool Read(mojo_base::mojom::PlatformSharedMemoryRegionDataView data, + base::subtle::PlatformSharedMemoryRegion* out); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::ReadOnlySharedMemoryRegionDataView, + base::ReadOnlySharedMemoryRegion> { + static bool IsNull(const base::ReadOnlySharedMemoryRegion& region); + static void SetToNull(base::ReadOnlySharedMemoryRegion* region); + static base::subtle::PlatformSharedMemoryRegion region( + base::ReadOnlySharedMemoryRegion& in_region); + static bool Read(mojo_base::mojom::ReadOnlySharedMemoryRegionDataView data, + base::ReadOnlySharedMemoryRegion* out); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::UnsafeSharedMemoryRegionDataView, + base::UnsafeSharedMemoryRegion> { + static bool IsNull(const base::UnsafeSharedMemoryRegion& region); + static void SetToNull(base::UnsafeSharedMemoryRegion* region); + static base::subtle::PlatformSharedMemoryRegion region( + base::UnsafeSharedMemoryRegion& in_region); + static bool Read(mojo_base::mojom::UnsafeSharedMemoryRegionDataView data, + base::UnsafeSharedMemoryRegion* out); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::WritableSharedMemoryRegionDataView, + base::WritableSharedMemoryRegion> { + static bool IsNull(const base::WritableSharedMemoryRegion& region); + static void SetToNull(base::WritableSharedMemoryRegion* region); + static base::subtle::PlatformSharedMemoryRegion region( + base::WritableSharedMemoryRegion& in_region); + static bool Read(mojo_base::mojom::WritableSharedMemoryRegionDataView data, + base::WritableSharedMemoryRegion* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_SHARED_MEMORY_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/shared_memory_unittest.cc b/chromium/mojo/public/cpp/base/shared_memory_unittest.cc new file mode 100644 index 00000000000..7904f5d1894 --- /dev/null +++ b/chromium/mojo/public/cpp/base/shared_memory_unittest.cc @@ -0,0 +1,53 @@ +// Copyright 2018 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 <string> + +#include "mojo/public/cpp/base/shared_memory_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/shared_memory.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(SharedMemoryMojomTest, ReadOnly) { + auto region = base::ReadOnlySharedMemoryRegion::Create(64); + const std::string kTestData = "Hello, world!"; + memcpy(region.mapping.memory(), kTestData.data(), kTestData.size()); + + base::ReadOnlySharedMemoryRegion read_only_out; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize< + mojo_base::mojom::ReadOnlySharedMemoryRegion>(®ion.region, + &read_only_out)); + base::ReadOnlySharedMemoryMapping mapping = read_only_out.Map(); + EXPECT_EQ(0, memcmp(mapping.memory(), kTestData.data(), kTestData.size())); +} + +TEST(SharedMemoryMojomTest, Writable) { + auto region = base::WritableSharedMemoryRegion::Create(64); + auto mapping = region.Map(); + const std::string kTestData = "Hello, world!"; + memcpy(mapping.memory(), kTestData.data(), kTestData.size()); + + base::WritableSharedMemoryRegion writable_out; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize< + mojo_base::mojom::WritableSharedMemoryRegion>(®ion, + &writable_out)); + + mapping = writable_out.Map(); + EXPECT_EQ(0, memcmp(mapping.memory(), kTestData.data(), kTestData.size())); +} + +TEST(SharedMemoryMojomTest, Unsafe) { + auto region = base::UnsafeSharedMemoryRegion::Create(64); + auto mapping = region.Map(); + const std::string kTestData = "Hello, world!"; + memcpy(mapping.memory(), kTestData.data(), kTestData.size()); + + base::UnsafeSharedMemoryRegion unsafe_out; + EXPECT_TRUE( + mojo::test::SerializeAndDeserialize< + mojo_base::mojom::UnsafeSharedMemoryRegion>(®ion, &unsafe_out)); + + mapping = unsafe_out.Map(); + EXPECT_EQ(0, memcmp(mapping.memory(), kTestData.data(), kTestData.size())); +} diff --git a/chromium/mojo/public/cpp/base/text_direction.typemap b/chromium/mojo/public/cpp/base/text_direction.typemap new file mode 100644 index 00000000000..33a3d1159d8 --- /dev/null +++ b/chromium/mojo/public/cpp/base/text_direction.typemap @@ -0,0 +1,15 @@ +# Copyright 2017 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. + +mojom = "//mojo/public/mojom/base/text_direction.mojom" +public_headers = [ "//base/i18n/rtl.h" ] +traits_headers = [ "//mojo/public/cpp/base/text_direction_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/text_direction_mojom_traits.cc", + "//mojo/public/cpp/base/text_direction_mojom_traits.h", +] +public_deps = [ + "//base:i18n", +] +type_mappings = [ "mojo_base.mojom.TextDirection=base::i18n::TextDirection" ] diff --git a/chromium/mojo/public/cpp/base/text_direction_mojom_traits.cc b/chromium/mojo/public/cpp/base/text_direction_mojom_traits.cc new file mode 100644 index 00000000000..5e1f6eb8541 --- /dev/null +++ b/chromium/mojo/public/cpp/base/text_direction_mojom_traits.cc @@ -0,0 +1,43 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/text_direction_mojom_traits.h" + +namespace mojo { + +// static +mojo_base::mojom::TextDirection +EnumTraits<mojo_base::mojom::TextDirection, base::i18n::TextDirection>::ToMojom( + base::i18n::TextDirection text_direction) { + switch (text_direction) { + case base::i18n::UNKNOWN_DIRECTION: + return mojo_base::mojom::TextDirection::UNKNOWN_DIRECTION; + case base::i18n::RIGHT_TO_LEFT: + return mojo_base::mojom::TextDirection::RIGHT_TO_LEFT; + case base::i18n::LEFT_TO_RIGHT: + return mojo_base::mojom::TextDirection::LEFT_TO_RIGHT; + } + NOTREACHED(); + return mojo_base::mojom::TextDirection::UNKNOWN_DIRECTION; +} + +// static +bool EnumTraits<mojo_base::mojom::TextDirection, base::i18n::TextDirection>:: + FromMojom(mojo_base::mojom::TextDirection input, + base::i18n::TextDirection* out) { + switch (input) { + case mojo_base::mojom::TextDirection::UNKNOWN_DIRECTION: + *out = base::i18n::UNKNOWN_DIRECTION; + return true; + case mojo_base::mojom::TextDirection::RIGHT_TO_LEFT: + *out = base::i18n::RIGHT_TO_LEFT; + return true; + case mojo_base::mojom::TextDirection::LEFT_TO_RIGHT: + *out = base::i18n::LEFT_TO_RIGHT; + return true; + } + return false; +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/base/text_direction_mojom_traits.h b/chromium/mojo/public/cpp/base/text_direction_mojom_traits.h new file mode 100644 index 00000000000..f59d45ca4cb --- /dev/null +++ b/chromium/mojo/public/cpp/base/text_direction_mojom_traits.h @@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_TEXT_DIRECTION_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_TEXT_DIRECTION_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/i18n/rtl.h" +#include "mojo/public/mojom/base/text_direction.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + EnumTraits<mojo_base::mojom::TextDirection, base::i18n::TextDirection> { + static mojo_base::mojom::TextDirection ToMojom( + base::i18n::TextDirection text_direction); + static bool FromMojom(mojo_base::mojom::TextDirection input, + base::i18n::TextDirection* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_TEXT_DIRECTION_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/text_direction_unittest.cc b/chromium/mojo/public/cpp/base/text_direction_unittest.cc new file mode 100644 index 00000000000..02085fcfdc0 --- /dev/null +++ b/chromium/mojo/public/cpp/base/text_direction_unittest.cc @@ -0,0 +1,31 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/text_direction_mojom_traits.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace text_direction_unittest { + +TEST(TextDirectionTest, TextDirection) { + static constexpr base::i18n::TextDirection kTestDirections[] = { + base::i18n::LEFT_TO_RIGHT, base::i18n::RIGHT_TO_LEFT, + base::i18n::UNKNOWN_DIRECTION}; + + for (auto direction_in : kTestDirections) { + base::i18n::TextDirection direction_out; + + mojo_base::mojom::TextDirection serialized_direction = + mojo::EnumTraits<mojo_base::mojom::TextDirection, + base::i18n::TextDirection>::ToMojom(direction_in); + ASSERT_TRUE((mojo::EnumTraits< + mojo_base::mojom::TextDirection, + base::i18n::TextDirection>::FromMojom(serialized_direction, + &direction_out))); + EXPECT_EQ(direction_in, direction_out); + } +} + +} // namespace text_direction_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/thread_priority.typemap b/chromium/mojo/public/cpp/base/thread_priority.typemap new file mode 100644 index 00000000000..319818f4cac --- /dev/null +++ b/chromium/mojo/public/cpp/base/thread_priority.typemap @@ -0,0 +1,13 @@ +# Copyright 2017 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. + +mojom = "//mojo/public/mojom/base/thread_priority.mojom" +public_headers = [ "//base/threading/platform_thread.h" ] +traits_headers = [ "//mojo/public/cpp/base/thread_priority_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/thread_priority_mojom_traits.cc", + "//mojo/public/cpp/base/thread_priority_mojom_traits.h", +] + +type_mappings = [ "mojo_base.mojom.ThreadPriority=base::ThreadPriority" ] diff --git a/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.cc b/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.cc new file mode 100644 index 00000000000..f8b88cd8095 --- /dev/null +++ b/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.cc @@ -0,0 +1,48 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/thread_priority_mojom_traits.h" + +namespace mojo { + +// static +mojo_base::mojom::ThreadPriority +EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority>::ToMojom( + base::ThreadPriority thread_priority) { + switch (thread_priority) { + case base::ThreadPriority::BACKGROUND: + return mojo_base::mojom::ThreadPriority::BACKGROUND; + case base::ThreadPriority::NORMAL: + return mojo_base::mojom::ThreadPriority::NORMAL; + case base::ThreadPriority::DISPLAY: + return mojo_base::mojom::ThreadPriority::DISPLAY; + case base::ThreadPriority::REALTIME_AUDIO: + return mojo_base::mojom::ThreadPriority::REALTIME_AUDIO; + } + NOTREACHED(); + return mojo_base::mojom::ThreadPriority::BACKGROUND; +} + +// static +bool EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority>:: + FromMojom(mojo_base::mojom::ThreadPriority input, + base::ThreadPriority* out) { + switch (input) { + case mojo_base::mojom::ThreadPriority::BACKGROUND: + *out = base::ThreadPriority::BACKGROUND; + return true; + case mojo_base::mojom::ThreadPriority::NORMAL: + *out = base::ThreadPriority::NORMAL; + return true; + case mojo_base::mojom::ThreadPriority::DISPLAY: + *out = base::ThreadPriority::DISPLAY; + return true; + case mojo_base::mojom::ThreadPriority::REALTIME_AUDIO: + *out = base::ThreadPriority::REALTIME_AUDIO; + return true; + } + return false; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.h b/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.h new file mode 100644 index 00000000000..7f58e03f280 --- /dev/null +++ b/chromium/mojo/public/cpp/base/thread_priority_mojom_traits.h @@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "mojo/public/mojom/base/thread_priority.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority> { + static mojo_base::mojom::ThreadPriority ToMojom( + base::ThreadPriority thread_priority); + static bool FromMojom(mojo_base::mojom::ThreadPriority input, + base::ThreadPriority* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/thread_priority_unittest.cc b/chromium/mojo/public/cpp/base/thread_priority_unittest.cc new file mode 100644 index 00000000000..115d757ad67 --- /dev/null +++ b/chromium/mojo/public/cpp/base/thread_priority_unittest.cc @@ -0,0 +1,31 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/thread_priority_mojom_traits.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace thread_priority_unittest { + +TEST(ThreadPriorityTest, ThreadPriority) { + static constexpr base::ThreadPriority kTestPriorities[] = { + base::ThreadPriority::BACKGROUND, base::ThreadPriority::NORMAL, + base::ThreadPriority::DISPLAY, base::ThreadPriority::REALTIME_AUDIO}; + + for (auto priority_in : kTestPriorities) { + base::ThreadPriority priority_out; + + mojo_base::mojom::ThreadPriority serialized_priority = + mojo::EnumTraits<mojo_base::mojom::ThreadPriority, + base::ThreadPriority>::ToMojom(priority_in); + ASSERT_TRUE( + (mojo::EnumTraits<mojo_base::mojom::ThreadPriority, + base::ThreadPriority>::FromMojom(serialized_priority, + &priority_out))); + EXPECT_EQ(priority_in, priority_out); + } +} + +} // namespace thread_priority_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/time.typemap b/chromium/mojo/public/cpp/base/time.typemap new file mode 100644 index 00000000000..b3b2e8b0658 --- /dev/null +++ b/chromium/mojo/public/cpp/base/time.typemap @@ -0,0 +1,20 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//mojo/public/mojom/base/time.mojom" +public_headers = [ "//base/time/time.h" ] +traits_headers = [ "//mojo/public/cpp/base/time_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/time_mojom_traits.cc", + "//mojo/public/cpp/base/time_mojom_traits.h", +] +public_deps = [ + "//base", +] + +type_mappings = [ + "mojo_base.mojom.Time=base::Time[copyable_pass_by_value]", + "mojo_base.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]", + "mojo_base.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]", +] diff --git a/chromium/mojo/public/cpp/base/time_mojom_traits.cc b/chromium/mojo/public/cpp/base/time_mojom_traits.cc new file mode 100644 index 00000000000..1fc25d81440 --- /dev/null +++ b/chromium/mojo/public/cpp/base/time_mojom_traits.cc @@ -0,0 +1,49 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/time_mojom_traits.h" + +namespace mojo { + +int64_t StructTraits<mojo_base::mojom::TimeDataView, + base::Time>::internal_value(const base::Time& time) { + return time.since_origin().InMicroseconds(); +} + +bool StructTraits<mojo_base::mojom::TimeDataView, base::Time>::Read( + mojo_base::mojom::TimeDataView data, + base::Time* time) { + *time = + base::Time() + base::TimeDelta::FromMicroseconds(data.internal_value()); + return true; +} + +int64_t +StructTraits<mojo_base::mojom::TimeDeltaDataView, + base::TimeDelta>::microseconds(const base::TimeDelta& delta) { + return delta.InMicroseconds(); +} + +bool StructTraits<mojo_base::mojom::TimeDeltaDataView, base::TimeDelta>::Read( + mojo_base::mojom::TimeDeltaDataView data, + base::TimeDelta* delta) { + *delta = base::TimeDelta::FromMicroseconds(data.microseconds()); + return true; +} + +int64_t +StructTraits<mojo_base::mojom::TimeTicksDataView, + base::TimeTicks>::internal_value(const base::TimeTicks& time) { + return time.since_origin().InMicroseconds(); +} + +bool StructTraits<mojo_base::mojom::TimeTicksDataView, base::TimeTicks>::Read( + mojo_base::mojom::TimeTicksDataView data, + base::TimeTicks* time) { + *time = base::TimeTicks() + + base::TimeDelta::FromMicroseconds(data.internal_value()); + return true; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/time_mojom_traits.h b/chromium/mojo/public/cpp/base/time_mojom_traits.h new file mode 100644 index 00000000000..db54476861f --- /dev/null +++ b/chromium/mojo/public/cpp/base/time_mojom_traits.h @@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/time/time.h" +#include "mojo/public/mojom/base/time.mojom-shared.h" + +namespace mojo { + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::TimeDataView, base::Time> { + static int64_t internal_value(const base::Time& time); + + static bool Read(mojo_base::mojom::TimeDataView data, base::Time* time); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::TimeDeltaDataView, base::TimeDelta> { + static int64_t microseconds(const base::TimeDelta& delta); + + static bool Read(mojo_base::mojom::TimeDeltaDataView data, + base::TimeDelta* delta); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::TimeTicksDataView, base::TimeTicks> { + static int64_t internal_value(const base::TimeTicks& time); + + static bool Read(mojo_base::mojom::TimeTicksDataView data, + base::TimeTicks* time); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_TIME_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/time_unittest.cc b/chromium/mojo/public/cpp/base/time_unittest.cc new file mode 100644 index 00000000000..9ab3910723b --- /dev/null +++ b/chromium/mojo/public/cpp/base/time_unittest.cc @@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/time.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace time_unittest { + +TEST(TimeTest, Time) { + base::Time in = base::Time::Now(); + base::Time out; + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Time>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(TimeTest, TimeDelta) { + base::TimeDelta in = base::TimeDelta::FromDays(123); + base::TimeDelta out; + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::TimeDelta>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(TimeTest, TimeTicks) { + base::TimeTicks in = base::TimeTicks::Now(); + base::TimeTicks out; + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::TimeTicks>(&in, &out)); + EXPECT_EQ(in, out); +} + +} // namespace time_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/typemaps.gni b/chromium/mojo/public/cpp/base/typemaps.gni index 83552ae5531..668dc8edb92 100644 --- a/chromium/mojo/public/cpp/base/typemaps.gni +++ b/chromium/mojo/public/cpp/base/typemaps.gni @@ -5,6 +5,20 @@ typemaps = [ "//mojo/public/cpp/base/big_buffer.typemap", "//mojo/public/cpp/base/big_string.typemap", + "//mojo/public/cpp/base/file_error.typemap", + "//mojo/public/cpp/base/file_info.typemap", + "//mojo/public/cpp/base/file_path.typemap", + "//mojo/public/cpp/base/file.typemap", + "//mojo/public/cpp/base/read_only_buffer.typemap", + "//mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap", + "//mojo/public/cpp/base/process_id.typemap", "//mojo/public/cpp/base/ref_counted_memory.typemap", + "//mojo/public/cpp/base/shared_memory.typemap", "//mojo/public/cpp/base/string16.typemap", + "//mojo/public/cpp/base/logfont_win.typemap", + "//mojo/public/cpp/base/text_direction.typemap", + "//mojo/public/cpp/base/thread_priority.typemap", + "//mojo/public/cpp/base/time.typemap", + "//mojo/public/cpp/base/unguessable_token.typemap", + "//mojo/public/cpp/base/values.typemap", ] diff --git a/chromium/mojo/public/cpp/base/unguessable_token.typemap b/chromium/mojo/public/cpp/base/unguessable_token.typemap new file mode 100644 index 00000000000..056f14612c0 --- /dev/null +++ b/chromium/mojo/public/cpp/base/unguessable_token.typemap @@ -0,0 +1,13 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//mojo/public/mojom/base/unguessable_token.mojom" +public_headers = [ "//base/unguessable_token.h" ] +traits_headers = [ "//mojo/public/cpp/base/unguessable_token_mojom_traits.h" ] +sources = [ + "//mojo/public/cpp/base/unguessable_token_mojom_traits.cc", + "//mojo/public/cpp/base/unguessable_token_mojom_traits.h", +] + +type_mappings = [ "mojo_base.mojom.UnguessableToken=base::UnguessableToken" ] diff --git a/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.cc b/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.cc new file mode 100644 index 00000000000..153d0a46b1e --- /dev/null +++ b/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.cc @@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits<mojo_base::mojom::UnguessableTokenDataView, + base::UnguessableToken>:: + Read(mojo_base::mojom::UnguessableTokenDataView data, + base::UnguessableToken* out) { + uint64_t high = data.high(); + uint64_t low = data.low(); + + // Receiving a zeroed UnguessableToken is a security issue. + if (high == 0 && low == 0) + return false; + + *out = base::UnguessableToken::Deserialize(high, low); + return true; +} + +} // namespace mojo
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.h b/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.h new file mode 100644 index 00000000000..b23bd70cc02 --- /dev/null +++ b/chromium/mojo/public/cpp/base/unguessable_token_mojom_traits.h @@ -0,0 +1,37 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_ + +#include "base/component_export.h" +#include "base/unguessable_token.h" +#include "mojo/public/mojom/base/unguessable_token.mojom-shared.h" + +namespace mojo { + +// If base::UnguessableToken is no longer 128 bits, the logic below and the +// mojom::UnguessableToken type should be updated. +static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t), + "base::UnguessableToken should be of size 2 * sizeof(uint64_t)."); + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_MOJOM) + StructTraits<mojo_base::mojom::UnguessableTokenDataView, + base::UnguessableToken> { + static uint64_t high(const base::UnguessableToken& token) { + return token.GetHighForSerialization(); + } + + static uint64_t low(const base::UnguessableToken& token) { + return token.GetLowForSerialization(); + } + + static bool Read(mojo_base::mojom::UnguessableTokenDataView data, + base::UnguessableToken* out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/unguessable_token_unittest.cc b/chromium/mojo/public/cpp/base/unguessable_token_unittest.cc new file mode 100644 index 00000000000..c752178c2b1 --- /dev/null +++ b/chromium/mojo/public/cpp/base/unguessable_token_unittest.cc @@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/unguessable_token.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { +namespace unguessable_token_unittest { + +TEST(UnguessableTokenTest, UnguessableToken) { + base::UnguessableToken in = base::UnguessableToken::Create(); + base::UnguessableToken out; + + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::UnguessableToken>(&in, &out)); + EXPECT_EQ(in, out); +} + +} // namespace unguessable_token_unittest +} // namespace mojo_base
\ No newline at end of file diff --git a/chromium/mojo/public/cpp/base/values.typemap b/chromium/mojo/public/cpp/base/values.typemap new file mode 100644 index 00000000000..8dfaa675389 --- /dev/null +++ b/chromium/mojo/public/cpp/base/values.typemap @@ -0,0 +1,16 @@ +# Copyright 2018 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. + +mojom = "//mojo/public/mojom/base/values.mojom" +public_headers = [ "//base/values.h" ] +traits_headers = [ "//mojo/public/cpp/base/values_mojom_traits.h" ] +public_deps = [ + "//base", + "//mojo/public/cpp/base:shared_typemap_traits", +] +type_mappings = [ + "mojo_base.mojom.Value=base::Value[move_only]", + "mojo_base.mojom.DictionaryValue=base::Value[move_only]", + "mojo_base.mojom.ListValue=base::Value[move_only]", +] diff --git a/chromium/mojo/public/cpp/base/values_mojom_traits.cc b/chromium/mojo/public/cpp/base/values_mojom_traits.cc new file mode 100644 index 00000000000..25930668551 --- /dev/null +++ b/chromium/mojo/public/cpp/base/values_mojom_traits.cc @@ -0,0 +1,94 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/base/values_mojom_traits.h" + +#include <memory> +#include <utility> + +#include "base/strings/string_piece.h" + +namespace mojo { + +bool StructTraits<mojo_base::mojom::DictionaryValueDataView, base::Value>::Read( + mojo_base::mojom::DictionaryValueDataView data, + base::Value* value_out) { + mojo::MapDataView<mojo::StringDataView, mojo_base::mojom::ValueDataView> view; + data.GetStorageDataView(&view); + std::vector<base::Value::DictStorage::value_type> dict_storage; + dict_storage.reserve(view.size()); + for (size_t i = 0; i < view.size(); ++i) { + base::StringPiece key; + auto value = std::make_unique<base::Value>(); + if (!view.keys().Read(i, &key) || !view.values().Read(i, value.get())) + return false; + dict_storage.emplace_back(key.as_string(), std::move(value)); + } + *value_out = base::Value(base::Value::DictStorage(std::move(dict_storage), + base::KEEP_LAST_OF_DUPES)); + return true; +} + +bool StructTraits<mojo_base::mojom::ListValueDataView, base::Value>::Read( + mojo_base::mojom::ListValueDataView data, + base::Value* value_out) { + mojo::ArrayDataView<mojo_base::mojom::ValueDataView> view; + data.GetStorageDataView(&view); + base::Value::ListStorage list_storage(view.size()); + for (size_t i = 0; i < view.size(); ++i) { + if (!view.Read(i, &list_storage[i])) + return false; + } + *value_out = base::Value(std::move(list_storage)); + return true; +} + +bool UnionTraits<mojo_base::mojom::ValueDataView, base::Value>::Read( + mojo_base::mojom::ValueDataView data, + base::Value* value_out) { + switch (data.tag()) { + case mojo_base::mojom::ValueDataView::Tag::NULL_VALUE: { + *value_out = base::Value(); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::BOOL_VALUE: { + *value_out = base::Value(data.bool_value()); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::INT_VALUE: { + *value_out = base::Value(data.int_value()); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::DOUBLE_VALUE: { + *value_out = base::Value(data.double_value()); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::STRING_VALUE: { + base::StringPiece string_piece; + if (!data.ReadStringValue(&string_piece)) + return false; + *value_out = base::Value(string_piece); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::BINARY_VALUE: { + mojo::ArrayDataView<uint8_t> binary_data_view; + data.GetBinaryValueDataView(&binary_data_view); + const char* data_pointer = + reinterpret_cast<const char*>(binary_data_view.data()); + base::Value::BlobStorage blob_storage( + data_pointer, data_pointer + binary_data_view.size()); + *value_out = base::Value(std::move(blob_storage)); + return true; + } + case mojo_base::mojom::ValueDataView::Tag::DICTIONARY_VALUE: { + return data.ReadDictionaryValue(value_out); + } + case mojo_base::mojom::ValueDataView::Tag::LIST_VALUE: { + return data.ReadListValue(value_out); + } + } + return false; +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/base/values_mojom_traits.h b/chromium/mojo/public/cpp/base/values_mojom_traits.h new file mode 100644 index 00000000000..ee1dbee510c --- /dev/null +++ b/chromium/mojo/public/cpp/base/values_mojom_traits.h @@ -0,0 +1,130 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BASE_VALUES_MOJOM_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BASE_VALUES_MOJOM_TRAITS_H_ + +#include <vector> + +#include "base/component_export.h" +#include "base/values.h" +#include "mojo/public/cpp/bindings/map_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "mojo/public/cpp/bindings/union_traits.h" +#include "mojo/public/mojom/base/values.mojom-shared.h" + +namespace mojo { + +template <> +struct MapTraits<base::Value> { + using Key = std::string; + using Value = base::Value; + using Iterator = base::Value::const_dict_iterator_proxy::const_iterator; + + static size_t GetSize(const base::Value& input) { + DCHECK(input.is_dict()); + return static_cast<const base::DictionaryValue&>(input).size(); + } + + static Iterator GetBegin(const base::Value& input) { + DCHECK(input.is_dict()); + return input.DictItems().cbegin(); + } + + static void AdvanceIterator(Iterator& iterator) { ++iterator; } + + static const Key& GetKey(const Iterator& iterator) { return iterator->first; } + + static const Value& GetValue(const Iterator& iterator) { + return iterator->second; + } +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS) + StructTraits<mojo_base::mojom::DictionaryValueDataView, base::Value> { + static const base::Value& storage(const base::Value& value) { + DCHECK(value.is_dict()); + return value; + } + + static bool Read(mojo_base::mojom::DictionaryValueDataView data, + base::Value* value); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS) + StructTraits<mojo_base::mojom::ListValueDataView, base::Value> { + static const base::Value::ListStorage& storage(const base::Value& value) { + DCHECK(value.is_list()); + return value.GetList(); + } + + static bool Read(mojo_base::mojom::ListValueDataView data, + base::Value* value); +}; + +template <> +struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS) + UnionTraits<mojo_base::mojom::ValueDataView, base::Value> { + static mojo_base::mojom::ValueDataView::Tag GetTag(const base::Value& data) { + switch (data.type()) { + case base::Value::Type::NONE: + return mojo_base::mojom::ValueDataView::Tag::NULL_VALUE; + case base::Value::Type::BOOLEAN: + return mojo_base::mojom::ValueDataView::Tag::BOOL_VALUE; + case base::Value::Type::INTEGER: + return mojo_base::mojom::ValueDataView::Tag::INT_VALUE; + case base::Value::Type::DOUBLE: + return mojo_base::mojom::ValueDataView::Tag::DOUBLE_VALUE; + case base::Value::Type::STRING: + return mojo_base::mojom::ValueDataView::Tag::STRING_VALUE; + case base::Value::Type::BINARY: + return mojo_base::mojom::ValueDataView::Tag::BINARY_VALUE; + case base::Value::Type::DICTIONARY: + return mojo_base::mojom::ValueDataView::Tag::DICTIONARY_VALUE; + case base::Value::Type::LIST: + return mojo_base::mojom::ValueDataView::Tag::LIST_VALUE; + } + NOTREACHED(); + return mojo_base::mojom::ValueDataView::Tag::NULL_VALUE; + } + + static uint8_t null_value(const base::Value& value) { return 0; } + + static bool bool_value(const base::Value& value) { return value.GetBool(); } + + static int32_t int_value(const base::Value& value) { return value.GetInt(); } + + static double double_value(const base::Value& value) { + return value.GetDouble(); + } + + static base::StringPiece string_value(const base::Value& value) { + return value.GetString(); + } + + static base::span<const uint8_t> binary_value(const base::Value& value) { + // TODO(dcheng): Change base::Value::BlobStorage to uint8_t. + return base::make_span( + reinterpret_cast<const uint8_t*>(value.GetBlob().data()), + value.GetBlob().size()); + } + + static const base::Value& list_value(const base::Value& value) { + DCHECK(value.is_list()); + return value; + } + static const base::Value& dictionary_value(const base::Value& value) { + DCHECK(value.is_dict()); + return value; + } + + static bool Read(mojo_base::mojom::ValueDataView view, + base::Value* value_out); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BASE_VALUES_MOJOM_TRAITS_H_ diff --git a/chromium/mojo/public/cpp/base/values_unittest.cc b/chromium/mojo/public/cpp/base/values_unittest.cc new file mode 100644 index 00000000000..169572bb342 --- /dev/null +++ b/chromium/mojo/public/cpp/base/values_unittest.cc @@ -0,0 +1,160 @@ +// Copyright 2018 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 <string> +#include <utility> + +#include "base/test/gtest_util.h" +#include "base/values.h" +#include "mojo/public/cpp/base/values_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "mojo/public/mojom/base/values.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo_base { + +TEST(ValuesStructTraitsTest, NullValue) { + base::Value in; + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(ValuesStructTraitsTest, BoolValue) { + static constexpr bool kTestCases[] = {true, false}; + for (auto& test_case : kTestCases) { + base::Value in(test_case); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + } +} + +TEST(ValuesStructTraitsTest, IntValue) { + static constexpr int kTestCases[] = {0, -1, 1, + std::numeric_limits<int>::min(), + std::numeric_limits<int>::max()}; + for (auto& test_case : kTestCases) { + base::Value in(test_case); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + } +} + +TEST(ValuesStructTraitsTest, DoubleValue) { + static constexpr double kTestCases[] = {-0.0, + +0.0, + -1.0, + +1.0, + std::numeric_limits<double>::min(), + std::numeric_limits<double>::max()}; + for (auto& test_case : kTestCases) { + base::Value in(test_case); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + } +} + +TEST(ValuesStructTraitsTest, StringValue) { + static constexpr const char* kTestCases[] = { + "", "ascii", + // 🎆: Unicode FIREWORKS + "\xf0\x9f\x8e\x86", + }; + for (auto* test_case : kTestCases) { + base::Value in(test_case); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + } +} + +TEST(ValuesStructTraitsTest, BinaryValue) { + std::vector<char> kBinaryData = {'\x00', '\x80', '\xff', '\x7f', '\x01'}; + base::Value in(std::move(kBinaryData)); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(ValuesStructTraitsTest, DictionaryValue) { + // Note: here and below, it would be nice to use an initializer list, but + // move-only types and initializer lists don't mix. Initializer lists can't be + // modified: thus it's not possible to move. + std::vector<base::Value::DictStorage::value_type> storage; + storage.emplace_back("null", std::make_unique<base::Value>()); + storage.emplace_back("bool", std::make_unique<base::Value>(false)); + storage.emplace_back("int", std::make_unique<base::Value>(0)); + storage.emplace_back("double", std::make_unique<base::Value>(0.0)); + storage.emplace_back("string", std::make_unique<base::Value>("0")); + storage.emplace_back( + "binary", std::make_unique<base::Value>(base::Value::BlobStorage({0}))); + storage.emplace_back( + "dictionary", std::make_unique<base::Value>(base::Value::DictStorage())); + storage.emplace_back( + "list", std::make_unique<base::Value>(base::Value::ListStorage())); + + base::Value in( + base::Value::DictStorage(std::move(storage), base::KEEP_LAST_OF_DUPES)); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::DictionaryValue>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(ValuesStructTraitsTest, SerializeInvalidDictionaryValue) { + base::Value in; + ASSERT_FALSE(in.is_dict()); + + base::Value out; + EXPECT_DCHECK_DEATH( + mojo::test::SerializeAndDeserialize<mojom::DictionaryValue>(&in, &out)); +} + +TEST(ValuesStructTraitsTest, ListValue) { + base::Value::ListStorage storage; + storage.emplace_back(); + storage.emplace_back(false); + storage.emplace_back(0); + storage.emplace_back(0.0); + storage.emplace_back("0"); + storage.emplace_back(base::Value::BlobStorage({0})); + storage.emplace_back(base::Value::DictStorage()); + storage.emplace_back(base::Value::ListStorage()); + base::Value in(std::move(storage)); + base::Value out; + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); + EXPECT_EQ(in, out); + + ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::ListValue>(&in, &out)); + EXPECT_EQ(in, out); +} + +TEST(ValuesStructTraitsTest, SerializeInvalidListValue) { + base::Value in; + ASSERT_FALSE(in.is_dict()); + + base::Value out; + EXPECT_DCHECK_DEATH( + mojo::test::SerializeAndDeserialize<mojom::ListValue>(&in, &out)); +} + +// A deeply nested base::Value should trigger a deserialization error. +TEST(ValuesStructTraitsTest, DeeplyNestedValue) { + base::Value in; + for (int i = 0; i < 100; ++i) { + base::Value::ListStorage storage; + storage.emplace_back(std::move(in)); + in = base::Value(std::move(storage)); + } + base::Value out; + ASSERT_FALSE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); +} + +} // namespace mojo_base diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn index a8f9c48d6c4..30bf196db3d 100644 --- a/chromium/mojo/public/cpp/bindings/BUILD.gn +++ b/chromium/mojo/public/cpp/bindings/BUILD.gn @@ -7,8 +7,8 @@ declare_args() { enable_mojo_tracing = false } -buildflag_header("mojo_features") { - header = "mojo_features.h" +buildflag_header("mojo_buildflags") { + header = "mojo_buildflags.h" flags = [ "MOJO_TRACE_ENABLED=$enable_mojo_tracing" ] } @@ -56,7 +56,6 @@ component("bindings_base") { "lib/serialization_forward.h", "lib/serialization_util.h", "lib/string_serialization.h", - "lib/string_traits_string16.cc", "lib/template_util.h", "lib/unserialized_message_context.cc", "lib/unserialized_message_context.h", @@ -77,7 +76,6 @@ component("bindings_base") { "string_data_view.h", "string_traits.h", "string_traits_stl.h", - "string_traits_string16.h", "string_traits_string_piece.h", "struct_ptr.h", "struct_traits.h", @@ -88,6 +86,7 @@ component("bindings_base") { defines = [ "IS_MOJO_CPP_BINDINGS_BASE_IMPL" ] public_deps = [ + ":mojo_buildflags", "//base", "//mojo/public/cpp/system", ] @@ -102,6 +101,7 @@ component("bindings") { "associated_interface_request.h", "binding.h", "binding_set.h", + "bindings_export.h", "callback_helpers.h", "connection_error_callback.h", "connector.h", @@ -136,6 +136,7 @@ component("bindings") { "lib/native_struct_serialization.h", "lib/pipe_control_message_handler.cc", "lib/pipe_control_message_proxy.cc", + "lib/sequence_local_sync_event_watcher.cc", "lib/sync_call_restrictions.cc", "lib/sync_event_watcher.cc", "lib/sync_handle_registry.cc", @@ -147,6 +148,7 @@ component("bindings") { "pipe_control_message_handler_delegate.h", "pipe_control_message_proxy.h", "raw_ptr_impl_ref_traits.h", + "sequence_local_sync_event_watcher.h", "strong_associated_binding.h", "strong_binding.h", "strong_binding_set.h", @@ -160,7 +162,6 @@ component("bindings") { public_deps = [ ":bindings_base", - ":mojo_features", ":struct_traits", "//base", "//ipc:message_support", @@ -203,10 +204,10 @@ if (!is_ios) { public_deps = [ ":bindings", - "//third_party/WebKit/Source/platform:platform_export", - "//third_party/WebKit/Source/platform/wtf", + "//third_party/blink/renderer/platform:platform_export", + "//third_party/blink/renderer/platform/wtf", ] - public_configs = [ "//third_party/WebKit/Source:config" ] + public_configs = [ "//third_party/blink/renderer:config" ] } } diff --git a/chromium/mojo/public/cpp/bindings/DEPS b/chromium/mojo/public/cpp/bindings/DEPS index f45f4e1acb5..4633930f94d 100644 --- a/chromium/mojo/public/cpp/bindings/DEPS +++ b/chromium/mojo/public/cpp/bindings/DEPS @@ -1,3 +1,3 @@ include_rules = [ - "+third_party/WebKit/Source/platform/wtf", + "+third_party/blink/renderer/platform/wtf", ] diff --git a/chromium/mojo/public/cpp/bindings/README.md b/chromium/mojo/public/cpp/bindings/README.md index 49610daa382..823feb70ee4 100644 --- a/chromium/mojo/public/cpp/bindings/README.md +++ b/chromium/mojo/public/cpp/bindings/README.md @@ -501,7 +501,10 @@ connection error and break out of the run loop. [Mojom enums](/mojo/public/tools/bindings#Enumeration-Types) translate directly to equivalent strongly-typed C++11 enum classes with `int32_t` as the underlying -type. The typename and value names are identical between Mojom and C++. +type. The typename and value names are identical between Mojom and C++. Mojo +also always defines a special enumerator `kMaxValue` that shares the value of +the highest enumerator: this makes it easy to record Mojo enums in histograms +and interoperate with legacy IPC. For example, consider the following Mojom definition: @@ -525,6 +528,7 @@ enum class Department : int32_t { kEngineering, kMarketing, kSales, + kMaxValue = kSales, }; } // namespace mojom diff --git a/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h b/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h index 0b59a704e0e..83d2ba3f511 100644 --- a/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h +++ b/chromium/mojo/public/cpp/bindings/array_traits_wtf_vector.h @@ -6,7 +6,7 @@ #define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ #include "mojo/public/cpp/bindings/array_traits.h" -#include "third_party/WebKit/Source/platform/wtf/Vector.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h index e9dcb0747d1..e723f80c009 100644 --- a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h +++ b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h @@ -42,6 +42,8 @@ class AssociatedInterfacePtr { internal_state_.Swap(&other.internal_state_); } + explicit AssociatedInterfacePtr(PtrInfoType&& info) { Bind(std::move(info)); } + AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { reset(); internal_state_.Swap(&other.internal_state_); diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr.h b/chromium/mojo/public/cpp/bindings/interface_ptr.h index 45b104099b4..7731cfdc7fe 100644 --- a/chromium/mojo/public/cpp/bindings/interface_ptr.h +++ b/chromium/mojo/public/cpp/bindings/interface_ptr.h @@ -145,6 +145,9 @@ class InterfacePtr { return internal_state_.HasAssociatedInterfaces(); } + // Returns true if bound and awaiting a response to a message. + bool IsExpectingResponse() { return internal_state_.has_pending_callbacks(); } + // Indicates whether the message pipe has encountered an error. If true, // method calls made on this interface will be dropped (and may already have // been dropped). diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr_set.h b/chromium/mojo/public/cpp/bindings/interface_ptr_set.h index 02bfc4bebb4..185cbffcdcd 100644 --- a/chromium/mojo/public/cpp/bindings/interface_ptr_set.h +++ b/chromium/mojo/public/cpp/bindings/interface_ptr_set.h @@ -5,15 +5,19 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ +#include <map> #include <utility> -#include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/stl_util.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" #include "mojo/public/cpp/bindings/interface_ptr.h" namespace mojo { + +using InterfacePtrSetElementId = size_t; + namespace internal { // TODO(blundell): This class should be rewritten to be structured @@ -26,25 +30,28 @@ class PtrSet { PtrSet() {} ~PtrSet() { CloseAll(); } - void AddPtr(Ptr<Interface> ptr) { + InterfacePtrSetElementId AddPtr(Ptr<Interface> ptr) { + InterfacePtrSetElementId id = next_ptr_id_++; auto weak_interface_ptr = new Element(std::move(ptr)); - ptrs_.push_back(weak_interface_ptr->GetWeakPtr()); + ptrs_.emplace(std::piecewise_construct, std::forward_as_tuple(id), + std::forward_as_tuple(weak_interface_ptr->GetWeakPtr())); ClearNullPtrs(); + return id; } template <typename FunctionType> void ForAllPtrs(FunctionType function) { for (const auto& it : ptrs_) { - if (it) - function(it->get()); + if (it.second) + function(it.second->get()); } ClearNullPtrs(); } void CloseAll() { for (const auto& it : ptrs_) { - if (it) - it->Close(); + if (it.second) + it.second->Close(); } ptrs_.clear(); } @@ -55,12 +62,27 @@ class PtrSet { // blocking operation, may be very slow as the number of pointers increases. void FlushForTesting() { for (const auto& it : ptrs_) { - if (it) - it->FlushForTesting(); + if (it.second) + it.second->FlushForTesting(); } ClearNullPtrs(); } + bool HasPtr(InterfacePtrSetElementId id) { + return ptrs_.find(id) != ptrs_.end(); + } + + Ptr<Interface> RemovePtr(InterfacePtrSetElementId id) { + auto it = ptrs_.find(id); + if (it == ptrs_.end()) + return Ptr<Interface>(); + Ptr<Interface> ptr; + if (it->second) + ptr = it->second->Take(); + ptrs_.erase(it); + return ptr; + } + private: class Element { public: @@ -81,6 +103,8 @@ class PtrSet { Interface* get() { return ptr_.get(); } + Ptr<Interface> Take() { return std::move(ptr_); } + base::WeakPtr<Element> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -97,14 +121,11 @@ class PtrSet { }; void ClearNullPtrs() { - ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(), - [](const base::WeakPtr<Element>& p) { - return p.get() == nullptr; - }), - ptrs_.end()); + base::EraseIf(ptrs_, [](const auto& pair) { return !(pair.second); }); } - std::vector<base::WeakPtr<Element>> ptrs_; + InterfacePtrSetElementId next_ptr_id_ = 0; + std::map<InterfacePtrSetElementId, base::WeakPtr<Element>> ptrs_; }; } // namespace internal diff --git a/chromium/mojo/public/cpp/bindings/interface_request.h b/chromium/mojo/public/cpp/bindings/interface_request.h index 1007cb0b8c8..ccfdb3716e5 100644 --- a/chromium/mojo/public/cpp/bindings/interface_request.h +++ b/chromium/mojo/public/cpp/bindings/interface_request.h @@ -54,7 +54,7 @@ class InterfaceRequest { // Indicates whether the request currently contains a valid message pipe. bool is_pending() const { return handle_.is_valid(); } - explicit operator bool() const { return handle_; } + explicit operator bool() const { return handle_.is_valid(); } // Removes the message pipe from the request and returns it. ScopedMessagePipeHandle PassMessagePipe() { return std::move(handle_); } diff --git a/chromium/mojo/public/cpp/bindings/lib/buffer.cc b/chromium/mojo/public/cpp/bindings/lib/buffer.cc index e726cfe7af4..2444cf4e54e 100644 --- a/chromium/mojo/public/cpp/bindings/lib/buffer.cc +++ b/chromium/mojo/public/cpp/bindings/lib/buffer.cc @@ -19,8 +19,15 @@ Buffer::Buffer(void* data, size_t size, size_t cursor) DCHECK(IsAligned(data_)); } -Buffer::Buffer(MessageHandle message, void* data, size_t size) - : message_(message), data_(data), size_(size), cursor_(0) { +Buffer::Buffer(MessageHandle message, + size_t message_payload_size, + void* data, + size_t size) + : message_(message), + message_payload_size_(message_payload_size), + data_(data), + size_(size), + cursor_(0) { DCHECK(IsAligned(data_)); } @@ -32,6 +39,7 @@ Buffer::~Buffer() = default; Buffer& Buffer::operator=(Buffer&& other) { message_ = other.message_; + message_payload_size_ = other.message_payload_size_; data_ = other.data_; size_ = other.size_; cursor_ = other.cursor_; @@ -51,12 +59,15 @@ size_t Buffer::Allocate(size_t num_bytes) { if (new_cursor > size_) { // If we have an underlying message object we can extend its payload to // obtain more storage capacity. - DCHECK(base::IsValueInRangeForNumericType<uint32_t>(new_cursor)); + DCHECK_LE(message_payload_size_, new_cursor); + size_t additional_bytes = new_cursor - message_payload_size_; + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(additional_bytes)); uint32_t new_size; - MojoResult rv = MojoExtendSerializedMessagePayload( - message_.value(), static_cast<uint32_t>(new_cursor), nullptr, 0, &data_, - &new_size); + MojoResult rv = MojoAppendMessageData( + message_.value(), static_cast<uint32_t>(additional_bytes), nullptr, 0, + nullptr, &data_, &new_size); DCHECK_EQ(MOJO_RESULT_OK, rv); + message_payload_size_ = new_cursor; size_ = new_size; } @@ -79,10 +90,9 @@ void Buffer::AttachHandles(std::vector<ScopedHandle>* handles) { DCHECK(message_.is_valid()); uint32_t new_size = 0; - MojoResult rv = MojoExtendSerializedMessagePayload( - message_.value(), static_cast<uint32_t>(cursor_), - reinterpret_cast<MojoHandle*>(handles->data()), - static_cast<uint32_t>(handles->size()), &data_, &new_size); + MojoResult rv = MojoAppendMessageData( + message_.value(), 0, reinterpret_cast<MojoHandle*>(handles->data()), + static_cast<uint32_t>(handles->size()), nullptr, &data_, &new_size); if (rv != MOJO_RESULT_OK) return; @@ -96,13 +106,21 @@ void Buffer::Seal() { return; // Ensure that the backing message has the final accumulated payload size. - DCHECK(base::IsValueInRangeForNumericType<uint32_t>(cursor_)); + DCHECK_LE(message_payload_size_, cursor_); + size_t additional_bytes = cursor_ - message_payload_size_; + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(additional_bytes)); + + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; void* data; uint32_t size; - MojoResult rv = MojoCommitSerializedMessageContents( - message_.value(), static_cast<uint32_t>(cursor_), &data, &size); + MojoResult rv = MojoAppendMessageData(message_.value(), + static_cast<uint32_t>(additional_bytes), + nullptr, 0, &options, &data, &size); DCHECK_EQ(MOJO_RESULT_OK, rv); message_ = MessageHandle(); + message_payload_size_ = cursor_; data_ = data; size_ = size; } diff --git a/chromium/mojo/public/cpp/bindings/lib/buffer.h b/chromium/mojo/public/cpp/bindings/lib/buffer.h index 58739bb3c12..9f2a7684906 100644 --- a/chromium/mojo/public/cpp/bindings/lib/buffer.h +++ b/chromium/mojo/public/cpp/bindings/lib/buffer.h @@ -39,11 +39,17 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Buffer { // Like above, but gives the Buffer an underlying message object which can // have its payload extended to acquire more storage capacity on Allocate(). // - // |data| and |size| must correspond to |message|'s serialized buffer contents - // at the time of construction. + // |data| and |size| must correspond to |message|'s data buffer at the time of + // construction. + // + // |payload_size| is the length of the payload as known by |message|, and it + // must be less than or equal to |size|. // // |message| is NOT owned and must outlive this Buffer. - Buffer(MessageHandle message, void* data, size_t size); + Buffer(MessageHandle message, + size_t message_payload_size, + void* data, + size_t size); Buffer(Buffer&& other); ~Buffer(); @@ -99,8 +105,21 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Buffer { private: MessageHandle message_; + + // The payload size from the message's internal perspective. This differs from + // |size_| as Mojo may intentionally over-allocate space to account for future + // growth. It differs from |cursor_| because we don't push payload size + // updates to the message object as frequently as we update |cursor_|, for + // performance. + size_t message_payload_size_ = 0; + + // The storage location and capacity currently backing |message_|. Owned by + // the message object internally, not by this Buffer. void* data_ = nullptr; size_t size_ = 0; + + // The current write offset into |data_| if this Buffer is being used for + // message creation. size_t cursor_ = 0; DISALLOW_COPY_AND_ASSIGN(Buffer); diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc index f255efd948f..5cc30b103a8 100644 --- a/chromium/mojo/public/cpp/bindings/lib/connector.cc +++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc @@ -18,7 +18,7 @@ #include "base/threading/thread_local.h" #include "base/trace_event/trace_event.h" #include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/mojo_features.h" +#include "mojo/public/cpp/bindings/mojo_buildflags.h" #include "mojo/public/cpp/bindings/sync_handle_watcher.h" #include "mojo/public/cpp/system/wait.h" @@ -89,10 +89,8 @@ class Connector::RunLoopNestingObserver } static RunLoopNestingObserver* GetForThread() { - if (!base::MessageLoop::current() || - !base::RunLoop::IsNestingAllowedOnCurrentThread()) { + if (!base::MessageLoop::current()) return nullptr; - } auto* observer = static_cast<RunLoopNestingObserver*>( g_tls_nesting_observer.Get().Get()); if (!observer) { diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc index b0dcbb0d192..9fd7bf41735 100644 --- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc @@ -150,7 +150,7 @@ void ControlMessageProxy::FlushForTesting() { auto input_ptr = interface_control::RunInput::New(); input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New()); - base::RunLoop run_loop; + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); run_loop_quit_closure_ = run_loop.QuitClosure(); SendRunMessage( receiver_, std::move(input_ptr), diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc index f350baadd15..44ebf653b26 100644 --- a/chromium/mojo/public/cpp/bindings/lib/message.cc +++ b/chromium/mojo/public/cpp/bindings/lib/message.cc @@ -90,19 +90,20 @@ void CreateSerializedMessageObject(uint32_t name, DCHECK(base::IsValueInRangeForNumericType<uint32_t>(total_size)); DCHECK(!handles || base::IsValueInRangeForNumericType<uint32_t>(handles->size())); - rv = MojoAttachSerializedMessageBuffer( + rv = MojoAppendMessageData( handle->value(), static_cast<uint32_t>(total_size), handles ? reinterpret_cast<MojoHandle*>(handles->data()) : nullptr, - handles ? static_cast<uint32_t>(handles->size()) : 0, &buffer, + handles ? static_cast<uint32_t>(handles->size()) : 0, nullptr, &buffer, &buffer_size); DCHECK_EQ(MOJO_RESULT_OK, rv); if (handles) { - // Handle ownership has been taken by MojoAttachSerializedMessageBuffer. + // Handle ownership has been taken by MojoAppendMessageData. for (size_t i = 0; i < handles->size(); ++i) ignore_result(handles->at(i).release()); } - internal::Buffer payload_buffer(handle.get(), buffer, buffer_size); + internal::Buffer payload_buffer(handle.get(), total_size, buffer, + buffer_size); // Make sure we zero the memory first! memset(payload_buffer.data(), 0, total_size); @@ -118,12 +119,13 @@ void SerializeUnserializedContext(MojoMessageHandle message, reinterpret_cast<internal::UnserializedMessageContext*>(context_value); void* buffer; uint32_t buffer_size; - MojoResult attach_result = MojoAttachSerializedMessageBuffer( - message, 0, nullptr, 0, &buffer, &buffer_size); + MojoResult attach_result = MojoAppendMessageData( + message, 0, nullptr, 0, nullptr, &buffer, &buffer_size); if (attach_result != MOJO_RESULT_OK) return; - internal::Buffer payload_buffer(MessageHandle(message), buffer, buffer_size); + internal::Buffer payload_buffer(MessageHandle(message), 0, buffer, + buffer_size); WriteMessageHeader(context->message_name(), context->message_flags(), 0 /* payload_interface_id_count */, &payload_buffer); @@ -162,9 +164,9 @@ ScopedMessageHandle CreateUnserializedMessageObject( DCHECK_EQ(MOJO_RESULT_OK, rv); DCHECK(handle.is_valid()); - rv = MojoAttachMessageContext( + rv = MojoSetMessageContext( handle->value(), reinterpret_cast<uintptr_t>(context.release()), - &SerializeUnserializedContext, &DestroyUnserializedContext); + &SerializeUnserializedContext, &DestroyUnserializedContext, nullptr); DCHECK_EQ(MOJO_RESULT_OK, rv); return handle; } @@ -204,22 +206,20 @@ Message::Message(ScopedMessageHandle handle) { DCHECK(handle.is_valid()); uintptr_t context_value = 0; - MojoResult get_context_result = MojoGetMessageContext( - handle->value(), &context_value, MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE); + MojoResult get_context_result = + MojoGetMessageContext(handle->value(), nullptr, &context_value); if (get_context_result == MOJO_RESULT_NOT_FOUND) { // It's a serialized message. Extract handles if possible. uint32_t num_bytes; void* buffer; uint32_t num_handles = 0; - MojoResult rv = MojoGetSerializedMessageContents( - handle->value(), &buffer, &num_bytes, nullptr, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + MojoResult rv = MojoGetMessageData(handle->value(), nullptr, &buffer, + &num_bytes, nullptr, &num_handles); if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { handles_.resize(num_handles); - rv = MojoGetSerializedMessageContents( - handle->value(), &buffer, &num_bytes, - reinterpret_cast<MojoHandle*>(handles_.data()), &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + rv = MojoGetMessageData(handle->value(), nullptr, &buffer, &num_bytes, + reinterpret_cast<MojoHandle*>(handles_.data()), + &num_handles); } else { // No handles, so it's safe to retransmit this message if the caller // really wants to. @@ -417,7 +417,7 @@ bool Message::DeserializeAssociatedEndpointHandles( } void Message::SerializeIfNecessary() { - MojoResult rv = MojoSerializeMessage(handle_->value()); + MojoResult rv = MojoSerializeMessage(handle_->value(), nullptr); if (rv == MOJO_RESULT_FAILED_PRECONDITION) return; @@ -430,8 +430,8 @@ Message::TakeUnserializedContext( const internal::UnserializedMessageContext::Tag* tag) { DCHECK(handle_.is_valid()); uintptr_t context_value = 0; - MojoResult rv = MojoGetMessageContext(handle_->value(), &context_value, - MOJO_GET_MESSAGE_CONTEXT_FLAG_NONE); + MojoResult rv = + MojoGetMessageContext(handle_->value(), nullptr, &context_value); if (rv == MOJO_RESULT_NOT_FOUND) return nullptr; DCHECK_EQ(MOJO_RESULT_OK, rv); @@ -442,10 +442,8 @@ Message::TakeUnserializedContext( return nullptr; // Detach the context from the message. - rv = MojoGetMessageContext(handle_->value(), &context_value, - MOJO_GET_MESSAGE_CONTEXT_FLAG_RELEASE); + rv = MojoSetMessageContext(handle_->value(), 0, nullptr, nullptr, nullptr); DCHECK_EQ(MOJO_RESULT_OK, rv); - DCHECK_EQ(context_value, reinterpret_cast<uintptr_t>(context)); return base::WrapUnique(context); } diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc index eb7cb31b2db..61833097ef3 100644 --- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc @@ -18,7 +18,7 @@ #include "mojo/public/cpp/bindings/interface_endpoint_client.h" #include "mojo/public/cpp/bindings/interface_endpoint_controller.h" #include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/sync_event_watcher.h" +#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h" namespace mojo { namespace internal { @@ -108,8 +108,8 @@ class MultiplexRouter::InterfaceEndpoint if (sync_message_event_signaled_) return; sync_message_event_signaled_ = true; - if (sync_message_event_) - sync_message_event_->Signal(); + if (sync_watcher_) + sync_watcher_->SignalEvent(); } void ResetSyncMessageSignal() { @@ -117,8 +117,8 @@ class MultiplexRouter::InterfaceEndpoint if (!sync_message_event_signaled_) return; sync_message_event_signaled_ = false; - if (sync_message_event_) - sync_message_event_->Reset(); + if (sync_watcher_) + sync_watcher_->ResetEvent(); } // --------------------------------------------------------------------------- @@ -136,7 +136,7 @@ class MultiplexRouter::InterfaceEndpoint DCHECK(task_runner_->RunsTasksInCurrentSequence()); EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); + sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence(); } bool SyncWatch(const bool* should_stop) override { @@ -182,20 +182,12 @@ class MultiplexRouter::InterfaceEndpoint if (sync_watcher_) return; - { - MayAutoLock locker(&router_->lock_); - if (!sync_message_event_) { - sync_message_event_.emplace( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - if (sync_message_event_signaled_) - sync_message_event_->Signal(); - } - } - sync_watcher_.reset( - new SyncEventWatcher(&sync_message_event_.value(), - base::Bind(&InterfaceEndpoint::OnSyncEventSignaled, - base::Unretained(this)))); + MayAutoLock locker(&router_->lock_); + sync_watcher_ = + std::make_unique<SequenceLocalSyncEventWatcher>(base::BindRepeating( + &InterfaceEndpoint::OnSyncEventSignaled, base::Unretained(this))); + if (sync_message_event_signaled_) + sync_watcher_->SignalEvent(); } // --------------------------------------------------------------------------- @@ -223,18 +215,11 @@ class MultiplexRouter::InterfaceEndpoint // Not owned. It is null if no client is attached to this endpoint. InterfaceEndpointClient* client_; - // An event used to signal that sync messages are available. The event is - // initialized under the router's lock and remains unchanged afterwards. It - // may be accessed outside of the router's lock later. - base::Optional<base::WaitableEvent> sync_message_event_; + // Indicates whether the sync watcher should be signaled for this endpoint. bool sync_message_event_signaled_ = false; - // --------------------------------------------------------------------------- - // The following members are only valid while a client is attached. They are - // used exclusively on the client's sequence. They may be accessed outside of - // the router's lock. - - std::unique_ptr<SyncEventWatcher> sync_watcher_; + // Guarded by the router's lock. Used to synchronously wait on replies. + std::unique_ptr<SequenceLocalSyncEventWatcher> sync_watcher_; DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); }; diff --git a/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc b/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc new file mode 100644 index 00000000000..f4618ffbe80 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc @@ -0,0 +1,286 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h" + +#include <map> +#include <memory> +#include <set> + +#include "base/bind.h" +#include "base/containers/flat_set.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/no_destructor.h" +#include "base/synchronization/lock.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/sequence_local_storage_slot.h" +#include "mojo/public/cpp/bindings/sync_event_watcher.h" + +namespace mojo { + +namespace { + +struct WatcherState; + +using WatcherStateMap = + std::map<const SequenceLocalSyncEventWatcher*, scoped_refptr<WatcherState>>; + +// Ref-counted watcher state which may outlive the watcher to which it pertains. +// This is necessary to store outside of the SequenceLocalSyncEventWatcher +// itself in order to support nested sync operations where an inner operation +// may destroy the watcher. +struct WatcherState : public base::RefCounted<WatcherState> { + WatcherState() = default; + + bool watcher_was_destroyed = false; + + private: + friend class base::RefCounted<WatcherState>; + + ~WatcherState() = default; + + DISALLOW_COPY_AND_ASSIGN(WatcherState); +}; + +} // namespace + +// Owns the WaitableEvent and SyncEventWatcher shared by all +// SequenceLocalSyncEventWatchers on a single sequence, and coordinates the +// multiplexing of those shared objects to support an arbitrary number of +// SequenceLocalSyncEventWatchers waiting and signaling potentially while +// nested. +class SequenceLocalSyncEventWatcher::SequenceLocalState { + public: + SequenceLocalState() + : event_(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED), + event_watcher_(&event_, + base::BindRepeating(&SequenceLocalState::OnEventSignaled, + base::Unretained(this))), + weak_ptr_factory_(this) { + // We always allow this event handler to be awoken during any sync event on + // the sequence. Individual watchers still must opt into having such + // wake-ups propagated to them. + event_watcher_.AllowWokenUpBySyncWatchOnSameThread(); + } + + ~SequenceLocalState() {} + + // Initializes a SequenceLocalState instance in sequence-local storage if + // not already initialized. Returns a WeakPtr to the stored state object. + static base::WeakPtr<SequenceLocalState> GetOrCreate() { + auto& state_ptr = GetStorageSlot().Get(); + if (!state_ptr) + state_ptr = std::make_unique<SequenceLocalState>(); + return state_ptr->weak_ptr_factory_.GetWeakPtr(); + } + + // Registers a new watcher and returns an iterator into the WatcherStateMap to + // be used for fast access with other methods. + WatcherStateMap::iterator RegisterWatcher( + const SequenceLocalSyncEventWatcher* watcher) { + auto result = registered_watchers_.emplace( + watcher, base::MakeRefCounted<WatcherState>()); + DCHECK(result.second); + return result.first; + } + + void UnregisterWatcher(WatcherStateMap::iterator iter) { + if (top_watcher_ == iter->first) { + // If the watcher being unregistered is currently blocking in a + // |SyncWatch()| operation, we need to unblock it. Setting this flag does + // that. + top_watcher_state_->watcher_was_destroyed = true; + top_watcher_state_ = nullptr; + top_watcher_ = nullptr; + } + + { + base::AutoLock lock(ready_watchers_lock_); + ready_watchers_.erase(iter->first); + } + + registered_watchers_.erase(iter); + if (registered_watchers_.empty()) { + // If no more watchers are registered, clear our sequence-local storage. + // Deletes |this|. + GetStorageSlot().Get().reset(); + } + } + + void SignalForWatcher(const SequenceLocalSyncEventWatcher* watcher) { + bool must_signal = false; + { + base::AutoLock lock(ready_watchers_lock_); + must_signal = ready_watchers_.empty(); + ready_watchers_.insert(watcher); + } + + // If we didn't have any ready watchers before, the event may not have + // been signaled. Signal it to ensure that |OnEventSignaled()| is run. + if (must_signal) + event_.Signal(); + } + + void ResetForWatcher(const SequenceLocalSyncEventWatcher* watcher) { + base::AutoLock lock(ready_watchers_lock_); + ready_watchers_.erase(watcher); + + // No more watchers are ready, so we can reset the event. The next watcher + // to call |SignalForWatcher()| will re-signal the event. + if (ready_watchers_.empty()) + event_.Reset(); + } + + bool SyncWatch(const SequenceLocalSyncEventWatcher* watcher, + WatcherState* watcher_state, + const bool* should_stop) { + // |SyncWatch()| calls may nest arbitrarily deep on the same sequence. We + // preserve the outer watcher state on the stack and restore it once the + // innermost watch is complete. + const SequenceLocalSyncEventWatcher* outer_watcher = top_watcher_; + WatcherState* outer_watcher_state = top_watcher_state_; + + // Keep a ref on the stack so the state stays alive even if the watcher is + // destroyed. + scoped_refptr<WatcherState> top_watcher_state(watcher_state); + top_watcher_state_ = watcher_state; + top_watcher_ = watcher; + + // In addition to the caller's own stop condition, we need to interrupt the + // SyncEventWatcher if |watcher| is destroyed while we're waiting. + const bool* stop_flags[] = {should_stop, + &top_watcher_state_->watcher_was_destroyed}; + + // |SyncWatch()| may delete |this|. + auto weak_self = weak_ptr_factory_.GetWeakPtr(); + bool result = event_watcher_.SyncWatch(stop_flags, 2); + if (!weak_self) + return false; + + top_watcher_state_ = outer_watcher_state; + top_watcher_ = outer_watcher; + return result; + } + + private: + using StorageSlotType = + base::SequenceLocalStorageSlot<std::unique_ptr<SequenceLocalState>>; + static StorageSlotType& GetStorageSlot() { + static base::NoDestructor<StorageSlotType> storage; + return *storage; + } + + void OnEventSignaled(); + + // The shared event and watcher used for this sequence. + base::WaitableEvent event_; + mojo::SyncEventWatcher event_watcher_; + + // All SequenceLocalSyncEventWatchers on the current sequence have some state + // registered here. + WatcherStateMap registered_watchers_; + + // Tracks state of the top-most |SyncWatch()| invocation on the stack. + const SequenceLocalSyncEventWatcher* top_watcher_ = nullptr; + WatcherState* top_watcher_state_ = nullptr; + + // Set of all SequenceLocalSyncEventWatchers in a signaled state, guarded by + // a lock for sequence-safe signaling. + base::Lock ready_watchers_lock_; + base::flat_set<const SequenceLocalSyncEventWatcher*> ready_watchers_; + + base::WeakPtrFactory<SequenceLocalState> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SequenceLocalState); +}; + +void SequenceLocalSyncEventWatcher::SequenceLocalState::OnEventSignaled() { + for (;;) { + base::flat_set<const SequenceLocalSyncEventWatcher*> ready_watchers; + { + base::AutoLock lock(ready_watchers_lock_); + std::swap(ready_watchers_, ready_watchers); + } + if (ready_watchers.empty()) + return; + + auto weak_self = weak_ptr_factory_.GetWeakPtr(); + for (auto* watcher : ready_watchers) { + if (top_watcher_ == watcher || watcher->can_wake_up_during_any_watch_) { + watcher->callback_.Run(); + + // The callback may have deleted |this|. + if (!weak_self) + return; + } + } + } +} + +// Manages a watcher's reference to the sequence-local state. This hides +// implementation details from the SequenceLocalSyncEventWatcher interface. +class SequenceLocalSyncEventWatcher::Registration { + public: + explicit Registration(const SequenceLocalSyncEventWatcher* watcher) + : weak_shared_state_(SequenceLocalState::GetOrCreate()), + shared_state_(weak_shared_state_.get()), + watcher_state_iterator_(shared_state_->RegisterWatcher(watcher)), + watcher_state_(watcher_state_iterator_->second) {} + + ~Registration() { + if (weak_shared_state_) { + // Because |this| may itself be owned by sequence- or thread-local storage + // (e.g. if an interface binding lives there) we have no guarantee that + // our SequenceLocalState's storage slot will still be alive during our + // own destruction; so we have to guard against any access to it. Note + // that this uncertainty only exists within the destructor and does not + // apply to other methods on SequenceLocalSyncEventWatcher. + // + // May delete |shared_state_|. + shared_state_->UnregisterWatcher(watcher_state_iterator_); + } + } + + SequenceLocalState* shared_state() const { return shared_state_; } + WatcherState* watcher_state() { return watcher_state_.get(); } + + private: + const base::WeakPtr<SequenceLocalState> weak_shared_state_; + SequenceLocalState* const shared_state_; + WatcherStateMap::iterator watcher_state_iterator_; + const scoped_refptr<WatcherState> watcher_state_; + + DISALLOW_COPY_AND_ASSIGN(Registration); +}; + +SequenceLocalSyncEventWatcher::SequenceLocalSyncEventWatcher( + const base::RepeatingClosure& callback) + : registration_(std::make_unique<Registration>(this)), + callback_(callback) {} + +SequenceLocalSyncEventWatcher::~SequenceLocalSyncEventWatcher() = default; + +void SequenceLocalSyncEventWatcher::SignalEvent() { + registration_->shared_state()->SignalForWatcher(this); +} + +void SequenceLocalSyncEventWatcher::ResetEvent() { + registration_->shared_state()->ResetForWatcher(this); +} + +void SequenceLocalSyncEventWatcher::AllowWokenUpBySyncWatchOnSameSequence() { + can_wake_up_during_any_watch_ = true; +} + +bool SequenceLocalSyncEventWatcher::SyncWatch(const bool* should_stop) { + // NOTE: |SyncWatch()| may delete |this|. + return registration_->shared_state()->SyncWatch( + this, registration_->watcher_state(), should_stop); +} + +} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization.h b/chromium/mojo/public/cpp/bindings/lib/serialization.h index d4fdfd68033..98bc273ebc8 100644 --- a/chromium/mojo/public/cpp/bindings/lib/serialization.h +++ b/chromium/mojo/public/cpp/bindings/lib/serialization.h @@ -22,7 +22,6 @@ #include "mojo/public/cpp/bindings/map_traits_stl.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/bindings/string_traits_stl.h" -#include "mojo/public/cpp/bindings/string_traits_string16.h" #include "mojo/public/cpp/bindings/string_traits_string_piece.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc b/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc deleted file mode 100644 index 95ff6ccf257..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/string_traits_string16.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/string_traits_string16.h" - -#include <string> - -#include "base/strings/utf_string_conversions.h" - -namespace mojo { - -// static -void* StringTraits<base::string16>::SetUpContext(const base::string16& input) { - return new std::string(base::UTF16ToUTF8(input)); -} - -// static -void StringTraits<base::string16>::TearDownContext(const base::string16& input, - void* context) { - delete static_cast<std::string*>(context); -} - -// static -size_t StringTraits<base::string16>::GetSize(const base::string16& input, - void* context) { - return static_cast<std::string*>(context)->size(); -} - -// static -const char* StringTraits<base::string16>::GetData(const base::string16& input, - void* context) { - return static_cast<std::string*>(context)->data(); -} - -// static -bool StringTraits<base::string16>::Read(StringDataView input, - base::string16* output) { - return base::UTF8ToUTF16(input.storage(), input.size(), output); -} - -} // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc index a58bb1b235d..71b758c49c1 100644 --- a/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc +++ b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc @@ -9,7 +9,7 @@ #include "base/logging.h" #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/string_data_view.h" -#include "third_party/WebKit/Source/platform/wtf/text/StringUTF8Adaptor.h" +#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" namespace mojo { namespace { diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_event_watcher.cc b/chromium/mojo/public/cpp/bindings/lib/sync_event_watcher.cc index 19a41eb510e..17165912fc9 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_event_watcher.cc +++ b/chromium/mojo/public/cpp/bindings/lib/sync_event_watcher.cc @@ -4,6 +4,9 @@ #include "mojo/public/cpp/bindings/sync_event_watcher.h" +#include <algorithm> + +#include "base/containers/stack_container.h" #include "base/logging.h" namespace mojo { @@ -27,7 +30,8 @@ void SyncEventWatcher::AllowWokenUpBySyncWatchOnSameThread() { IncrementRegisterCount(); } -bool SyncEventWatcher::SyncWatch(const bool* should_stop) { +bool SyncEventWatcher::SyncWatch(const bool** stop_flags, + size_t num_stop_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); IncrementRegisterCount(); if (!registered_) { @@ -38,8 +42,14 @@ bool SyncEventWatcher::SyncWatch(const bool* should_stop) { // This object may be destroyed during the Wait() call. So we have to preserve // the boolean that Wait uses. auto destroyed = destroyed_; - const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = registry_->Wait(should_stop_array, 2); + + constexpr size_t kFlagStackCapacity = 4; + base::StackVector<const bool*, kFlagStackCapacity> should_stop_array; + should_stop_array.container().push_back(&destroyed->data); + std::copy(stop_flags, stop_flags + num_stop_flags, + std::back_inserter(should_stop_array.container())); + bool result = registry_->Wait(should_stop_array.container().data(), + should_stop_array.container().size()); // This object has been destroyed. if (destroyed->data) diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc index 6816de0ec5c..2ac48334450 100644 --- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc @@ -128,9 +128,10 @@ bool SyncHandleRegistry::Wait(const bool* should_stop[], size_t count) { scoped_refptr<SyncHandleRegistry> preserver(this); while (true) { - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { if (*should_stop[i]) return true; + } // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we // give priority to the handle that is waiting for sync response. diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h b/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h index d801dafb751..2a3bef25921 100644 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h +++ b/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h @@ -9,10 +9,10 @@ #include "mojo/public/cpp/bindings/clone_traits.h" #include "mojo/public/cpp/bindings/equals_traits.h" -#include "third_party/WebKit/Source/platform/wtf/HashMap.h" -#include "third_party/WebKit/Source/platform/wtf/Optional.h" -#include "third_party/WebKit/Source/platform/wtf/Vector.h" -#include "third_party/WebKit/Source/platform/wtf/text/WTFString.h" +#include "third_party/blink/renderer/platform/wtf/hash_map.h" +#include "third_party/blink/renderer/platform/wtf/optional.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h b/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h index 509b7cf8bde..fa02262e8e8 100644 --- a/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h +++ b/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h @@ -9,9 +9,9 @@ #include "mojo/public/cpp/bindings/lib/hash_util.h" #include "mojo/public/cpp/bindings/struct_ptr.h" -#include "third_party/WebKit/Source/platform/wtf/HashFunctions.h" -#include "third_party/WebKit/Source/platform/wtf/text/StringHash.h" -#include "third_party/WebKit/Source/platform/wtf/text/WTFString.h" +#include "third_party/blink/renderer/platform/wtf/hash_functions.h" +#include "third_party/blink/renderer/platform/wtf/text/string_hash.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace mojo { namespace internal { diff --git a/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h b/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h index 128350ff542..32deab7aaed 100644 --- a/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h +++ b/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h @@ -7,7 +7,7 @@ #include "base/logging.h" #include "mojo/public/cpp/bindings/map_traits.h" -#include "third_party/WebKit/Source/platform/wtf/HashMap.h" +#include "third_party/blink/renderer/platform/wtf/hash_map.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/message.h b/chromium/mojo/public/cpp/bindings/message.h index 97f92b073f8..4ad1c04c187 100644 --- a/chromium/mojo/public/cpp/bindings/message.h +++ b/chromium/mojo/public/cpp/bindings/message.h @@ -17,6 +17,7 @@ #include "base/compiler_specific.h" #include "base/component_export.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "mojo/public/cpp/bindings/lib/buffer.h" #include "mojo/public/cpp/bindings/lib/message_internal.h" #include "mojo/public/cpp/bindings/lib/unserialized_message_context.h" diff --git a/chromium/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h b/chromium/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h new file mode 100644 index 00000000000..ad50bde436b --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h @@ -0,0 +1,69 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_SEQUENCE_LOCAL_SYNC_EVENT_WATCHER_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_SEQUENCE_LOCAL_SYNC_EVENT_WATCHER_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/bindings_export.h" + +namespace mojo { + +// This encapsulates a SyncEventWatcher watching an event shared by all +// |SequenceLocalSyncEventWatcher| on the same sequence. This class is NOT +// sequence-safe in general, but |SignalEvent()| is safe to call from any +// sequence. +// +// Interfaces which support sync messages use a WaitableEvent to block and +// be signaled when messages are available, but having a WaitableEvent for every +// such interface endpoint would cause the number of WaitableEvents to grow +// arbitrarily large. +// +// Some platform constraints may limit the number of WaitableEvents the bindings +// layer can wait upon concurrently, so this type is used to keep the number +// of such events fixed at a small constant value per sequence regardless of the +// number of active interface endpoints supporting sync messages on that +// sequence. +class MOJO_CPP_BINDINGS_EXPORT SequenceLocalSyncEventWatcher { + public: + explicit SequenceLocalSyncEventWatcher( + const base::RepeatingClosure& callback); + ~SequenceLocalSyncEventWatcher(); + + // Signals the shared event on behalf of this specific watcher. Safe to call + // from any sequence. + void SignalEvent(); + + // Resets the shared event on behalf of this specific watcher. + void ResetEvent(); + + // Allows this watcher to be notified during sync wait operations invoked by + // other watchers (for example, other SequenceLocalSyncEventWatchers calling + // |SyncWatch()|) on the same sequence. + void AllowWokenUpBySyncWatchOnSameSequence(); + + // Blocks the calling sequence until the shared event is signaled on behalf of + // this specific watcher (i.e. until someone calls |SignalEvent()| on |this|). + // Behaves similarly to SyncEventWatcher and SyncHandleWatcher, returning + // |true| when |*should_stop| is set to |true|, or |false| if some other + // (e.g. error) event interrupts the wait. + bool SyncWatch(const bool* should_stop); + + private: + class Registration; + class SequenceLocalState; + friend class SequenceLocalState; + + const std::unique_ptr<Registration> registration_; + const base::RepeatingClosure callback_; + bool can_wake_up_during_any_watch_ = false; + + DISALLOW_COPY_AND_ASSIGN(SequenceLocalSyncEventWatcher); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_SEQUENCE_LOCAL_SYNC_EVENT_WATCHER_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_string16.h b/chromium/mojo/public/cpp/bindings/string_traits_string16.h deleted file mode 100644 index 26f7f1dbf43..00000000000 --- a/chromium/mojo/public/cpp/bindings/string_traits_string16.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ - -#include "base/component_export.h" -#include "base/strings/string16.h" -#include "mojo/public/cpp/bindings/string_data_view.h" -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { - -template <> -struct COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) StringTraits<base::string16> { - static bool IsNull(const base::string16& input) { - // base::string16 is always converted to non-null mojom string. - return false; - } - - static void SetToNull(base::string16* output) { - // Convert null to an "empty" base::string16. - output->clear(); - } - - static void* SetUpContext(const base::string16& input); - static void TearDownContext(const base::string16& input, void* context); - - static size_t GetSize(const base::string16& input, void* context); - static const char* GetData(const base::string16& input, void* context); - - static bool Read(StringDataView input, base::string16* output); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ diff --git a/chromium/mojo/public/cpp/bindings/string_traits_wtf.h b/chromium/mojo/public/cpp/bindings/string_traits_wtf.h index 4f0de4890f9..51601d1ab85 100644 --- a/chromium/mojo/public/cpp/bindings/string_traits_wtf.h +++ b/chromium/mojo/public/cpp/bindings/string_traits_wtf.h @@ -7,7 +7,7 @@ #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/string_traits.h" -#include "third_party/WebKit/Source/platform/wtf/text/WTFString.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace mojo { diff --git a/chromium/mojo/public/cpp/bindings/strong_binding_set.h b/chromium/mojo/public/cpp/bindings/strong_binding_set.h index f6bcd5259c0..3f855f428ef 100644 --- a/chromium/mojo/public/cpp/bindings/strong_binding_set.h +++ b/chromium/mojo/public/cpp/bindings/strong_binding_set.h @@ -15,11 +15,13 @@ namespace mojo { // set, and the interface implementation is deleted. When the StrongBindingSet // is destructed, all outstanding bindings in the set are destroyed and all the // bound interface implementations are automatically deleted. -template <typename Interface, typename ContextType = void> -using StrongBindingSet = - BindingSetBase<Interface, - Binding<Interface, UniquePtrImplRefTraits<Interface>>, - ContextType>; +template <typename Interface, + typename ContextType = void, + typename Deleter = std::default_delete<Interface>> +using StrongBindingSet = BindingSetBase< + Interface, + Binding<Interface, UniquePtrImplRefTraits<Interface, Deleter>>, + ContextType>; } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/sync_event_watcher.h b/chromium/mojo/public/cpp/bindings/sync_event_watcher.h index 76dc4feaf3c..9bc9ada5946 100644 --- a/chromium/mojo/public/cpp/bindings/sync_event_watcher.h +++ b/chromium/mojo/public/cpp/bindings/sync_event_watcher.h @@ -36,11 +36,15 @@ class MOJO_CPP_BINDINGS_EXPORT SyncEventWatcher { // Waits on |event_| plus all other events and handles registered with this // sequence's SyncHandleRegistry, running callbacks synchronously for any // ready events and handles. + // + // |stop_flags| is treated as an array of |const bool*| with |num_stop_flags| + // entries. + // // This method: - // - returns true when |should_stop| is set to true; + // - returns true when any flag in |stop_flags| is set to |true|. // - return false when any error occurs, including this object being // destroyed during a callback. - bool SyncWatch(const bool* should_stop); + bool SyncWatch(const bool** stop_flags, size_t num_stop_flags); private: void IncrementRegisterCount(); diff --git a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn index 4ab1ff1c53f..b54000d3212 100644 --- a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn @@ -50,7 +50,7 @@ source_set("tests") { deps = [ ":mojo_public_bindings_test_utils", "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", "//mojo/public/cpp/test_support:test_utils", @@ -134,7 +134,7 @@ source_set("perftests") { deps = [ "//base/test:test_support", - "//mojo/edk/system", + "//mojo/edk", "//mojo/edk/test:test_support", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", diff --git a/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h index 73b87683311..fb690375fba 100644 --- a/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h +++ b/chromium/mojo/public/cpp/bindings/thread_safe_interface_ptr.h @@ -152,7 +152,8 @@ class ThreadSafeForwarder : public MessageReceiverWithResponder { bool event_signaled = false; SyncEventWatcher watcher(&response->event, base::Bind(assign_true, &event_signaled)); - watcher.SyncWatch(&event_signaled); + const bool* stop_flags[] = {&event_signaled}; + watcher.SyncWatch(stop_flags, 1); { base::AutoLock l(sync_calls->lock); diff --git a/chromium/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h b/chromium/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h index f1ac097396b..ca7fe930c60 100644 --- a/chromium/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h +++ b/chromium/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h @@ -9,9 +9,9 @@ namespace mojo { // Traits for a binding's implementation reference type. // This corresponds to a unique_ptr reference type. -template <typename Interface> +template <typename Interface, typename Deleter = std::default_delete<Interface>> struct UniquePtrImplRefTraits { - using PointerType = std::unique_ptr<Interface>; + using PointerType = std::unique_ptr<Interface, Deleter>; static bool IsNull(const PointerType& ptr) { return !ptr; } static Interface* GetRawPointer(PointerType* ptr) { return ptr->get(); } diff --git a/chromium/mojo/public/cpp/system/BUILD.gn b/chromium/mojo/public/cpp/system/BUILD.gn index e93d72789d6..fbabef61684 100644 --- a/chromium/mojo/public/cpp/system/BUILD.gn +++ b/chromium/mojo/public/cpp/system/BUILD.gn @@ -27,6 +27,10 @@ component("system") { "buffer.h", "core.h", "data_pipe.h", + "data_pipe_drainer.cc", + "data_pipe_drainer.h", + "data_pipe_utils.cc", + "data_pipe_utils.h", "file_data_pipe_producer.cc", "file_data_pipe_producer.h", "functions.h", @@ -44,12 +48,12 @@ component("system") { "string_data_pipe_producer.cc", "string_data_pipe_producer.h", "system_export.h", + "trap.cc", + "trap.h", "wait.cc", "wait.h", "wait_set.cc", "wait_set.h", - "watcher.cc", - "watcher.h", ] public_deps = [ diff --git a/chromium/mojo/public/cpp/system/buffer.cc b/chromium/mojo/public/cpp/system/buffer.cc index 49f45d84988..13f20263165 100644 --- a/chromium/mojo/public/cpp/system/buffer.cc +++ b/chromium/mojo/public/cpp/system/buffer.cc @@ -43,4 +43,12 @@ ScopedSharedBufferMapping SharedBufferHandle::MapAtOffset( return ScopedSharedBufferMapping(buffer); } +uint64_t SharedBufferHandle::GetSize() const { + MojoSharedBufferInfo buffer_info; + buffer_info.struct_size = sizeof(buffer_info); + return MojoGetBufferInfo(value(), nullptr, &buffer_info) == MOJO_RESULT_OK + ? buffer_info.size + : 0; +} + } // namespace mojo diff --git a/chromium/mojo/public/cpp/system/buffer.h b/chromium/mojo/public/cpp/system/buffer.h index 660b7503a11..d72d1976507 100644 --- a/chromium/mojo/public/cpp/system/buffer.h +++ b/chromium/mojo/public/cpp/system/buffer.h @@ -69,6 +69,9 @@ class MOJO_CPP_SYSTEM_EXPORT SharedBufferHandle : public Handle { // Maps |size| bytes of this shared buffer, starting |offset| bytes into the // buffer. On failure, this will return a null mapping. ScopedSharedBufferMapping MapAtOffset(uint64_t size, uint64_t offset) const; + + // Get the size of this shared buffer. + uint64_t GetSize() const; }; static_assert(sizeof(SharedBufferHandle) == sizeof(Handle), diff --git a/chromium/mojo/common/data_pipe_drainer.cc b/chromium/mojo/public/cpp/system/data_pipe_drainer.cc index b155ad80fb1..27b995a2a77 100644 --- a/chromium/mojo/common/data_pipe_drainer.cc +++ b/chromium/mojo/public/cpp/system/data_pipe_drainer.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/common/data_pipe_drainer.h" +#include "mojo/public/cpp/system/data_pipe_drainer.h" #include <stdint.h> @@ -11,13 +11,14 @@ #include "base/bind.h" namespace mojo { -namespace common { DataPipeDrainer::DataPipeDrainer(Client* client, mojo::ScopedDataPipeConsumerHandle source) : client_(client), source_(std::move(source)), - handle_watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC), + handle_watcher_(FROM_HERE, + SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()), weak_factory_(this) { DCHECK(client_); handle_watcher_.Watch( @@ -46,5 +47,4 @@ void DataPipeDrainer::WaitComplete(MojoResult result) { ReadData(); } -} // namespace common } // namespace mojo diff --git a/chromium/mojo/common/data_pipe_drainer.h b/chromium/mojo/public/cpp/system/data_pipe_drainer.h index 5cff8203e09..209d93d705b 100644 --- a/chromium/mojo/common/data_pipe_drainer.h +++ b/chromium/mojo/public/cpp/system/data_pipe_drainer.h @@ -2,21 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_COMMON_DATA_PIPE_DRAINER_H_ -#define MOJO_COMMON_DATA_PIPE_DRAINER_H_ +#ifndef MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_DRAINER_H_ +#define MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_DRAINER_H_ #include <stddef.h> #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "mojo/common/mojo_common_export.h" #include "mojo/public/cpp/system/core.h" #include "mojo/public/cpp/system/simple_watcher.h" +#include "mojo/public/cpp/system/system_export.h" namespace mojo { -namespace common { -class MOJO_COMMON_EXPORT DataPipeDrainer { +class MOJO_CPP_SYSTEM_EXPORT DataPipeDrainer { public: class Client { public: @@ -43,7 +42,6 @@ class MOJO_COMMON_EXPORT DataPipeDrainer { DISALLOW_COPY_AND_ASSIGN(DataPipeDrainer); }; -} // namespace common } // namespace mojo -#endif // MOJO_COMMON_DATA_PIPE_DRAINER_H_ +#endif // MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_DRAINER_H_ diff --git a/chromium/mojo/common/data_pipe_utils.cc b/chromium/mojo/public/cpp/system/data_pipe_utils.cc index bfcb5d5ae06..77f79d31bb1 100644 --- a/chromium/mojo/common/data_pipe_utils.cc +++ b/chromium/mojo/public/cpp/system/data_pipe_utils.cc @@ -2,19 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/common/data_pipe_utils.h" - #include <utility> #include "base/bind.h" #include "base/callback.h" +#include "mojo/public/cpp/system/data_pipe_utils.h" #include "mojo/public/cpp/system/wait.h" namespace mojo { -namespace common { namespace { -bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, +bool BlockingCopyHelper( + ScopedDataPipeConsumerHandle source, const base::Callback<size_t(const void*, uint32_t)>& write_bytes) { for (;;) { const void* buffer; @@ -44,8 +43,9 @@ bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, return false; } -size_t CopyToStringHelper( - std::string* result, const void* buffer, uint32_t num_bytes) { +size_t CopyToStringHelper(std::string* result, + const void* buffer, + uint32_t num_bytes) { result->append(static_cast<const char*>(buffer), num_bytes); return num_bytes; } @@ -61,9 +61,9 @@ bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, base::Bind(&CopyToStringHelper, result)); } -bool MOJO_COMMON_EXPORT BlockingCopyFromString( - const std::string& source, - const ScopedDataPipeProducerHandle& destination) { +bool MOJO_CPP_SYSTEM_EXPORT +BlockingCopyFromString(const std::string& source, + const ScopedDataPipeProducerHandle& destination) { auto it = source.begin(); for (;;) { void* buffer = nullptr; @@ -92,5 +92,4 @@ bool MOJO_COMMON_EXPORT BlockingCopyFromString( } } -} // namespace common } // namespace mojo diff --git a/chromium/mojo/common/data_pipe_utils.h b/chromium/mojo/public/cpp/system/data_pipe_utils.h index a3f7c093e47..d0d6f521e3e 100644 --- a/chromium/mojo/common/data_pipe_utils.h +++ b/chromium/mojo/public/cpp/system/data_pipe_utils.h @@ -2,31 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_COMMON_DATA_PIPE_UTILS_H_ -#define MOJO_COMMON_DATA_PIPE_UTILS_H_ +#ifndef MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_UTILS_H_ +#define MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_UTILS_H_ #include <stdint.h> #include <string> -#include "mojo/common/mojo_common_export.h" #include "mojo/public/cpp/system/data_pipe.h" +#include "mojo/public/cpp/system/system_export.h" namespace mojo { -namespace common { // Copies the data from |source| into |contents| and returns true on success and // false on error. In case of I/O error, |contents| holds the data that could // be read from source before the error occurred. -bool MOJO_COMMON_EXPORT BlockingCopyToString( - ScopedDataPipeConsumerHandle source, - std::string* contents); +bool MOJO_CPP_SYSTEM_EXPORT +BlockingCopyToString(ScopedDataPipeConsumerHandle source, + std::string* contents); -bool MOJO_COMMON_EXPORT BlockingCopyFromString( - const std::string& source, - const ScopedDataPipeProducerHandle& destination); +bool MOJO_CPP_SYSTEM_EXPORT +BlockingCopyFromString(const std::string& source, + const ScopedDataPipeProducerHandle& destination); -} // namespace common } // namespace mojo -#endif // MOJO_COMMON_DATA_PIPE_UTILS_H_ +#endif // MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_UTILS_H_ diff --git a/chromium/mojo/public/cpp/system/file_data_pipe_producer.cc b/chromium/mojo/public/cpp/system/file_data_pipe_producer.cc index 301e826d82f..842fe8f2998 100644 --- a/chromium/mojo/public/cpp/system/file_data_pipe_producer.cc +++ b/chromium/mojo/public/cpp/system/file_data_pipe_producer.cc @@ -107,7 +107,8 @@ class FileDataPipeProducer::FileSequenceState // If we didn't nail it all on the first transaction attempt, setup a // watcher and complete the read asynchronously. watcher_ = std::make_unique<SimpleWatcher>( - FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); + FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()); watcher_->Watch(producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_WATCH_CONDITION_SATISFIED, base::Bind(&FileSequenceState::OnHandleReady, this)); diff --git a/chromium/mojo/public/cpp/system/handle_signal_tracker.cc b/chromium/mojo/public/cpp/system/handle_signal_tracker.cc index 37b2c9347ff..a6e9d97a017 100644 --- a/chromium/mojo/public/cpp/system/handle_signal_tracker.cc +++ b/chromium/mojo/public/cpp/system/handle_signal_tracker.cc @@ -11,15 +11,19 @@ namespace mojo { HandleSignalTracker::HandleSignalTracker(Handle handle, MojoHandleSignals signals) - : high_watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL), - low_watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL) { + : high_watcher_(FROM_HERE, + SimpleWatcher::ArmingPolicy::MANUAL, + base::SequencedTaskRunnerHandle::Get()), + low_watcher_(FROM_HERE, + SimpleWatcher::ArmingPolicy::MANUAL, + base::SequencedTaskRunnerHandle::Get()) { MojoResult rv = high_watcher_.Watch( - handle, signals, MOJO_WATCH_CONDITION_SATISFIED, + handle, signals, MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, base::Bind(&HandleSignalTracker::OnNotify, base::Unretained(this))); DCHECK_EQ(MOJO_RESULT_OK, rv); rv = low_watcher_.Watch( - handle, signals, MOJO_WATCH_CONDITION_NOT_SATISFIED, + handle, signals, MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED, base::Bind(&HandleSignalTracker::OnNotify, base::Unretained(this))); DCHECK_EQ(MOJO_RESULT_OK, rv); diff --git a/chromium/mojo/public/cpp/system/message.h b/chromium/mojo/public/cpp/system/message.h index 58aed2635aa..ebe0f31dfe1 100644 --- a/chromium/mojo/public/cpp/system/message.h +++ b/chromium/mojo/public/cpp/system/message.h @@ -52,7 +52,7 @@ using ScopedMessageHandle = ScopedHandleBase<MessageHandle>; inline MojoResult CreateMessage(ScopedMessageHandle* handle) { MojoMessageHandle raw_handle; - MojoResult rv = MojoCreateMessage(&raw_handle); + MojoResult rv = MojoCreateMessage(nullptr, &raw_handle); if (rv != MOJO_RESULT_OK) return rv; @@ -60,18 +60,21 @@ inline MojoResult CreateMessage(ScopedMessageHandle* handle) { return MOJO_RESULT_OK; } -inline MojoResult GetSerializedMessageContents( - MessageHandle message, - void** buffer, - uint32_t* num_bytes, - std::vector<ScopedHandle>* handles, - MojoGetSerializedMessageContentsFlags flags) { +inline MojoResult GetMessageData(MessageHandle message, + void** buffer, + uint32_t* num_bytes, + std::vector<ScopedHandle>* handles, + MojoGetMessageDataFlags flags) { DCHECK(message.is_valid()); DCHECK(num_bytes); DCHECK(buffer); uint32_t num_handles = 0; - MojoResult rv = MojoGetSerializedMessageContents( - message.value(), buffer, num_bytes, nullptr, &num_handles, flags); + + MojoGetMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = flags; + MojoResult rv = MojoGetMessageData(message.value(), &options, buffer, + num_bytes, nullptr, &num_handles); if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) { if (handles) handles->clear(); @@ -79,9 +82,9 @@ inline MojoResult GetSerializedMessageContents( } handles->resize(num_handles); - return MojoGetSerializedMessageContents( - message.value(), buffer, num_bytes, - reinterpret_cast<MojoHandle*>(handles->data()), &num_handles, flags); + return MojoGetMessageData(message.value(), &options, buffer, num_bytes, + reinterpret_cast<MojoHandle*>(handles->data()), + &num_handles); } inline MojoResult NotifyBadMessage(MessageHandle message, diff --git a/chromium/mojo/public/cpp/system/message_pipe.cc b/chromium/mojo/public/cpp/system/message_pipe.cc index a29dcfa81bc..0d1adb543a4 100644 --- a/chromium/mojo/public/cpp/system/message_pipe.cc +++ b/chromium/mojo/public/cpp/system/message_pipe.cc @@ -18,16 +18,15 @@ MojoResult WriteMessageRaw(MessagePipeHandle message_pipe, MojoResult rv = CreateMessage(&message_handle); DCHECK_EQ(MOJO_RESULT_OK, rv); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; void* buffer; uint32_t buffer_size; - rv = MojoAttachSerializedMessageBuffer( - message_handle->value(), base::checked_cast<uint32_t>(num_bytes), handles, - base::checked_cast<uint32_t>(num_handles), &buffer, &buffer_size); - if (rv != MOJO_RESULT_OK) - return MOJO_RESULT_ABORTED; - rv = MojoCommitSerializedMessageContents( - message_handle->value(), base::checked_cast<uint32_t>(num_bytes), &buffer, - &buffer_size); + rv = MojoAppendMessageData(message_handle->value(), + base::checked_cast<uint32_t>(num_bytes), handles, + base::checked_cast<uint32_t>(num_handles), + &options, &buffer, &buffer_size); if (rv != MOJO_RESULT_OK) return MOJO_RESULT_ABORTED; @@ -48,23 +47,21 @@ MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, if (rv != MOJO_RESULT_OK) return rv; - rv = MojoSerializeMessage(message_handle->value()); + rv = MojoSerializeMessage(message_handle->value(), nullptr); if (rv != MOJO_RESULT_OK && rv != MOJO_RESULT_FAILED_PRECONDITION) return MOJO_RESULT_ABORTED; void* buffer = nullptr; uint32_t num_bytes = 0; uint32_t num_handles = 0; - rv = MojoGetSerializedMessageContents( - message_handle->value(), &buffer, &num_bytes, nullptr, &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + rv = MojoGetMessageData(message_handle->value(), nullptr, &buffer, &num_bytes, + nullptr, &num_handles); if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { DCHECK(handles); handles->resize(num_handles); - rv = MojoGetSerializedMessageContents( - message_handle->value(), &buffer, &num_bytes, - reinterpret_cast<MojoHandle*>(handles->data()), &num_handles, - MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE); + rv = MojoGetMessageData( + message_handle->value(), nullptr, &buffer, &num_bytes, + reinterpret_cast<MojoHandle*>(handles->data()), &num_handles); } if (num_bytes) { diff --git a/chromium/mojo/public/cpp/system/platform_handle.cc b/chromium/mojo/public/cpp/system/platform_handle.cc index c8e9ef30f46..a4f5670a2f2 100644 --- a/chromium/mojo/public/cpp/system/platform_handle.cc +++ b/chromium/mojo/public/cpp/system/platform_handle.cc @@ -4,6 +4,9 @@ #include "mojo/public/cpp/system/platform_handle.h" +#include "base/memory/platform_shared_memory_region.h" +#include "build/build_config.h" + #if defined(OS_MACOSX) && !defined(OS_IOS) #include <mach/mach.h> #include "base/mac/mach_logging.h" @@ -29,6 +32,103 @@ base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) { #endif } +ScopedSharedBufferHandle WrapPlatformSharedMemoryRegion( + base::subtle::PlatformSharedMemoryRegion region) { + if (!region.IsValid()) + return ScopedSharedBufferHandle(); + + // TODO(https://crbug.com/826213): Support writable regions too, then simplify + // mojom base shared memory traits using this code. This will require the C + // API to be extended first. + DCHECK_NE(base::subtle::PlatformSharedMemoryRegion::Mode::kWritable, + region.GetMode()); + + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle = + region.PassPlatformHandle(); + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(platform_handle); +#if defined(OS_WIN) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; + platform_handle.value = reinterpret_cast<uint64_t>(handle.Take()); +#elif defined(OS_FUCHSIA) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#elif defined(OS_MACOSX) && !defined(OS_IOS) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#elif defined(OS_ANDROID) + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; + platform_handle.value = static_cast<uint64_t>(handle.release()); +#else + platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; + platform_handle.value = static_cast<uint64_t>(handle.fd.release()); +#endif + const auto& guid = region.GetGUID(); + MojoSharedBufferGuid mojo_guid = {guid.GetHighForSerialization(), + guid.GetLowForSerialization()}; + MojoHandle mojo_handle; + MojoResult result = MojoWrapPlatformSharedBufferHandle( + &platform_handle, region.GetSize(), &mojo_guid, + region.GetMode() == + base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly + ? MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY + : MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE, + &mojo_handle); + if (result != MOJO_RESULT_OK) + return ScopedSharedBufferHandle(); + return ScopedSharedBufferHandle(SharedBufferHandle(mojo_handle)); +} + +base::subtle::PlatformSharedMemoryRegion UnwrapPlatformSharedMemoryRegion( + ScopedSharedBufferHandle mojo_handle) { + if (!mojo_handle.is_valid()) + return base::subtle::PlatformSharedMemoryRegion(); + + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(platform_handle); + size_t size; + MojoSharedBufferGuid mojo_guid; + MojoPlatformSharedBufferHandleFlags flags; + MojoResult result = MojoUnwrapPlatformSharedBufferHandle( + mojo_handle.release().value(), &platform_handle, &size, &mojo_guid, + &flags); + if (result != MOJO_RESULT_OK) + return base::subtle::PlatformSharedMemoryRegion(); + + base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle region_handle; +#if defined(OS_WIN) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) + return base::subtle::PlatformSharedMemoryRegion(); + region_handle.Set(reinterpret_cast<HANDLE>(platform_handle.value)); +#elif defined(OS_FUCHSIA) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE) + return base::subtle::PlatformSharedMemoryRegion(); + region_handle.reset(static_cast<zx_handle_t>(platform_handle.value)); +#elif defined(OS_MACOSX) && !defined(OS_IOS) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) + return base::subtle::PlatformSharedMemoryRegion(); + region_handle.reset(static_cast<mach_port_t>(platform_handle.value)); +#elif defined(OS_ANDROID) + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) + return base::subtle::PlatformSharedMemoryRegion(); + region_handle.reset(static_cast<int>(platform_handle.value)); +#else + if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) + return base::subtle::PlatformSharedMemoryRegion(); + region_handle.fd.reset(static_cast<int>(platform_handle.value)); +#endif + + // TODO(https://crbug.com/826213): Support unwrapping writable regions. See + // comment in |WrapPlatformSharedMemoryRegion()| above. + base::subtle::PlatformSharedMemoryRegion::Mode mode = + flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY + ? base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly + : base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe; + return base::subtle::PlatformSharedMemoryRegion::Take( + std::move(region_handle), mode, size, + base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low)); +} + } // namespace ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) { @@ -81,9 +181,22 @@ ScopedSharedBufferHandle WrapSharedMemoryHandle( MojoPlatformSharedBufferHandleFlags flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; - if (protection == UnwrappedSharedMemoryHandleProtection::kReadOnly) + if (protection == UnwrappedSharedMemoryHandleProtection::kReadOnly) { flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY; +#if defined(OS_ANDROID) + // Many callers assume that base::SharedMemory::GetReadOnlyHandle() gives + // them a handle which is actually read-only. This assumption is invalid on + // Android. As a precursor to migrating all base::SharedMemory usage -- + // including Mojo internals -- to the new base shared memory API, we ensure + // that regions are set to read-only if any of their handles are wrapped + // read-only. This relies on existing usages not attempting to map the + // region writable any time after this call. + if (!memory_handle.IsRegionReadOnly()) + memory_handle.SetRegionReadOnly(); +#endif + } + MojoSharedBufferGuid guid; guid.high = memory_handle.GetGUID().GetHighForSerialization(); guid.low = memory_handle.GetGUID().GetLowForSerialization(); @@ -148,6 +261,48 @@ MojoResult UnwrapSharedMemoryHandle( return MOJO_RESULT_OK; } +ScopedSharedBufferHandle WrapReadOnlySharedMemoryRegion( + base::ReadOnlySharedMemoryRegion region) { + return WrapPlatformSharedMemoryRegion( + base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization( + std::move(region))); +} + +ScopedSharedBufferHandle WrapUnsafeSharedMemoryRegion( + base::UnsafeSharedMemoryRegion region) { + return WrapPlatformSharedMemoryRegion( + base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( + std::move(region))); +} + +ScopedSharedBufferHandle WrapWritableSharedMemoryRegion( + base::WritableSharedMemoryRegion region) { + // TODO(https://crbug.com/826213): Support wrapping writable regions. See + // comment in |WrapPlatformSharedMemoryRegion()| above. + NOTIMPLEMENTED(); + return ScopedSharedBufferHandle(); +} + +base::ReadOnlySharedMemoryRegion UnwrapReadOnlySharedMemoryRegion( + ScopedSharedBufferHandle handle) { + return base::ReadOnlySharedMemoryRegion::Deserialize( + UnwrapPlatformSharedMemoryRegion(std::move(handle))); +} + +base::UnsafeSharedMemoryRegion UnwrapUnsafeSharedMemoryRegion( + ScopedSharedBufferHandle handle) { + return base::UnsafeSharedMemoryRegion::Deserialize( + UnwrapPlatformSharedMemoryRegion(std::move(handle))); +} + +base::WritableSharedMemoryRegion UnwrapWritableSharedMemoryRegion( + ScopedSharedBufferHandle handle) { + // TODO(https://crbug.com/826213): Support unwrapping writable regions. See + // comment in |WrapPlatformSharedMemoryRegion()| above. + NOTIMPLEMENTED(); + return base::WritableSharedMemoryRegion(); +} + #if defined(OS_MACOSX) && !defined(OS_IOS) ScopedHandle WrapMachPort(mach_port_t port) { kern_return_t kr = diff --git a/chromium/mojo/public/cpp/system/platform_handle.h b/chromium/mojo/public/cpp/system/platform_handle.h index 1522bf3ea65..2f0cba0707b 100644 --- a/chromium/mojo/public/cpp/system/platform_handle.h +++ b/chromium/mojo/public/cpp/system/platform_handle.h @@ -17,7 +17,10 @@ #include "base/files/file.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/shared_memory_handle.h" +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/memory/writable_shared_memory_region.h" #include "base/process/process_handle.h" #include "mojo/public/c/system/platform_handle.h" #include "mojo/public/cpp/system/buffer.h" @@ -120,6 +123,26 @@ UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle, size_t* size, UnwrappedSharedMemoryHandleProtection* protection); +// Helpers for wrapping and unwrapping new base shared memory API primitives. + +MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle +WrapReadOnlySharedMemoryRegion(base::ReadOnlySharedMemoryRegion region); + +MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle +WrapUnsafeSharedMemoryRegion(base::UnsafeSharedMemoryRegion region); + +MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle +WrapWritableSharedMemoryRegion(base::WritableSharedMemoryRegion region); + +MOJO_CPP_SYSTEM_EXPORT base::ReadOnlySharedMemoryRegion +UnwrapReadOnlySharedMemoryRegion(ScopedSharedBufferHandle handle); + +MOJO_CPP_SYSTEM_EXPORT base::UnsafeSharedMemoryRegion +UnwrapUnsafeSharedMemoryRegion(ScopedSharedBufferHandle handle); + +MOJO_CPP_SYSTEM_EXPORT base::WritableSharedMemoryRegion +UnwrapWritableSharedMemoryRegion(ScopedSharedBufferHandle handle); + #if defined(OS_MACOSX) && !defined(OS_IOS) // Wraps a mach_port_t as a Mojo handle. This takes a reference to the // Mach port. diff --git a/chromium/mojo/public/cpp/system/simple_watcher.cc b/chromium/mojo/public/cpp/system/simple_watcher.cc index 307e28818af..82763f1d32e 100644 --- a/chromium/mojo/public/cpp/system/simple_watcher.cc +++ b/chromium/mojo/public/cpp/system/simple_watcher.cc @@ -11,37 +11,37 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/heap_profiler.h" -#include "mojo/public/c/system/watcher.h" +#include "mojo/public/c/system/trap.h" namespace mojo { -// Thread-safe Context object used to dispatch watch notifications from a -// arbitrary threads. +// Thread-safe Context object used to schedule trap events from arbitrary +// threads. class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { public: - // Creates a |Context| instance for a new watch on |watcher|, to watch - // |handle| for |signals|. + // Creates a |Context| instance for a new watch on |watcher|, to observe + // |signals| on |handle|. static scoped_refptr<Context> Create( base::WeakPtr<SimpleWatcher> watcher, scoped_refptr<base::SequencedTaskRunner> task_runner, - WatcherHandle watcher_handle, + TrapHandle trap_handle, Handle handle, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, int watch_id, - MojoResult* watch_result) { + MojoResult* result) { scoped_refptr<Context> context = new Context(watcher, task_runner, watch_id); - // If MojoWatch succeeds, it assumes ownership of a reference to |context|. - // In that case, this reference is balanced in CallNotify() when |result| is - // |MOJO_RESULT_CANCELLED|. + // If MojoAddTrigger succeeds, it effectively assumes ownership of a + // reference to |context|. In that case, this reference is balanced in + // CallNotify() when |result| is |MOJO_RESULT_CANCELLED|. context->AddRef(); - *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals, - condition, context->value()); - if (*watch_result != MOJO_RESULT_OK) { - // Balanced by the AddRef() above since watching failed. + *result = MojoAddTrigger(trap_handle.value(), handle.value(), signals, + condition, context->value(), nullptr); + if (*result != MOJO_RESULT_OK) { + // Balanced by the AddRef() above since MojoAddTrigger failed. context->Release(); return nullptr; } @@ -49,16 +49,13 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { return context; } - static void CallNotify(uintptr_t context_value, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - auto* context = reinterpret_cast<Context*>(context_value); - context->Notify(result, signals_state, flags); + static void CallNotify(const MojoTrapEvent* event) { + auto* context = reinterpret_cast<Context*>(event->trigger_context); + context->Notify(event->result, event->signals_state, event->flags); - // That was the last notification for the context. We can release the ref - // owned by the watch, which may in turn delete the Context. - if (result == MOJO_RESULT_CANCELLED) + // The trigger was removed. We can release the ref it owned, which in turn + // may delete the Context. + if (event->result == MOJO_RESULT_CANCELLED) context->Release(); } @@ -82,9 +79,9 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { void Notify(MojoResult result, MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { + MojoTrapEventFlags flags) { if (result == MOJO_RESULT_CANCELLED) { - // The SimpleWatcher may have explicitly cancelled this watch, so we don't + // The SimpleWatcher may have explicitly removed this trigger, so we don't // bother dispatching the notification - it would be ignored anyway. // // TODO(rockot): This shouldn't really be necessary, but there are already @@ -98,7 +95,7 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { HandleSignalsState state(signals_state.satisfied_signals, signals_state.satisfiable_signals); - if ((flags & MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM) && + if (!(flags & MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL) && task_runner_->RunsTasksInCurrentSequence() && weak_watcher_ && weak_watcher_->is_default_task_runner_) { // System notifications will trigger from the task runner passed to @@ -132,7 +129,7 @@ SimpleWatcher::SimpleWatcher(const base::Location& from_here, base::ThreadTaskRunnerHandle::Get()), heap_profiler_tag_(from_here.file_name()), weak_factory_(this) { - MojoResult rv = CreateWatcher(&Context::CallNotify, &watcher_handle_); + MojoResult rv = CreateTrap(&Context::CallNotify, &trap_handle_); DCHECK_EQ(MOJO_RESULT_OK, rv); DCHECK(task_runner_->RunsTasksInCurrentSequence()); } @@ -149,7 +146,7 @@ bool SimpleWatcher::IsWatching() const { MojoResult SimpleWatcher::Watch(Handle handle, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, const ReadyCallbackWithState& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!IsWatching()); @@ -159,15 +156,15 @@ MojoResult SimpleWatcher::Watch(Handle handle, handle_ = handle; watch_id_ += 1; - MojoResult watch_result = MOJO_RESULT_UNKNOWN; + MojoResult result = MOJO_RESULT_UNKNOWN; context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_, - watcher_handle_.get(), handle_, signals, condition, - watch_id_, &watch_result); + trap_handle_.get(), handle_, signals, condition, + watch_id_, &result); if (!context_) { handle_.set_value(kInvalidHandleValue); callback_.Reset(); - DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, watch_result); - return watch_result; + DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, result); + return result; } if (arming_policy_ == ArmingPolicy::AUTOMATIC) @@ -191,13 +188,13 @@ void SimpleWatcher::Cancel() { handle_.set_value(kInvalidHandleValue); callback_.Reset(); - // Ensure |context_| is unset by the time we call MojoCancelWatch, as may + // Ensure |context_| is unset by the time we call MojoRemoveTrigger, as it may // re-enter the notification callback and we want to ensure |context_| is // unset by then. scoped_refptr<Context> context; std::swap(context, context_); MojoResult rv = - MojoCancelWatch(watcher_handle_.get().value(), context->value()); + MojoRemoveTrigger(trap_handle_.get().value(), context->value(), nullptr); // It's possible this cancellation could race with a handle closure // notification, in which case the watch may have already been implicitly @@ -215,9 +212,9 @@ MojoResult SimpleWatcher::Arm(MojoResult* ready_result, if (!ready_state) ready_state = &local_ready_state; MojoResult rv = - MojoArmWatcher(watcher_handle_.get().value(), &num_ready_contexts, - &ready_context, &local_ready_result, - reinterpret_cast<MojoHandleSignalsState*>(ready_state)); + MojoArmTrap(trap_handle_.get().value(), nullptr, &num_ready_contexts, + &ready_context, &local_ready_result, + reinterpret_cast<MojoHandleSignalsState*>(ready_state)); if (rv == MOJO_RESULT_FAILED_PRECONDITION) { DCHECK(context_); DCHECK_EQ(1u, num_ready_contexts); @@ -277,13 +274,10 @@ void SimpleWatcher::OnHandleReady(int watch_id, if (!weak_self) return; - if (unsatisfiable_) - return; - // Prevent |MOJO_RESULT_FAILED_PRECONDITION| task spam by only notifying // at most once in AUTOMATIC arming mode. if (result == MOJO_RESULT_FAILED_PRECONDITION) - unsatisfiable_ = true; + return; if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching()) ArmOrNotify(); diff --git a/chromium/mojo/public/cpp/system/simple_watcher.h b/chromium/mojo/public/cpp/system/simple_watcher.h index 87026891f19..cc916c88019 100644 --- a/chromium/mojo/public/cpp/system/simple_watcher.h +++ b/chromium/mojo/public/cpp/system/simple_watcher.h @@ -16,7 +16,7 @@ #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/handle_signals_state.h" #include "mojo/public/cpp/system/system_export.h" -#include "mojo/public/cpp/system/watcher.h" +#include "mojo/public/cpp/system/trap.h" namespace base { class SequencedTaskRunner; @@ -119,7 +119,7 @@ class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher { // Destroying the SimpleWatcher implicitly calls |Cancel()|. MojoResult Watch(Handle handle, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, const ReadyCallbackWithState& callback); // DEPRECATED: Please use the above signature instead. @@ -211,7 +211,7 @@ class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher { // base::SequencedTaskRunnerHandle::Get() for the thread. const bool is_default_task_runner_; - ScopedWatcherHandle watcher_handle_; + ScopedTrapHandle trap_handle_; // A thread-safe context object corresponding to the currently active watch, // if any. @@ -229,10 +229,6 @@ class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher { // The callback to call when the handle is signaled. ReadyCallbackWithState callback_; - // Tracks if the SimpleWatcher has already notified of unsatisfiability. This - // is used to prevent redundant notifications in AUTOMATIC mode. - bool unsatisfiable_ = false; - // Tag used to ID memory allocations that originated from notifications in // this watcher. const char* heap_profiler_tag_ = nullptr; diff --git a/chromium/mojo/public/cpp/system/string_data_pipe_producer.cc b/chromium/mojo/public/cpp/system/string_data_pipe_producer.cc index b8409506dd6..6b36b8ec06f 100644 --- a/chromium/mojo/public/cpp/system/string_data_pipe_producer.cc +++ b/chromium/mojo/public/cpp/system/string_data_pipe_producer.cc @@ -58,7 +58,9 @@ MojoResult WriteDataToProducerHandle(DataPipeProducerHandle producer, StringDataPipeProducer::StringDataPipeProducer( ScopedDataPipeProducerHandle producer) : producer_(std::move(producer)), - watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC), + watcher_(FROM_HERE, + SimpleWatcher::ArmingPolicy::AUTOMATIC, + base::SequencedTaskRunnerHandle::Get()), weak_factory_(this) {} StringDataPipeProducer::~StringDataPipeProducer() = default; diff --git a/chromium/mojo/public/cpp/system/tests/BUILD.gn b/chromium/mojo/public/cpp/system/tests/BUILD.gn index 7acc44b1e4e..6a2fc59652e 100644 --- a/chromium/mojo/public/cpp/system/tests/BUILD.gn +++ b/chromium/mojo/public/cpp/system/tests/BUILD.gn @@ -7,6 +7,7 @@ source_set("tests") { sources = [ "core_unittest.cc", + "data_pipe_drainer_unittest.cc", "file_data_pipe_producer_unittest.cc", "handle_signal_tracker_unittest.cc", "handle_signals_state_unittest.cc", diff --git a/chromium/mojo/public/cpp/system/watcher.cc b/chromium/mojo/public/cpp/system/trap.cc index 0c62ba8e201..65154c12d0a 100644 --- a/chromium/mojo/public/cpp/system/watcher.cc +++ b/chromium/mojo/public/cpp/system/trap.cc @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/public/cpp/system/watcher.h" +#include "mojo/public/cpp/system/trap.h" #include "mojo/public/c/system/functions.h" namespace mojo { -MojoResult CreateWatcher(MojoWatcherCallback callback, - ScopedWatcherHandle* watcher_handle) { +MojoResult CreateTrap(MojoTrapEventHandler handler, + ScopedTrapHandle* trap_handle) { MojoHandle handle; - MojoResult rv = MojoCreateWatcher(callback, &handle); + MojoResult rv = MojoCreateTrap(handler, nullptr, &handle); if (rv == MOJO_RESULT_OK) - watcher_handle->reset(WatcherHandle(handle)); + trap_handle->reset(TrapHandle(handle)); return rv; } diff --git a/chromium/mojo/public/cpp/system/trap.h b/chromium/mojo/public/cpp/system/trap.h new file mode 100644 index 00000000000..5414aaf2858 --- /dev/null +++ b/chromium/mojo/public/cpp/system/trap.h @@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_SYSTEM_TRAP_H_ +#define MOJO_PUBLIC_CPP_SYSTEM_TRAP_H_ + +#include "mojo/public/c/system/trap.h" +#include "mojo/public/c/system/types.h" +#include "mojo/public/cpp/system/handle.h" +#include "mojo/public/cpp/system/system_export.h" + +namespace mojo { + +// A strongly-typed representation of a |MojoHandle| for a trap. +class TrapHandle : public Handle { + public: + TrapHandle() = default; + explicit TrapHandle(MojoHandle value) : Handle(value) {} + + // Copying and assignment allowed. +}; + +static_assert(sizeof(TrapHandle) == sizeof(Handle), + "Bad size for C++ TrapHandle"); + +typedef ScopedHandleBase<TrapHandle> ScopedTrapHandle; +static_assert(sizeof(ScopedTrapHandle) == sizeof(TrapHandle), + "Bad size for C++ ScopedTrapHandle"); + +MOJO_CPP_SYSTEM_EXPORT MojoResult CreateTrap(MojoTrapEventHandler handler, + ScopedTrapHandle* trap_handle); + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_SYSTEM_TRAP_H_ diff --git a/chromium/mojo/public/cpp/system/wait.cc b/chromium/mojo/public/cpp/system/wait.cc index 4f00587af81..a1aa4bc16c0 100644 --- a/chromium/mojo/public/cpp/system/wait.cc +++ b/chromium/mojo/public/cpp/system/wait.cc @@ -10,15 +10,15 @@ #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/synchronization/waitable_event.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/watcher.h" +#include "mojo/public/c/system/trap.h" +#include "mojo/public/cpp/system/trap.h" namespace mojo { namespace { -class WatchContext : public base::RefCountedThreadSafe<WatchContext> { +class TriggerContext : public base::RefCountedThreadSafe<TriggerContext> { public: - WatchContext() + TriggerContext() : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED) {} @@ -27,22 +27,19 @@ class WatchContext : public base::RefCountedThreadSafe<WatchContext> { MojoHandleSignalsState wait_state() const { return wait_state_; } uintptr_t context_value() const { return reinterpret_cast<uintptr_t>(this); } - static void OnNotification(uintptr_t context_value, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - auto* context = reinterpret_cast<WatchContext*>(context_value); - context->Notify(result, state); - if (result == MOJO_RESULT_CANCELLED) { + static void OnNotification(const MojoTrapEvent* event) { + auto* context = reinterpret_cast<TriggerContext*>(event->trigger_context); + context->Notify(event->result, event->signals_state); + if (event->result == MOJO_RESULT_CANCELLED) { // Balanced in Wait() or WaitMany(). context->Release(); } } private: - friend class base::RefCountedThreadSafe<WatchContext>; + friend class base::RefCountedThreadSafe<TriggerContext>; - ~WatchContext() {} + ~TriggerContext() {} void Notify(MojoResult result, MojoHandleSignalsState state) { if (wait_result_ == MOJO_RESULT_UNKNOWN) { @@ -57,32 +54,32 @@ class WatchContext : public base::RefCountedThreadSafe<WatchContext> { // NOTE: Although these are modified in Notify() which may be called from any // sequence, Notify() is guaranteed to never run concurrently with itself. // Furthermore, they are only modified once, before |event_| signals; so there - // is no need for a WatchContext user to synchronize access to these fields + // is no need for a TriggerContext user to synchronize access to these fields // apart from waiting on |event()|. MojoResult wait_result_ = MOJO_RESULT_UNKNOWN; MojoHandleSignalsState wait_state_ = {0, 0}; - DISALLOW_COPY_AND_ASSIGN(WatchContext); + DISALLOW_COPY_AND_ASSIGN(TriggerContext); }; } // namespace MojoResult Wait(Handle handle, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, MojoHandleSignalsState* signals_state) { - ScopedWatcherHandle watcher; - MojoResult rv = CreateWatcher(&WatchContext::OnNotification, &watcher); + ScopedTrapHandle trap; + MojoResult rv = CreateTrap(&TriggerContext::OnNotification, &trap); DCHECK_EQ(MOJO_RESULT_OK, rv); - scoped_refptr<WatchContext> context = new WatchContext; + scoped_refptr<TriggerContext> context = new TriggerContext; - // Balanced in WatchContext::OnNotification if MojoWatch() is successful. - // Otherwise balanced immediately below. + // Balanced in TriggerContext::OnNotification if MojoAddTrigger() is + // successful. Otherwise balanced immediately below. context->AddRef(); - rv = MojoWatch(watcher.get().value(), handle.value(), signals, condition, - context->context_value()); + rv = MojoAddTrigger(trap.get().value(), handle.value(), signals, condition, + context->context_value(), nullptr); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { // Balanced above. context->Release(); @@ -94,8 +91,8 @@ MojoResult Wait(Handle handle, uintptr_t ready_context; MojoResult ready_result; MojoHandleSignalsState ready_state; - rv = MojoArmWatcher(watcher.get().value(), &num_ready_contexts, - &ready_context, &ready_result, &ready_state); + rv = MojoArmTrap(trap.get().value(), nullptr, &num_ready_contexts, + &ready_context, &ready_result, &ready_state); if (rv == MOJO_RESULT_FAILED_PRECONDITION) { DCHECK_EQ(1u, num_ready_contexts); if (signals_state) @@ -123,22 +120,23 @@ MojoResult WaitMany(const Handle* handles, if (!handles || !signals) return MOJO_RESULT_INVALID_ARGUMENT; - ScopedWatcherHandle watcher; - MojoResult rv = CreateWatcher(&WatchContext::OnNotification, &watcher); + ScopedTrapHandle trap; + MojoResult rv = CreateTrap(&TriggerContext::OnNotification, &trap); DCHECK_EQ(MOJO_RESULT_OK, rv); - std::vector<scoped_refptr<WatchContext>> contexts(num_handles); + std::vector<scoped_refptr<TriggerContext>> contexts(num_handles); std::vector<base::WaitableEvent*> events(num_handles); for (size_t i = 0; i < num_handles; ++i) { - contexts[i] = new WatchContext(); + contexts[i] = new TriggerContext(); - // Balanced in WatchContext::OnNotification if MojoWatch() is successful. - // Otherwise balanced immediately below. + // Balanced in TriggerContext::OnNotification if MojoAddTrigger() is + // successful. Otherwise balanced immediately below. contexts[i]->AddRef(); MojoResult rv = - MojoWatch(watcher.get().value(), handles[i].value(), signals[i], - MOJO_WATCH_CONDITION_SATISFIED, contexts[i]->context_value()); + MojoAddTrigger(trap.get().value(), handles[i].value(), signals[i], + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, + contexts[i]->context_value(), nullptr); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { if (result_index) *result_index = i; @@ -156,8 +154,8 @@ MojoResult WaitMany(const Handle* handles, uintptr_t ready_context = 0; MojoResult ready_result = MOJO_RESULT_UNKNOWN; MojoHandleSignalsState ready_state{0, 0}; - rv = MojoArmWatcher(watcher.get().value(), &num_ready_contexts, - &ready_context, &ready_result, &ready_state); + rv = MojoArmTrap(trap.get().value(), nullptr, &num_ready_contexts, + &ready_context, &ready_result, &ready_state); size_t index = num_handles; if (rv == MOJO_RESULT_FAILED_PRECONDITION) { diff --git a/chromium/mojo/public/cpp/system/wait.h b/chromium/mojo/public/cpp/system/wait.h index ccd6ebe762e..651a37f1696 100644 --- a/chromium/mojo/public/cpp/system/wait.h +++ b/chromium/mojo/public/cpp/system/wait.h @@ -7,6 +7,7 @@ #include <stddef.h> +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/system_export.h" @@ -35,15 +36,16 @@ namespace mojo { MOJO_CPP_SYSTEM_EXPORT MojoResult Wait(Handle handle, MojoHandleSignals signals, - MojoWatchCondition condition, + MojoTriggerCondition condition, MojoHandleSignalsState* signals_state = nullptr); // A pseudonym for the above Wait() which always waits on -// |MOJO_WATCH_CONDITION_SATISFIED|. +// |MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED|. inline MojoResult Wait(Handle handle, MojoHandleSignals signals, MojoHandleSignalsState* signals_state = nullptr) { - return Wait(handle, signals, MOJO_WATCH_CONDITION_SATISFIED, signals_state); + return Wait(handle, signals, MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, + signals_state); } // Waits on |handles[0]|, ..., |handles[num_handles-1]| until: diff --git a/chromium/mojo/public/cpp/system/wait_set.cc b/chromium/mojo/public/cpp/system/wait_set.cc index e2a26f8a900..3ad98409160 100644 --- a/chromium/mojo/public/cpp/system/wait_set.cc +++ b/chromium/mojo/public/cpp/system/wait_set.cc @@ -16,7 +16,7 @@ #include "base/memory/ptr_util.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" -#include "mojo/public/cpp/system/watcher.h" +#include "mojo/public/cpp/system/trap.h" namespace mojo { @@ -25,13 +25,13 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { State() : handle_event_(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED) { - MojoResult rv = CreateWatcher(&Context::OnNotification, &watcher_handle_); + MojoResult rv = CreateTrap(&Context::OnNotification, &trap_handle_); DCHECK_EQ(MOJO_RESULT_OK, rv); } void ShutDown() { // NOTE: This may immediately invoke Notify for every context. - watcher_handle_.reset(); + trap_handle_.reset(); cancelled_contexts_.clear(); } @@ -52,7 +52,7 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { } MojoResult AddHandle(Handle handle, MojoHandleSignals signals) { - DCHECK(watcher_handle_.is_valid()); + DCHECK(trap_handle_.is_valid()); scoped_refptr<Context> context = new Context(this, handle); @@ -68,14 +68,15 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { } // Balanced in State::Notify() with MOJO_RESULT_CANCELLED if - // MojoWatch() succeeds. Otherwise balanced immediately below. + // MojoAddTrigger() succeeds. Otherwise balanced immediately below. context->AddRef(); // This can notify immediately if the watcher is already armed. Don't hold // |lock_| while calling it. MojoResult rv = - MojoWatch(watcher_handle_.get().value(), handle.value(), signals, - MOJO_WATCH_CONDITION_SATISFIED, context->context_value()); + MojoAddTrigger(trap_handle_.get().value(), handle.value(), signals, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, + context->context_value(), nullptr); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { base::AutoLock lock(lock_); handle_to_context_.erase(handle); @@ -91,7 +92,7 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { } MojoResult RemoveHandle(Handle handle) { - DCHECK(watcher_handle_.is_valid()); + DCHECK(trap_handle_.is_valid()); scoped_refptr<Context> context; { @@ -116,8 +117,8 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { // NOTE: This may enter the notification callback immediately, so don't hold // |lock_| while calling it. - MojoResult rv = MojoCancelWatch(watcher_handle_.get().value(), - context->context_value()); + MojoResult rv = MojoRemoveTrigger(trap_handle_.get().value(), + context->context_value(), nullptr); // We don't really care whether or not this succeeds. In either case, the // context was or will imminently be cancelled and moved from |contexts_| @@ -132,7 +133,7 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { Handle* ready_handles, MojoResult* ready_results, MojoHandleSignalsState* signals_states) { - DCHECK(watcher_handle_.is_valid()); + DCHECK(trap_handle_.is_valid()); DCHECK(num_ready_handles); DCHECK(ready_handles); DCHECK(ready_results); @@ -152,13 +153,13 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { MojoHandleSignalsState* out_states = signals_states; if (!out_states) { // If the caller didn't provide a buffer for signal states, we provide - // our own locally. MojoArmWatcher() requires one if we want to handle + // our own locally. MojoArmTrap() requires one if we want to handle // arming failure properly. ready_states.container().resize(num_ready_contexts); out_states = ready_states.container().data(); } - MojoResult rv = MojoArmWatcher( - watcher_handle_.get().value(), &num_ready_contexts, + MojoResult rv = MojoArmTrap( + trap_handle_.get().value(), nullptr, &num_ready_contexts, ready_contexts.container().data(), ready_results, out_states); if (rv == MOJO_RESULT_FAILED_PRECONDITION) { @@ -242,11 +243,9 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { return reinterpret_cast<uintptr_t>(this); } - static void OnNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - reinterpret_cast<Context*>(context)->Notify(result, signals_state); + static void OnNotification(const MojoTrapEvent* event) { + reinterpret_cast<Context*>(event->trigger_context) + ->Notify(event->result, event->signals_state); } private: @@ -315,7 +314,7 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> { // Not guarded by lock. Must only be accessed from the WaitSet's owning // sequence. - ScopedWatcherHandle watcher_handle_; + ScopedTrapHandle trap_handle_; base::Lock lock_; std::map<uintptr_t, scoped_refptr<Context>> contexts_; diff --git a/chromium/mojo/public/cpp/system/wait_set.h b/chromium/mojo/public/cpp/system/wait_set.h index 46d6b7df430..efb54dea39d 100644 --- a/chromium/mojo/public/cpp/system/wait_set.h +++ b/chromium/mojo/public/cpp/system/wait_set.h @@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "mojo/public/c/system/trap.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/system_export.h" diff --git a/chromium/mojo/public/cpp/system/watcher.h b/chromium/mojo/public/cpp/system/watcher.h deleted file mode 100644 index d0a257814d7..00000000000 --- a/chromium/mojo/public/cpp/system/watcher.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ - -#include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace mojo { - -// A strongly-typed representation of a |MojoHandle| for a watcher. -class WatcherHandle : public Handle { - public: - WatcherHandle() = default; - explicit WatcherHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. -}; - -static_assert(sizeof(WatcherHandle) == sizeof(Handle), - "Bad size for C++ WatcherHandle"); - -typedef ScopedHandleBase<WatcherHandle> ScopedWatcherHandle; -static_assert(sizeof(ScopedWatcherHandle) == sizeof(WatcherHandle), - "Bad size for C++ ScopedWatcherHandle"); - -MOJO_CPP_SYSTEM_EXPORT MojoResult -CreateWatcher(MojoWatcherCallback callback, - ScopedWatcherHandle* watcher_handle); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ diff --git a/chromium/mojo/public/interfaces/bindings/tests/echo.mojom b/chromium/mojo/public/interfaces/bindings/tests/echo.mojom index 545c5c9cabe..1418e3d272a 100644 --- a/chromium/mojo/public/interfaces/bindings/tests/echo.mojom +++ b/chromium/mojo/public/interfaces/bindings/tests/echo.mojom @@ -4,7 +4,7 @@ module test.echo.mojom; -import "echo_import/echo_import.mojom"; +import "mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom"; interface Echo { EchoPoint(test.echo_import.mojom.Point point) diff --git a/chromium/mojo/public/interfaces/bindings/tests/sample_factory.mojom b/chromium/mojo/public/interfaces/bindings/tests/sample_factory.mojom index ade3bf37d65..cb718afd766 100644 --- a/chromium/mojo/public/interfaces/bindings/tests/sample_factory.mojom +++ b/chromium/mojo/public/interfaces/bindings/tests/sample_factory.mojom @@ -5,7 +5,7 @@ [JavaPackage="org.chromium.mojo.bindings.test.mojom.sample"] module sample; -import "sample_import.mojom"; +import "mojo/public/interfaces/bindings/tests/sample_import.mojom"; // This sample shows how handles to MessagePipes can be sent as both parameters // to methods as well as fields on structs. diff --git a/chromium/mojo/public/interfaces/bindings/tests/sample_import2.mojom b/chromium/mojo/public/interfaces/bindings/tests/sample_import2.mojom index ca4e81c0bb6..a8c909a3c2c 100644 --- a/chromium/mojo/public/interfaces/bindings/tests/sample_import2.mojom +++ b/chromium/mojo/public/interfaces/bindings/tests/sample_import2.mojom @@ -5,7 +5,7 @@ [JavaPackage="org.chromium.mojo.bindings.test.mojom.imported"] module imported; -import "sample_import.mojom"; +import "mojo/public/interfaces/bindings/tests/sample_import.mojom"; // This sample adds more types and constants to the "imported" namespace, // to test a bug with importing multiple modules with the same namespace. diff --git a/chromium/mojo/public/interfaces/bindings/tests/sample_service.mojom b/chromium/mojo/public/interfaces/bindings/tests/sample_service.mojom index 761cb91a9b5..62ff1a8b7ed 100644 --- a/chromium/mojo/public/interfaces/bindings/tests/sample_service.mojom +++ b/chromium/mojo/public/interfaces/bindings/tests/sample_service.mojom @@ -6,8 +6,8 @@ [JavaPackage="org.chromium.mojo.bindings.test.mojom.sample"] module sample; -import "sample_import.mojom"; -import "sample_import2.mojom"; +import "mojo/public/interfaces/bindings/tests/sample_import.mojom"; +import "mojo/public/interfaces/bindings/tests/sample_import2.mojom"; const uint8 kTwelve = 12; diff --git a/chromium/mojo/public/java/BUILD.gn b/chromium/mojo/public/java/BUILD.gn index 985916cb0f0..14951f4f095 100644 --- a/chromium/mojo/public/java/BUILD.gn +++ b/chromium/mojo/public/java/BUILD.gn @@ -66,3 +66,13 @@ android_library("bindings_java") { srcjar_deps = [ "../interfaces/bindings:bindings_java_sources" ] } + +android_library("base_java") { + java_files = [ "base/src/org/chromium/mojo_base/BigBufferUtil.java" ] + + deps = [ + ":system_java", + "//mojo/android:system_java", + "//mojo/public/mojom/base:base_java", + ] +} diff --git a/chromium/mojo/public/mojom/base/BUILD.gn b/chromium/mojo/public/mojom/base/BUILD.gn index 51cb4facfcd..acbc8140919 100644 --- a/chromium/mojo/public/mojom/base/BUILD.gn +++ b/chromium/mojo/public/mojom/base/BUILD.gn @@ -8,10 +8,36 @@ mojom_component("base") { sources = [ "big_buffer.mojom", "big_string.mojom", + "file.mojom", + "file_error.mojom", + "file_info.mojom", + "file_path.mojom", + "memory_allocator_dump_cross_process_uid.mojom", + "process_id.mojom", "ref_counted_memory.mojom", + "shared_memory.mojom", "string16.mojom", + "text_direction.mojom", + "thread_priority.mojom", + "time.mojom", + "unguessable_token.mojom", + "values.mojom", ] + if (is_win) { + sources += [ "logfont_win.mojom" ] + } + + if (is_posix && !is_android && !is_fuchsia && !is_mac) { + enabled_features = [ "shared_memory_region_uses_fd_pair" ] + } + output_prefix = "mojo_base_mojom" macro_prefix = "MOJO_BASE_MOJOM" } + +mojom("read_only_buffer") { + sources = [ + "read_only_buffer.mojom", + ] +} diff --git a/chromium/mojo/common/file.mojom b/chromium/mojo/public/mojom/base/file.mojom index fe224734d94..824ebb1f133 100644 --- a/chromium/mojo/common/file.mojom +++ b/chromium/mojo/public/mojom/base/file.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Corresponds to |base::File| in base/files/file.h struct File { diff --git a/chromium/mojo/public/mojom/base/file_error.mojom b/chromium/mojo/public/mojom/base/file_error.mojom new file mode 100644 index 00000000000..3ca61aa91f4 --- /dev/null +++ b/chromium/mojo/public/mojom/base/file_error.mojom @@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo_base.mojom; + +// Error codes used by the file system. These error codes line up exactly with +// those of base::File and are typemapped to base::File::Error enum. +enum FileError { + OK = 0, + FAILED = -1, + IN_USE = -2, + EXISTS = -3, + NOT_FOUND = -4, + ACCESS_DENIED = -5, + TOO_MANY_OPENED = -6, + NO_MEMORY = -7, + NO_SPACE = -8, + NOT_A_DIRECTORY = -9, + INVALID_OPERATION = -10, + SECURITY = -11, + ABORT = -12, + NOT_A_FILE = -13, + NOT_EMPTY = -14, + INVALID_URL = -15, + IO = -16, +}; diff --git a/chromium/mojo/common/file_info.mojom b/chromium/mojo/public/mojom/base/file_info.mojom index 9777a2a63cf..544f2914387 100644 --- a/chromium/mojo/common/file_info.mojom +++ b/chromium/mojo/public/mojom/base/file_info.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; [Native] struct FileInfo; diff --git a/chromium/mojo/common/file_path.mojom b/chromium/mojo/public/mojom/base/file_path.mojom index 10ebe058be8..cbe0bbe4a5d 100644 --- a/chromium/mojo/common/file_path.mojom +++ b/chromium/mojo/public/mojom/base/file_path.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; [Native] struct FilePath; diff --git a/chromium/mojo/common/logfont_win.mojom b/chromium/mojo/public/mojom/base/logfont_win.mojom index 71d60eab02d..81beefad726 100644 --- a/chromium/mojo/common/logfont_win.mojom +++ b/chromium/mojo/public/mojom/base/logfont_win.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Native Windows struct. Its typemap only exists for windows builds. [Native] diff --git a/chromium/mojo/common/memory_allocator_dump_cross_process_uid.mojom b/chromium/mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom index 6a254f77e5f..6091d792936 100644 --- a/chromium/mojo/common/memory_allocator_dump_cross_process_uid.mojom +++ b/chromium/mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Corresponds to |base::trace_event::MemoryAllocatorDumpGuid| in base/trace_event/memory_allocator_dump_guid.h -// TODO(ssid): MemoryAllocatorDumpGUID should be renamed. crbug.com/732653 struct MemoryAllocatorDumpCrossProcessUid { uint64 value; }; diff --git a/chromium/mojo/common/process_id.mojom b/chromium/mojo/public/mojom/base/process_id.mojom index d72fe6eb96f..f3b17780a51 100644 --- a/chromium/mojo/common/process_id.mojom +++ b/chromium/mojo/public/mojom/base/process_id.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; struct ProcessId { // This is the storage for the pid, on windows the pid is a DWORD and the diff --git a/chromium/mojo/common/read_only_buffer.mojom b/chromium/mojo/public/mojom/base/read_only_buffer.mojom index 19d08ce42b9..924f19ec821 100644 --- a/chromium/mojo/common/read_only_buffer.mojom +++ b/chromium/mojo/public/mojom/base/read_only_buffer.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // This struct is typemapped to base::span<const uint8_t>. // Note: At the receiving end, this base::span<const uint8_t> refers to a memory diff --git a/chromium/mojo/public/mojom/base/shared_memory.mojom b/chromium/mojo/public/mojom/base/shared_memory.mojom new file mode 100644 index 00000000000..e11ed2d7535 --- /dev/null +++ b/chromium/mojo/public/mojom/base/shared_memory.mojom @@ -0,0 +1,59 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo_base.mojom; + +import "mojo/public/mojom/base/unguessable_token.mojom"; + +// Mirrors the base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle +// type. +// +// TODO(https://crbug.com/826213): Remove this once Mojo shared buffers are +// properly backed by base::subtle::PlatformSharedMemoryRegion. +struct PlatformSharedMemoryHandle { + handle handle_value; + + [EnableIf=shared_memory_region_uses_fd_pair] + handle? readonly_fd; +}; + +// Mirrors the base::subtle::PlatformSharedMemoryRegion type. +// +// This should not be used directly. Use one of the specific region types below +// instead. +// +// TODO(https://crbug.com/826213): Remove this once Mojo shared buffers are +// properly backed by base::subtle::PlatformSharedMemoryRegion. +struct PlatformSharedMemoryRegion { + enum Mode { + kReadOnly, + kWritable, + kUnsafe, + }; + + PlatformSharedMemoryHandle platform_handle; + Mode mode; + uint64 size; + UnguessableToken guid; +}; + +// Wraps a shared memory handle with additional type information to convey that +// the handle is only mappable to read-only memory. +struct ReadOnlySharedMemoryRegion { + PlatformSharedMemoryRegion region; +}; + +// Wraps a shared memory handle with additional type information to convey that +// the handle is mappable to writable memory but can also be converted to +// a ReadOnlySharedMemoryRegion for sharing with other clients. +struct WritableSharedMemoryRegion { + PlatformSharedMemoryRegion region; +}; + +// Wraps a shared memory handle with additional type information to convey that +// the handle is always mappable to writable memory by any client which obtains +// a handle duplicated from this one. +struct UnsafeSharedMemoryRegion { + PlatformSharedMemoryRegion region; +}; diff --git a/chromium/mojo/common/text_direction.mojom b/chromium/mojo/public/mojom/base/text_direction.mojom index 7d651245eda..999ff3e58c2 100644 --- a/chromium/mojo/common/text_direction.mojom +++ b/chromium/mojo/public/mojom/base/text_direction.mojom @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Corresponds to |base::i18n::TextDirection| in base/i18n/rtl.h -enum TextDirection { - UNKNOWN_DIRECTION, - RIGHT_TO_LEFT, - LEFT_TO_RIGHT -}; +enum TextDirection { + UNKNOWN_DIRECTION, + RIGHT_TO_LEFT, + LEFT_TO_RIGHT +}; diff --git a/chromium/mojo/common/thread_priority.mojom b/chromium/mojo/public/mojom/base/thread_priority.mojom index c3ebb468fad..21d7f343765 100644 --- a/chromium/mojo/common/thread_priority.mojom +++ b/chromium/mojo/public/mojom/base/thread_priority.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Corresponds to |base::ThreadPriority| enum ThreadPriority { diff --git a/chromium/mojo/common/time.mojom b/chromium/mojo/public/mojom/base/time.mojom index b403bcac3a6..78cde1a1671 100644 --- a/chromium/mojo/common/time.mojom +++ b/chromium/mojo/public/mojom/base/time.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; struct Time { // The internal value is expressed in terms of microseconds since a fixed but diff --git a/chromium/mojo/common/unguessable_token.mojom b/chromium/mojo/public/mojom/base/unguessable_token.mojom index 32797171caf..42aa7e21571 100644 --- a/chromium/mojo/common/unguessable_token.mojom +++ b/chromium/mojo/public/mojom/base/unguessable_token.mojom @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module mojo.common.mojom; +module mojo_base.mojom; // Corresponds to |base::UnguessableToken| in base/unguessable_token.h struct UnguessableToken { diff --git a/chromium/mojo/public/mojom/base/values.mojom b/chromium/mojo/public/mojom/base/values.mojom new file mode 100644 index 00000000000..ea7c1fa590f --- /dev/null +++ b/chromium/mojo/public/mojom/base/values.mojom @@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo_base.mojom; + +// Value represents a value that can be serialized to/from JSON. +// +// One notable caveat is that Value supports arbitrary binary data, which JSON +// does not support natively. +union Value { + // Null type placeholder. This field is never used. + uint8 null_value; + // Primitive types. + bool bool_value; + int32 int_value; + double double_value; + // Unicode string. + string string_value; + // Binary blob with arbitrary bytes. Not supported for JSON. + array<uint8> binary_value; + // Basic container support for lists and maps. + DictionaryValue dictionary_value; + ListValue list_value; +}; + +// Interfaces that only want to handle a value of dictionary or list type +// should use base.mojom.DictionaryValue or base.mojom.ListValue in the method +// declaration. Though both of these types are mapped to base::Value in C++, +// the generated deserialization will guarantee that the method is only invoked +// with a base::Value of the correct subtype. +struct DictionaryValue { + map<string, Value> storage; +}; + +struct ListValue { + array<Value> storage; +}; diff --git a/chromium/mojo/public/tools/bindings/BUILD.gn b/chromium/mojo/public/tools/bindings/BUILD.gn index 3c9386bc9bf..371a453f0ed 100644 --- a/chromium/mojo/public/tools/bindings/BUILD.gn +++ b/chromium/mojo/public/tools/bindings/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//mojo/public/tools/bindings/mojom.gni") +import("//third_party/jinja2/jinja2.gni") action("precompile_templates") { sources = mojom_generator_sources @@ -57,6 +58,9 @@ action("precompile_templates") { "$mojom_generator_root/generators/java_templates/struct.java.tmpl", "$mojom_generator_root/generators/java_templates/union.java.tmpl", "$mojom_generator_root/generators/js_templates/enum_definition.tmpl", + "$mojom_generator_root/generators/js_templates/externs/interface_definition.tmpl", + "$mojom_generator_root/generators/js_templates/externs/module.externs.tmpl", + "$mojom_generator_root/generators/js_templates/externs/struct_definition.tmpl", "$mojom_generator_root/generators/js_templates/interface_definition.tmpl", "$mojom_generator_root/generators/js_templates/module.amd.tmpl", "$mojom_generator_root/generators/js_templates/module_definition.tmpl", @@ -65,6 +69,8 @@ action("precompile_templates") { "$mojom_generator_root/generators/js_templates/validation_macros.tmpl", ] script = mojom_generator_script + + inputs = jinja2_sources outputs = [ "$target_gen_dir/cpp_templates.zip", "$target_gen_dir/java_templates.zip", diff --git a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni index a6edb9746df..2825b314a75 100644 --- a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni +++ b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni @@ -8,9 +8,9 @@ for_blink = true _typemap_imports = [ "//mojo/public/cpp/bindings/tests/blink_typemaps.gni", - "//third_party/WebKit/Source/platform/mojo/blink_typemaps.gni", - "//third_party/WebKit/public/blink_typemaps.gni", - "//third_party/WebKit/public/public_typemaps.gni", + "//third_party/blink/renderer/platform/mojo/blink_typemaps.gni", + "//third_party/blink/public/blink_typemaps.gni", + "//third_party/blink/public/public_typemaps.gni", ] _typemaps = [] diff --git a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni index c9a3ab509a3..19804b4dd6e 100644 --- a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni @@ -8,6 +8,7 @@ _typemap_imports = [ "//chrome/common/importer/typemaps.gni", "//chrome/common/media_router/mojo/typemaps.gni", "//chrome/typemaps.gni", + "//chromeos/services/device_sync/public/mojom/typemaps.gni", "//components/arc/common/typemaps.gni", "//components/metrics/public/cpp/typemaps.gni", "//components/sync/mojo/typemaps.gni", @@ -18,9 +19,10 @@ _typemap_imports = [ "//content/common/typemaps.gni", "//content/public/common/typemaps.gni", "//device/bluetooth/public/mojom/typemaps.gni", + "//device/bluetooth/public/mojom/test/typemaps.gni", "//device/gamepad/public/mojom/typemaps.gni", "//gpu/ipc/common/typemaps.gni", - "//media/capture/mojo/typemaps.gni", + "//media/capture/mojom/typemaps.gni", "//media/mojo/interfaces/typemaps.gni", "//mojo/common/typemaps.gni", "//mojo/public/cpp/base/typemaps.gni", @@ -41,8 +43,9 @@ _typemap_imports = [ "//services/viz/privileged/interfaces/compositing/typemaps.gni", "//services/viz/public/cpp/compositing/typemaps.gni", "//skia/public/interfaces/typemaps.gni", - "//third_party/WebKit/common/typemaps.gni", - "//third_party/WebKit/public/public_typemaps.gni", + "//third_party/blink/common/typemaps.gni", + "//third_party/blink/public/public_typemaps.gni", + "//ui/accessibility/mojom/typemaps.gni", "//ui/base/mojo/typemaps.gni", "//ui/display/mojo/typemaps.gni", "//ui/events/devices/mojo/typemaps.gni", diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl index c334a52f983..d2416ab8c09 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl @@ -12,6 +12,12 @@ enum class {{enum_name}} : int32_t { {{field.name}}, {%- endif %} {%- endfor %} +{%- if enum.min_value is not none %} + kMinValue = {{enum.min_value}}, +{%- endif %} +{%- if enum.max_value is not none %} + kMaxValue = {{enum.max_value}}, +{%- endif %} }; inline std::ostream& operator<<(std::ostream& os, {{enum_name}} value) { diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index dd6fdf5db26..a4eda9a1ab8 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl @@ -212,8 +212,13 @@ class {{class_name}}_{{method.name}}_ProxyToResponder { std::unique_ptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy( new {{class_name}}_{{method.name}}_ProxyToResponder( request_id, is_sync, std::move(responder))); +{%- if use_once_callback %} + return base::BindOnce(&{{class_name}}_{{method.name}}_ProxyToResponder::Run, + std::move(proxy)); +{%- else %} return base::Bind(&{{class_name}}_{{method.name}}_ProxyToResponder::Run, base::Passed(&proxy)); +{%- endif %} } ~{{class_name}}_{{method.name}}_ProxyToResponder() { @@ -610,7 +615,11 @@ void {{interface.name}}AsyncWaiter::{{method.name}}( {%- for param in method.parameters -%} std::move({{param.name}}), {%- endfor %} +{%- if use_once_callback %} + base::BindOnce( +{%- else %} base::Bind( +{%- endif %} [](base::RunLoop* loop {%- for param in method.response_parameters -%}, {{param.kind|cpp_wrapper_call_type}}* out_{{param.name}} diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 3d147950c24..f1b22bf7a02 100644 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -43,7 +43,7 @@ namespace {{variant}} { #include "base/macros.h" #include "base/optional.h" -#include "mojo/public/cpp/bindings/mojo_features.h" +#include "mojo/public/cpp/bindings/mojo_buildflags.h" #if BUILDFLAG(MOJO_TRACE_ENABLED) #include "base/trace_event/trace_event.h" #endif @@ -69,10 +69,10 @@ namespace {{variant}} { every use of {Inlined}StructPtr. #} #include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h" #include "mojo/public/cpp/bindings/lib/wtf_hash_util.h" -#include "third_party/WebKit/Source/platform/mojo/RevocableInterfacePtr.h" -#include "third_party/WebKit/Source/platform/wtf/HashFunctions.h" -#include "third_party/WebKit/Source/platform/wtf/Optional.h" -#include "third_party/WebKit/Source/platform/wtf/text/WTFString.h" +#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h" +#include "third_party/blink/renderer/platform/wtf/hash_functions.h" +#include "third_party/blink/renderer/platform/wtf/optional.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" {%- endif %} {% if not disallow_interfaces -%} @@ -85,7 +85,7 @@ namespace {{variant}} { #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" {%- if for_blink %} -#include "third_party/WebKit/Source/platform/mojo/RevocableInterfacePtr.h" +#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h" {%- endif %} {%- endif %} diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl index 3855c3f9bf6..59c6fee7581 100644 --- a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl @@ -1,34 +1,6 @@ {%- from "constant_definition.tmpl" import constant_def %} {%- from "enum_definition.tmpl" import enum_def %} -{%- macro equality(kind, v1, v2, ne=False) -%} -{%- if kind|is_reference_kind -%} -{%- if kind|is_array_kind -%} -{%- if kind.kind|is_reference_kind -%} -{%- if ne %}!{%- endif %}java.util.Arrays.deepEquals({{v1}}, {{v2}}) -{%- else -%} -{%- if ne %}!{%- endif %}java.util.Arrays.equals({{v1}}, {{v2}}) -{%- endif -%} -{%- else -%} -{%- if ne %}!{%- endif %}org.chromium.mojo.bindings.BindingsHelper.equals({{v1}}, {{v2}}) -{%- endif -%} -{%- else -%} -{{v1}} {%- if ne %}!={%- else %}=={%- endif %} {{v2}} -{%- endif -%} -{%- endmacro -%} - -{%- macro hash(kind, v) -%} -{%- if kind|is_array_kind -%} -{%- if kind.kind|is_reference_kind -%} -java.util.Arrays.deepHashCode({{v}}) -{%- else -%} -java.util.Arrays.hashCode({{v}}) -{%- endif -%} -{%- else -%} -org.chromium.mojo.bindings.BindingsHelper.hashCode({{v}}) -{%- endif -%} -{%- endmacro -%} - {%- macro array_element_size(kind) -%} {%- if kind|is_union_kind %} org.chromium.mojo.bindings.BindingsHelper.UNION_SIZE @@ -188,9 +160,6 @@ if ({{variable}} != null) { * @throws org.chromium.mojo.bindings.DeserializationException on deserialization failure. */ public static {{struct|name}} deserialize(java.nio.ByteBuffer data) { - if (data == null) - return null; - return deserialize(new org.chromium.mojo.bindings.Message( data, new java.util.ArrayList<org.chromium.mojo.system.Handle>())); } @@ -204,14 +173,26 @@ if ({{variable}} != null) { {{struct|name}} result; try { org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY); - result = new {{struct|name}}(mainDataHeader.elementsOrVersion); + final int elementsOrVersion = mainDataHeader.elementsOrVersion; + result = new {{struct|name}}(elementsOrVersion); +{%- set prev_ver = [0] %} {%- for byte in struct.bytes %} {%- for packed_field in byte.packed_fields %} - if (mainDataHeader.elementsOrVersion >= {{packed_field.min_version}}) { - {{decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(16)}} +{%- if packed_field.min_version != prev_ver[-1] %} +{%- if prev_ver[-1] != 0 %} } +{%- endif %} +{%- set _ = prev_ver.append(packed_field.min_version) %} + if (elementsOrVersion >= {{packed_field.min_version}}) { +{%- endif %} + { + {{decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(16)}} + } {%- endfor %} {%- endfor %} +{%- if prev_ver[-1] != 0 %} + } +{%- endif %} } finally { decoder0.decreaseStackDepth(); } @@ -232,40 +213,6 @@ if ({{variable}} != null) { {%- endfor %} {%- endfor %} } - - /** - * @see Object#equals(Object) - */ - @Override - public boolean equals(Object object) { - if (object == this) - return true; - if (object == null) - return false; - if (getClass() != object.getClass()) - return false; -{%- if struct.fields|length %} - {{struct|name}} other = ({{struct|name}}) object; -{%- for field in struct.fields %} - if ({{equality(field.kind, 'this.'~field|name, 'other.'~field|name, True)}}) - return false; -{%- endfor %} -{%- endif %} - return true; - } - - /** - * @see Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = prime + getClass().hashCode(); -{%- for field in struct.fields %} - result = prime * result + {{hash(field.kind, 'this.'~field|name)}}; -{%- endfor %} - return result; - } } {%- endmacro %} @@ -279,27 +226,19 @@ public final class {{union|name}} extends org.chromium.mojo.bindings.Union { {%- endfor %} }; - private int mTag_ = -1; {%- for field in union.fields %} private {{field.kind|java_type}} m{{field|ucc}}; {%- endfor %} - public int which() { - return mTag_; - } - - public boolean isUnknown() { - return mTag_ == -1; - } {%- for field in union.fields %} public void set{{field|ucc}}({{field.kind|java_type}} {{field|name}}) { - this.mTag_ = Tag.{{field|ucc}}; + this.mTag = Tag.{{field|ucc}}; this.m{{field|ucc}} = {{field|name}}; } public {{field.kind|java_type}} get{{field|ucc}}() { - assert this.mTag_ == Tag.{{field|ucc}}; + assert this.mTag == Tag.{{field|ucc}}; return this.m{{field|ucc}}; } {%- endfor %} @@ -308,8 +247,8 @@ public final class {{union|name}} extends org.chromium.mojo.bindings.Union { @Override protected final void encode(org.chromium.mojo.bindings.Encoder encoder0, int offset) { encoder0.encode(org.chromium.mojo.bindings.BindingsHelper.UNION_SIZE, offset); - encoder0.encode(this.mTag_, offset + 4); - switch (mTag_) { + encoder0.encode(this.mTag, offset + 4); + switch (mTag) { {%- for field in union.fields %} case Tag.{{field|ucc}}: { {%- if field.kind|is_union_kind %} @@ -352,54 +291,7 @@ public final class {{union|name}} extends org.chromium.mojo.bindings.Union { {%- else %} {{decode('result.m'~field|ucc, field.kind, 'offset + org.chromium.mojo.bindings.DataHeader.HEADER_SIZE', 0)|indent(16)}} {%- endif %} - result.mTag_ = Tag.{{field|ucc}}; - break; - } -{%- endfor %} - default: { - break; - } - } - return result; - } - - /** - * @see Object#equals(Object) - */ - @Override - public boolean equals(Object object) { - if (object == this) - return true; - if (object == null) - return false; - if (getClass() != object.getClass()) - return false; - {{union|name}} other = ({{union|name}}) object; - if (this.mTag_ != other.mTag_) - return false; - switch (this.mTag_) { -{%- for field in union.fields %} - case Tag.{{field|ucc}}: - return {{equality(field.kind, 'this.m'~field|ucc, 'other.m'~field|ucc)}}; -{%- endfor %} - default: - break; - } - return false; - } - - /** - * @see Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = prime + getClass().hashCode(); - result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(mTag_); - switch (this.mTag_) { -{%- for field in union.fields %} - case Tag.{{field|ucc}}: { - result = prime * result + {{hash(field.kind, 'this.m'~field|ucc)}}; + result.mTag = Tag.{{field|ucc}}; break; } {%- endfor %} diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl new file mode 100644 index 00000000000..9f9b9f1ebd3 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl @@ -0,0 +1,24 @@ +/** @implements {mojo.InterfacePtr} */ +{{module.namespace}}.{{interface.name}}Ptr = class { +{% for method in interface.methods %} + /** +{%- for parameter in method.parameters %} + * @param { {{parameter.kind|closure_type_with_nullability}} } {{parameter.name|sanitize_identifier}} +{%- endfor -%} +{%- if method.response_parameters != None %} + * @return {Promise} +{%- endif %} + */ + {{method.name}}( +{%- for parameter in method.parameters -%} +{{parameter.name|sanitize_identifier}}{% if not loop.last %}, {% endif %} +{%- endfor -%} +) {} +{%- endfor %} +}; + +/** + * @const + * @type { mojo.Interface }; + */ +{{module.namespace}}.{{interface.name}}; diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl new file mode 100644 index 00000000000..8eccefbfecf --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl @@ -0,0 +1,22 @@ +// Copyright 2018 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. + +{% for declaration in module.namespace|namespace_declarations -%} +/** @const */ +{%- if loop.first %} +let {{declaration}} = {}; +{% else %} +{{declaration}} = {}; +{% endif -%} +{%- endfor -%} + +{#--- Interface definitions #} +{%- for interface in interfaces -%} +{%- include "externs/interface_definition.tmpl" %} +{% endfor -%} + +{#--- Struct definitions #} +{%- for struct in structs -%} +{%- include "externs/struct_definition.tmpl" %} +{% endfor -%} diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/struct_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/struct_definition.tmpl new file mode 100644 index 00000000000..4aecb67c840 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/struct_definition.tmpl @@ -0,0 +1,8 @@ +{{module.namespace}}.{{struct.name}} = class { + constructor() { +{%- for packed_field in struct.packed.packed_fields %} + /** @type { {{packed_field.field.kind|closure_type_with_nullability}} } */ + this.{{packed_field.field.name}}; +{%- endfor %} + } +}; diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl index 4b7d65ca483..988ca0af4d3 100644 --- a/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl +++ b/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl @@ -33,12 +33,12 @@ {{interface.name}}Proxy.prototype.{{method.name}} = function( {%- for parameter in method.parameters -%} -{{parameter.name}}{% if not loop.last %}, {% endif %} +{{parameter.name|sanitize_identifier}}{% if not loop.last %}, {% endif %} {%- endfor -%} ) { - var params = new {{interface_method_id}}_Params(); + var params_ = new {{interface_method_id}}_Params(); {%- for parameter in method.parameters %} - params.{{parameter.name}} = {{parameter.name}}; + params_.{{parameter.name}} = {{parameter.name|sanitize_identifier}}; {%- endfor %} {%- if method.response_parameters == None %} @@ -46,12 +46,12 @@ var builder = new codec.MessageV2Builder( k{{interface_method_id}}_Name, codec.align({{interface_method_id}}_Params.encodedSize)); - builder.setPayload({{interface_method_id}}_Params, params); + builder.setPayload({{interface_method_id}}_Params, params_); {%- else %} var builder = new codec.MessageV0Builder( k{{interface_method_id}}_Name, codec.align({{interface_method_id}}_Params.encodedSize)); - builder.encodeStruct({{interface_method_id}}_Params, params); + builder.encodeStruct({{interface_method_id}}_Params, params_); {%- endif %} var message = builder.finish(); this.receiver_.accept(message); @@ -62,13 +62,13 @@ k{{interface_method_id}}_Name, codec.align({{interface_method_id}}_Params.encodedSize), codec.kMessageExpectsResponse, 0); - builder.setPayload({{interface_method_id}}_Params, params); + builder.setPayload({{interface_method_id}}_Params, params_); {%- else %} var builder = new codec.MessageV1Builder( k{{interface_method_id}}_Name, codec.align({{interface_method_id}}_Params.encodedSize), codec.kMessageExpectsResponse, 0); - builder.encodeStruct({{interface_method_id}}_Params, params); + builder.encodeStruct({{interface_method_id}}_Params, params_); {%- endif %} var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { @@ -89,8 +89,8 @@ } {%- for method in interface.methods %} - {{interface.name}}Stub.prototype.{{method.name}} = function({{method.parameters|map(attribute='name')|join(', ')}}) { - return this.delegate_ && this.delegate_.{{method.name}} && this.delegate_.{{method.name}}({{method.parameters|map(attribute='name')|join(', ')}}); + {{interface.name}}Stub.prototype.{{method.name}} = function({{method.parameters|map(attribute='name')|map('sanitize_identifier')|join(', ')}}) { + return this.delegate_ && this.delegate_.{{method.name}} && this.delegate_.{{method.name}}({{method.parameters|map(attribute='name')|map('sanitize_identifier')|join(', ')}}); } {%- endfor %} diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py index 26a6ad89974..5a4de762eca 100644 --- a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py +++ b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py @@ -63,6 +63,79 @@ _kind_to_codec_type = { mojom.NULLABLE_STRING: "codec.NullableString", } +_kind_to_closure_type = { + mojom.BOOL: "boolean", + mojom.INT8: "number", + mojom.UINT8: "number", + mojom.INT16: "number", + mojom.UINT16: "number", + mojom.INT32: "number", + mojom.UINT32: "number", + mojom.FLOAT: "number", + mojom.INT64: "number", + mojom.UINT64: "number", + mojom.DOUBLE: "number", + mojom.STRING: "string", + mojom.NULLABLE_STRING: "string", + mojom.HANDLE: "mojo.MojoHandle", + mojom.DCPIPE: "mojo.MojoHandle", + mojom.DPPIPE: "mojo.MojoHandle", + mojom.MSGPIPE: "mojo.MojoHandle", + mojom.SHAREDBUFFER: "mojo.MojoHandle", + mojom.NULLABLE_HANDLE: "mojo.MojoHandle", + mojom.NULLABLE_DCPIPE: "mojo.MojoHandle", + mojom.NULLABLE_DPPIPE: "mojo.MojoHandle", + mojom.NULLABLE_MSGPIPE: "mojo.MojoHandle", + mojom.NULLABLE_SHAREDBUFFER: "mojo.MojoHandle", +} + +_js_reserved_keywords = [ + 'arguments', + 'await', + 'break' + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'enum', + 'export', + 'extends', + 'finally', + 'for', + 'function', + 'if', + 'implements', + 'import', + 'in', + 'instanceof', + 'interface', + 'let', + 'new', + 'package', + 'private', + 'protected', + 'public', + 'return', + 'static', + 'super', + 'switch', + 'this', + 'throw', + 'try', + 'typeof', + 'var', + 'void', + 'while', + 'with', + 'yield', +] + def JavaScriptPayloadSize(packed): packed_fields = packed.packed_fields @@ -142,6 +215,7 @@ class Generator(generator.Generator): def GetFilters(self): js_filters = { + "closure_type": self._ClosureType, "decode_snippet": self._JavaScriptDecodeSnippet, "default_value": self._JavaScriptDefaultValue, "encode_snippet": self._JavaScriptEncodeSnippet, @@ -166,6 +240,8 @@ class Generator(generator.Generator): "is_union_kind": mojom.IsUnionKind, "js_type": self._JavaScriptType, "method_passes_associated_kinds": mojom.MethodPassesAssociatedKinds, + "namespace_declarations": self._NamespaceDeclarations, + "closure_type_with_nullability": self._ClosureTypeWithNullability, "payload_size": JavaScriptPayloadSize, "to_camel": generator.ToCamel, "union_decode_snippet": self._JavaScriptUnionDecodeSnippet, @@ -176,6 +252,7 @@ class Generator(generator.Generator): "validate_nullable_params": self._JavaScriptNullableParam, "validate_struct_params": self._JavaScriptValidateStructParams, "validate_union_params": self._JavaScriptValidateUnionParams, + "sanitize_identifier": self._JavaScriptSanitizeIdentifier, } return js_filters @@ -183,6 +260,10 @@ class Generator(generator.Generator): def _GenerateAMDModule(self): return self._GetParameters() + @UseJinja("externs/module.externs.tmpl") + def _GenerateExterns(self): + return self._GetParameters() + def GenerateFiles(self, args): if self.variant: raise Exception("Variants not supported in JavaScript bindings.") @@ -195,6 +276,7 @@ class Generator(generator.Generator): self._SetUniqueNameForImports() self.Write(self._GenerateAMDModule(), "%s.js" % self.module.path) + self.Write(self._GenerateExterns(), "%s.externs.js" % self.module.path) def _SetUniqueNameForImports(self): used_names = set() @@ -213,6 +295,44 @@ class Generator(generator.Generator): each_import.unique_name = unique_name + "$" counter += 1 + def _ClosureType(self, kind): + if kind in mojom.PRIMITIVES: + return _kind_to_closure_type[kind] + if (mojom.IsStructKind(kind) or mojom.IsInterfaceKind(kind) or + mojom.IsEnumKind(kind)): + return kind.module.namespace + "." + kind.name + # TODO(calamity): Support unions properly. + if mojom.IsUnionKind(kind): + return "Object" + if mojom.IsArrayKind(kind): + return "Array<%s>" % self._ClosureType(kind.kind) + if mojom.IsMapKind(kind): + return "Map<%s, %s>" % ( + self._ClosureType(kind.key_kind), self._ClosureType(kind.value_kind)) + if mojom.IsInterfaceRequestKind(kind): + return "mojo.InterfaceRequest" + # TODO(calamity): Support associated interfaces properly. + if mojom.IsAssociatedInterfaceKind(kind): + return "mojo.AssociatedInterfacePtrInfo" + # TODO(calamity): Support associated interface requests properly. + if mojom.IsAssociatedInterfaceRequestKind(kind): + return "mojo.AssociatedInterfaceRequest" + # TODO(calamity): Support enums properly. + + raise Exception("No valid closure type: %s" % kind) + + def _ClosureTypeWithNullability(self, kind): + return ("" if mojom.IsNullableKind(kind) else "!") + self._ClosureType(kind) + + def _NamespaceDeclarations(self, namespace): + pieces = namespace.split('.') + declarations = [] + declaration = [] + for p in pieces: + declaration.append(p) + declarations.append('.'.join(declaration)) + return declarations + def _JavaScriptType(self, kind): name = [] if kind.module and kind.module.path != self.module.path: @@ -378,6 +498,12 @@ class Generator(generator.Generator): return "%s, %s, %s, %s" % \ (nullable, keys_type, values_type, values_nullable) + def _JavaScriptSanitizeIdentifier(self, identifier): + if identifier in _js_reserved_keywords: + return identifier + '_' + + return identifier + def _TranslateConstants(self, token): if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): # Both variable and enum constants are constructed like: diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni index 465b059c943..317d8c0fd3b 100644 --- a/chromium/mojo/public/tools/bindings/mojom.gni +++ b/chromium/mojo/public/tools/bindings/mojom.gni @@ -12,6 +12,7 @@ import("//build/config/jumbo.gni") import("//build/config/chrome_build.gni") import("//build/config/nacl/config.gni") import("//components/nacl/features.gni") +import("//third_party/jinja2/jinja2.gni") declare_args() { # Indicates whether typemapping should be supported in this build @@ -355,6 +356,24 @@ template("mojom") { } } + target_sources_list = "$target_gen_dir/$target_name.sources_list" + sources_list = [] + if (defined(invoker.sources)) { + sources_list = invoker.sources + } + write_file(target_sources_list, sources_list) + + # a target implicitly depends on its own sources + deps_sources = [ rebase_path(target_sources_list, root_build_dir) ] + foreach(d, all_deps) { + dep_dir = get_label_info("$d", "target_gen_dir") + dep_short_name = get_label_info("$d", "name") + deps_sources += + [ rebase_path("$dep_dir/$dep_short_name.sources_list", root_build_dir) ] + } + + write_file("$target_gen_dir/$target_name.deps_sources_list", deps_sources) + if (defined(invoker.sources)) { parser_target_name = "${target_name}__parser" enabled_features = [] @@ -379,16 +398,25 @@ template("mojom") { } else if (is_win) { enabled_features += [ "is_win" ] } - action_foreach(parser_target_name) { + + action(parser_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = invoker.sources - outputs = [ - "{{source_gen_dir}}/{{source_name_part}}.p", - ] + outputs = [] + filelist = [] + foreach(source, invoker.sources) { + filename = get_path_info("$source", "name") + dirname = get_path_info("$source", "gen_dir") + outputs += [ "$dirname/$filename.p" ] + filelist += [ rebase_path("$source", root_build_dir) ] + } + + response_file_contents = filelist + args = [ "parse", - "{{source}}", + "--filelist={{response_file_name}}", "-o", rebase_path(root_gen_dir, root_build_dir), "-d", @@ -418,6 +446,46 @@ template("mojom") { } } + if (defined(invoker.sources)) { + verify_deps_target_names = [] + if (!defined(invoker.skip_deps_check) || !invoker.skip_deps_check) { + verify_deps_target_name = "${target_name}__verify_deps" + verify_deps_target_names += [ ":$verify_deps_target_name" ] + source_file_name = target_name + + action(verify_deps_target_name) { + script = mojom_generator_script + inputs = mojom_generator_sources + jinja2_sources + sources = invoker.sources + deps = [ + ":$parsed_target_name", + ] + outputs = [] + filelist = [] + foreach(source, invoker.sources) { + filename = get_path_info("$source", "name") + dirname = get_path_info("$source", "gen_dir") + outputs += [ "$dirname/$filename.v" ] + filelist += [ rebase_path("$source", root_build_dir) ] + } + + response_file_contents = filelist + + args = [ + "verify", + "--filelist={{response_file_name}}", + "-f", + rebase_path("$target_gen_dir/$source_file_name.deps_sources_list", + root_build_dir), + "--gen_dir", + rebase_path(root_gen_dir, root_build_dir), + "--depth", + rebase_path("//", root_build_dir), + ] + } + } + } + generator_cpp_message_ids_target_name = "${target_name}__generate_message_ids" # Generate code that is shared by different variants. @@ -425,7 +493,6 @@ template("mojom") { common_generator_args = [ "--use_bundled_pylibs", "generate", - "{{source}}", "-d", rebase_path("//", root_build_dir), "-I", @@ -485,19 +552,26 @@ template("mojom") { } } - action_foreach(generator_cpp_message_ids_target_name) { + action(generator_cpp_message_ids_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = invoker.sources deps = [ ":$parsed_target_name", "//mojo/public/tools/bindings:precompile_templates", ] - outputs = [ - "{{source_gen_dir}}/{{source_name_part}}.mojom-shared-message-ids.h", - ] + outputs = [] args = common_generator_args + filelist = [] + foreach(source, invoker.sources) { + outputs += [ "$target_gen_dir/$source-shared-message-ids.h" ] + filelist += [ rebase_path("$source", root_build_dir) ] + } + + response_file_contents = filelist + args += [ + "--filelist={{response_file_name}}", "--generate_non_variant_code", "--generate_message_ids", "-g", @@ -517,17 +591,31 @@ template("mojom") { "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.h", ] generator_shared_target_name = "${target_name}_shared__generator" - action_foreach(generator_shared_target_name) { + action(generator_shared_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = invoker.sources deps = [ - ":$parsed_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = generator_shared_cpp_outputs + ":$parsed_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + verify_deps_target_names + + outputs = [] args = common_generator_args + filelist = [] + foreach(source, invoker.sources) { + filelist += [ rebase_path("$source", root_build_dir) ] + outputs += [ + "$target_gen_dir/$source-shared-internal.h", + "$target_gen_dir/$source-shared.cc", + "$target_gen_dir/$source-shared.h", + ] + } + + response_file_contents = filelist + args += [ + "--filelist={{response_file_name}}", "--generate_non_variant_code", "-g", "c++", @@ -690,18 +778,30 @@ template("mojom") { } generator_target_name = "${target_name}${variant_suffix}__generator" - action_foreach(generator_target_name) { + action(generator_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = invoker.sources deps = [ - ":$parsed_target_name", - ":$type_mappings_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = generator_cpp_outputs + ":$parsed_target_name", + ":$type_mappings_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + verify_deps_target_names + outputs = [] args = common_generator_args + filelist = [] + foreach(source, invoker.sources) { + filelist += [ rebase_path("$source", root_build_dir) ] + outputs += [ + "$target_gen_dir/${source}${variant_dash_suffix}.cc", + "$target_gen_dir/${source}${variant_dash_suffix}.h", + ] + } + + response_file_contents = filelist + args += [ + "--filelist={{response_file_name}}", "-g", "c++", ] @@ -762,7 +862,8 @@ template("mojom") { } action(type_mappings_target_name) { - inputs = _bindings_configuration_files + mojom_generator_sources + inputs = _bindings_configuration_files + mojom_generator_sources + + jinja2_sources outputs = [ type_mappings_path, ] @@ -941,18 +1042,27 @@ template("mojom") { if (enabled_sources != []) { generator_java_outputs = [ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ] - action_foreach(java_generator_target_name) { + action(java_generator_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = enabled_sources deps = [ - ":$parsed_target_name", - ":$type_mappings_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = generator_java_outputs + ":$parsed_target_name", + ":$type_mappings_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + verify_deps_target_names + outputs = [] args = common_generator_args + filelist = [] + foreach(source, invoker.sources) { + filelist += [ rebase_path("$source", root_build_dir) ] + outputs += [ "$target_gen_dir/$source.srcjar" ] + } + + response_file_contents = filelist + args += [ + "--filelist={{response_file_name}}", "-g", "java", ] @@ -1021,22 +1131,36 @@ template("mojom") { if (!defined(invoker.cpp_only) || !invoker.cpp_only) { if (defined(invoker.sources)) { generator_js_target_name = "${target_name}_js__generator" - generator_js_outputs = - [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ] - action_foreach(generator_js_target_name) { + generator_js_outputs = [ + "{{source_gen_dir}}/{{source_name_part}}.mojom.js", + "{{source_gen_dir}}/{{source_name_part}}.mojom.externs.js", + ] + action(generator_js_target_name) { script = mojom_generator_script - inputs = mojom_generator_sources + inputs = mojom_generator_sources + jinja2_sources sources = [] if (defined(invoker.sources)) { sources += invoker.sources } deps = [ - ":$parsed_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = generator_js_outputs + ":$parsed_target_name", + "//mojo/public/tools/bindings:precompile_templates", + ] + verify_deps_target_names + outputs = [] args = common_generator_args + filelist = [] + foreach(source, invoker.sources) { + filelist += [ rebase_path("$source", root_build_dir) ] + outputs += [ + "$target_gen_dir/$source.js", + "$target_gen_dir/$source.externs.js", + ] + } + + response_file_contents = filelist + args += [ + "--filelist={{response_file_name}}", "-g", "javascript", ] diff --git a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py index 804896cee7f..4117629e996 100755 --- a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py @@ -174,14 +174,7 @@ class MojomProcessor(object): MakeImportStackMessage(imported_filename_stack + [rel_filename.path]) sys.exit(1) - pickle_path = _GetPicklePath(rel_filename, args.output_dir) - try: - with open(pickle_path, "rb") as f: - tree = cPickle.load(f) - except (IOError, cPickle.UnpicklingError) as e: - print "%s: Error: %s" % (pickle_path, str(e)) - sys.exit(1) - + tree = _UnpickleAST(_GetPicklePath(rel_filename, args.output_dir)) dirname = os.path.dirname(rel_filename.path) # Process all our imports first and collect the module object for each. @@ -250,6 +243,11 @@ def _Generate(args, remaining_args): processor = MojomProcessor(lambda filename: filename in args.filename) processor.LoadTypemaps(set(args.typemaps)) + + if args.filelist: + with open(args.filelist) as f: + args.filename.extend(f.read().split()) + for filename in args.filename: processor._GenerateModule(args, remaining_args, generator_modules, RelativePath(filename, args.depth), []) @@ -273,6 +271,13 @@ def _PickleAST(ast, output_file): print "%s: Error: %s" % (output_file, str(e)) sys.exit(1) +def _UnpickleAST(input_file): + try: + with open(input_file, "rb") as f: + return cPickle.load(f) + except (IOError, cPickle.UnpicklingError) as e: + print "%s: Error: %s" % (input_file, str(e)) + sys.exit(1) def _ParseFile(args, rel_filename): try: @@ -288,12 +293,16 @@ def _ParseFile(args, rel_filename): except Error as e: print "%s: Error: %s" % (rel_filename.path, str(e)) sys.exit(1) - _PickleAST(tree, _GetPicklePath(rel_filename, args.output_dir)) def _Parse(args, _): fileutil.EnsureDirectoryExists(args.output_dir) + + if args.filelist: + with open(args.filelist) as f: + args.filename.extend(f.read().split()) + for filename in args.filename: _ParseFile(args, RelativePath(filename, args.depth)) return 0 @@ -305,7 +314,46 @@ def _Precompile(args, _): template_expander.PrecompileTemplates(generator_modules, args.output_dir) return 0 +def _VerifyImportDeps(args, __): + fileutil.EnsureDirectoryExists(args.gen_dir) + + if args.filelist: + with open(args.filelist) as f: + args.filename.extend(f.read().split()) + for filename in args.filename: + rel_path = RelativePath(filename, args.depth) + tree = _UnpickleAST(_GetPicklePath(rel_path, args.gen_dir)) + + mojom_imports = set( + parsed_imp.import_filename for parsed_imp in tree.import_list + ) + + # read the paths from the file + f_deps = open(args.deps_file, 'r') + deps_sources = set() + for deps_path in f_deps: + deps_path = deps_path.rstrip('\n') + f_sources = open(deps_path, 'r') + + for source_file in f_sources: + source_dir = deps_path.split(args.gen_dir + "/", 1)[1] + full_source_path = os.path.dirname(source_dir) + "/" + \ + source_file + deps_sources.add(full_source_path.rstrip('\n')) + + if (not deps_sources.issuperset(mojom_imports)): + print ">>> [%s] Missing dependencies for the following imports: %s" % ( \ + args.filename[0], \ + list(mojom_imports.difference(deps_sources))) + sys.exit(1) + + source_filename, _ = os.path.splitext(rel_path.relative_path()) + output_file = source_filename + '.v' + output_file_path = os.path.join(args.gen_dir, output_file) + WriteFile("", output_file_path) + + return 0 def main(): parser = argparse.ArgumentParser( @@ -318,7 +366,8 @@ def main(): parse_parser = subparsers.add_parser( "parse", description="Parse mojom to AST and remove disabled definitions." " Pickle pruned AST into output_dir.") - parse_parser.add_argument("filename", nargs="+", help="mojom input file") + parse_parser.add_argument("filename", nargs="*", help="mojom input file") + parse_parser.add_argument("--filelist", help="mojom input file list") parse_parser.add_argument( "-o", "--output_dir", @@ -339,8 +388,9 @@ def main(): generate_parser = subparsers.add_parser( "generate", description="Generate bindings from mojom files.") - generate_parser.add_argument("filename", nargs="+", + generate_parser.add_argument("filename", nargs="*", help="mojom input file") + generate_parser.add_argument("--filelist", help="mojom input file list") generate_parser.add_argument("-d", "--depth", dest="depth", default=".", help="depth from source root") generate_parser.add_argument("-o", "--output_dir", dest="output_dir", @@ -425,6 +475,23 @@ def main(): help="output directory for precompiled templates") precompile_parser.set_defaults(func=_Precompile) + verify_parser = subparsers.add_parser("verify", description="Checks " + "the set of imports against the set of dependencies.") + verify_parser.add_argument("filename", nargs="*", + help="mojom input file") + verify_parser.add_argument("--filelist", help="mojom input file list") + verify_parser.add_argument("-f", "--file", dest="deps_file", + help="file containing paths to the sources files for " + "dependencies") + verify_parser.add_argument("-g", "--gen_dir", + dest="gen_dir", + help="directory with the syntax tree") + verify_parser.add_argument( + "-d", "--depth", dest="depth", + help="depth from source root") + + verify_parser.set_defaults(func=_VerifyImportDeps) + args, remaining_args = parser.parse_known_args() return args.func(args, remaining_args) diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py index ebe5601b0a3..db45e3344f1 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -683,6 +683,8 @@ class Enum(Kind): Kind.__init__(self, spec, module) self.fields = [] self.attributes = attributes + self.min_value = None + self.max_value = None def Repr(self, as_ref=True): if as_ref: diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/translate.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/translate.py index 4153e7456cf..94fe2a6a523 100644 --- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/translate.py +++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/translate.py @@ -450,11 +450,17 @@ def _ResolveNumericEnumValues(enum_fields): """ Given a reference to a list of mojom.EnumField, resolves and assigns their values to EnumField.numeric_value. + + Returns: + A tuple of the lowest and highest assigned enumerator value or None, None + if no enumerator values were assigned. """ # map of <mojom_name> -> integral value resolved_enum_values = {} prev_value = -1 + min_value = None + max_value = None for field in enum_fields: # This enum value is +1 the previous enum value (e.g: BEGIN). if field.value is None: @@ -472,6 +478,12 @@ def _ResolveNumericEnumValues(enum_fields): resolved_enum_values[field.mojom_name] = prev_value field.numeric_value = prev_value + if min_value is None or prev_value < min_value: + min_value = prev_value + if max_value is None or prev_value > max_value: + max_value = prev_value + + return min_value, max_value def _Enum(module, parsed_enum, parent_kind): """ @@ -491,13 +503,11 @@ def _Enum(module, parsed_enum, parent_kind): enum.spec = 'x:%s.%s' % (module.mojom_namespace, mojom_name) enum.parent_kind = parent_kind enum.attributes = _AttributeListToDict(parsed_enum.attribute_list) - if enum.native_only: - enum.fields = [] - else: + if not enum.native_only: enum.fields = map( lambda field: _EnumField(module, enum, field, parent_kind), parsed_enum.enum_value_list) - _ResolveNumericEnumValues(enum.fields) + enum.min_value, enum.max_value = _ResolveNumericEnumValues(enum.fields) module.kinds[enum.spec] = enum diff --git a/chromium/mojo/public/tools/fuzzers/BUILD.gn b/chromium/mojo/public/tools/fuzzers/BUILD.gn index 12d1b9f0b0d..00d09f1969e 100644 --- a/chromium/mojo/public/tools/fuzzers/BUILD.gn +++ b/chromium/mojo/public/tools/fuzzers/BUILD.gn @@ -7,6 +7,7 @@ import("//build/config/features.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//testing/libfuzzer/fuzzer_test.gni") +import("//third_party/protobuf/proto_library.gni") # mojo/public BUILD depends on this target. Needed for package discovery group("fuzzers") { @@ -25,7 +26,7 @@ fuzzer_test("mojo_parse_message_fuzzer") { ] deps = [ ":fuzz_mojom", - "//mojo/edk/system", + "//mojo/edk", ] seed_corpus = "//mojo/public/tools/fuzzers/message_corpus" } @@ -41,7 +42,27 @@ if (!is_win) { ":fuzz_mojom", "//base", "//build/config:exe_and_shlib_deps", - "//mojo/edk/system", + "//mojo/edk", ] } } + +fuzzer_test("mojo_parse_message_proto_fuzzer") { + sources = [ + "fuzz_impl.cc", + "mojo_parse_message_proto_fuzzer.cc", + ] + deps = [ + ":fuzz_mojom", + ":mojo_fuzzer_proto", + "//mojo/edk", + "//third_party/libprotobuf-mutator", + ] + seed_corpus = "//mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus" +} + +proto_library("mojo_fuzzer_proto") { + sources = [ + "mojo_fuzzer.proto", + ] +} diff --git a/chromium/mojo/public/tools/fuzzers/mojo_fuzzer.proto b/chromium/mojo/public/tools/fuzzers/mojo_fuzzer.proto new file mode 100644 index 00000000000..fb17871151f --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_fuzzer.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; + +package mojo_proto_fuzzer; + +message MojoFuzzerMessages { + repeated bytes messages = 1; +}
\ No newline at end of file diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06 new file mode 100644 index 00000000000..f1932a62de8 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06 @@ -0,0 +1 @@ +messages: "\060\000\000\000\002\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\200\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496 new file mode 100644 index 00000000000..52bae3dad43 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496 @@ -0,0 +1 @@ +messages: "\030\000\000\000\000\000\000\000\001\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34 new file mode 100644 index 00000000000..9cbd5621d55 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34 @@ -0,0 +1 @@ +messages: "\030\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\040\001\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\001\377\001\000\000\377\000\001\000\000\377\377\000\000\001\000\000\000\000\000\377\377\377\377\000\000\000\000\001\000\000\000\000\000\200\077\000\000\000\000\000\000\000\000\000\000\360\077\110\000\000\000\000\000\000\000\120\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\230\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\240\001\000\000\000\000\000\000\110\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\140\003\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\002\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\061\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\062\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\020\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\022\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6 new file mode 100644 index 00000000000..fb4a52b1980 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6 @@ -0,0 +1 @@ +messages: "\040\000\000\000\001\000\000\000\000\000\000\000\005\000\000\000\001\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\040\001\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\001\377\001\000\000\377\000\001\000\000\377\377\000\000\001\000\000\000\000\000\377\377\377\377\000\000\000\000\001\000\000\000\000\000\200\077\000\000\000\000\000\000\000\000\000\000\360\077\110\000\000\000\000\000\000\000\120\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\230\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\240\001\000\000\000\000\000\000\110\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\140\003\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\002\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\061\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\062\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\020\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\022\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc new file mode 100644 index 00000000000..d5fa6119789 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc @@ -0,0 +1 @@ +messages: "\040\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\005\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106 new file mode 100644 index 00000000000..c5567f2f49b --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106 @@ -0,0 +1 @@ +messages: "\030\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f new file mode 100644 index 00000000000..619a2bbe143 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f @@ -0,0 +1 @@ +messages: "\030\000\000\000\000\000\000\000\377\377\377\377\376\377\377\377\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\001\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e new file mode 100644 index 00000000000..dcd7e6e8c1b --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e @@ -0,0 +1 @@ +messages: "\040\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374 b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374 new file mode 100644 index 00000000000..186f82d8676 --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374 @@ -0,0 +1 @@ +messages: "\030\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000" diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc new file mode 100644 index 00000000000..6772541db7e --- /dev/null +++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc @@ -0,0 +1,70 @@ +// Copyright 2018 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. + +// Implementation of a proto version of mojo_parse_message_fuzzer that sends +// multiple messages per run. + +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/task_scheduler/task_scheduler.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/tools/fuzzers/fuzz_impl.h" +#include "mojo/public/tools/fuzzers/mojo_fuzzer.pb.h" +#include "testing/libfuzzer/proto/lpm_interface.h" + +namespace mojo_proto_fuzzer { + +void FuzzMessage(const MojoFuzzerMessages& mojo_fuzzer_messages, + base::RunLoop* run) { + fuzz::mojom::FuzzInterfacePtr fuzz; + auto impl = std::make_unique<FuzzImpl>(MakeRequest(&fuzz)); + auto router = impl->binding_.RouterForTesting(); + + for (auto& message_str : mojo_fuzzer_messages.messages()) { + // Create a mojo message with the appropriate payload size. + mojo::Message message(0, 0, message_str.size(), 0, nullptr); + if (message.data_num_bytes() < message_str.size()) { + message.payload_buffer()->Allocate(message_str.size() - + message.data_num_bytes()); + } + + // Set the raw message data. + memcpy(message.mutable_data(), message_str.data(), message_str.size()); + + // Run the message through header validation, payload validation, and + // dispatch to the impl. + router->SimulateReceivingMessageForTesting(&message); + } + + // Allow the harness function to return now. + run->Quit(); +} + +// Environment for the fuzzer. Initializes the mojo EDK and sets up a +// TaskScheduler, because Mojo messages must be sent and processed from +// TaskRunners. +struct Environment { + Environment() : message_loop(base::MessageLoop::TYPE_UI) { + base::TaskScheduler::CreateAndStartWithDefaultParams( + "MojoParseMessageFuzzerProcess"); + mojo::edk::Init(); + } + + // Message loop to send and handle messages on. + base::MessageLoop message_loop; + + // Suppress mojo validation failure logs. + mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; +}; + +DEFINE_PROTO_FUZZER(const MojoFuzzerMessages& mojo_fuzzer_messages) { + static Environment* env = new Environment(); + // Pass the data along to run on a MessageLoop, and wait for it to finish. + base::RunLoop run; + env->message_loop.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FuzzMessage, mojo_fuzzer_messages, &run)); + run.Run(); +} +} // namespace mojo_proto_fuzzer |