diff options
Diffstat (limited to 'mojo/common')
33 files changed, 1785 insertions, 0 deletions
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn new file mode 100644 index 0000000000..9e74e582d3 --- /dev/null +++ b/mojo/common/BUILD.gn @@ -0,0 +1,93 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") +import("//testing/test.gni") + +group("common") { + public_deps = [ + ":common_base", + ":common_custom_types", + ] +} + +mojom("common_custom_types") { + sources = [ + "file.mojom", + "file_path.mojom", + "string16.mojom", + "text_direction.mojom", + "time.mojom", + "unguessable_token.mojom", + "values.mojom", + "version.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", + ] +} + +test("mojo_common_unittests") { + deps = [ + ":common", + ":common_custom_types", + ":struct_traits", + ":test_common_custom_types", + "//base", + "//base:message_loop_tests", + "//base/test:test_support", + "//mojo/edk/test:run_all_unittests", + "//mojo/edk/test:test_support", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/test_support:test_utils", + "//testing/gtest", + "//url", + ] + + 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", + ] + deps = [ + ":common_custom_types_shared_cpp_sources", + "//base:base", + "//mojo/public/cpp/system", + ] + public_deps = [ + "//base:i18n", + ] +} diff --git a/mojo/common/DEPS b/mojo/common/DEPS new file mode 100644 index 0000000000..e8ac42887d --- /dev/null +++ b/mojo/common/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + # common must not depend on embedder. + "-mojo", + "+mojo/common", + "+mojo/public", +] diff --git a/mojo/common/common_custom_types_struct_traits.cc b/mojo/common/common_custom_types_struct_traits.cc new file mode 100644 index 0000000000..62895048ad --- /dev/null +++ b/mojo/common/common_custom_types_struct_traits.cc @@ -0,0 +1,108 @@ +// 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 +bool StructTraits<common::mojom::String16DataView, base::string16>::Read( + common::mojom::String16DataView data, + base::string16* out) { + ArrayDataView<uint16_t> view; + data.GetDataDataView(&view); + out->assign(reinterpret_cast<const base::char16*>(view.data()), view.size()); + return true; +} + +// 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; +} + +} // namespace mojo diff --git a/mojo/common/common_custom_types_struct_traits.h b/mojo/common/common_custom_types_struct_traits.h new file mode 100644 index 0000000000..85815ffd62 --- /dev/null +++ b/mojo/common/common_custom_types_struct_traits.h @@ -0,0 +1,85 @@ +// 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/strings/utf_string_conversions.h" +#include "base/unguessable_token.h" +#include "base/version.h" +#include "mojo/common/file.mojom-shared.h" +#include "mojo/common/mojo_common_export.h" +#include "mojo/common/string16.mojom-shared.h" +#include "mojo/common/text_direction.mojom-shared.h" +#include "mojo/common/time.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::String16DataView, base::string16> { + static ConstCArray<uint16_t> data(const base::string16& str) { + return ConstCArray<uint16_t>(str.size(), + reinterpret_cast<const uint16_t*>(str.data())); + } + + static bool Read(common::mojom::String16DataView data, base::string16* out); +}; + +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::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); +}; + +} // namespace mojo + +#endif // MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ diff --git a/mojo/common/common_custom_types_unittest.cc b/mojo/common/common_custom_types_unittest.cc new file mode 100644 index 0000000000..e3571d9d86 --- /dev/null +++ b/mojo/common/common_custom_types_unittest.cc @@ -0,0 +1,433 @@ +// 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/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/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "mojo/common/test_common_custom_types.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace common { +namespace test { +namespace { + +template <typename T> +struct BounceTestTraits { + static void ExpectEquality(const T& a, const T& b) { + EXPECT_EQ(a, b); + } +}; + +template <typename T> +struct PassTraits { + using Type = const T&; +}; + +template <> +struct PassTraits<base::Time> { + using Type = base::Time; +}; + +template <> +struct PassTraits<base::TimeDelta> { + using Type = base::TimeDelta; +}; + +template <> +struct PassTraits<base::TimeTicks> { + using Type = base::TimeTicks; +}; + +template <typename T> +void DoExpectResponse(T* expected_value, + const base::Closure& closure, + typename PassTraits<T>::Type value) { + BounceTestTraits<T>::ExpectEquality(*expected_value, value); + closure.Run(); +} + +template <typename T> +base::Callback<void(typename PassTraits<T>::Type)> ExpectResponse( + T* expected_value, + const base::Closure& closure) { + 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, + const BounceFilePathCallback& callback) override { + 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, + const BounceNonceCallback& callback) override { + 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, const BounceTimeCallback& callback) override { + callback.Run(in); + } + + void BounceTimeDelta(base::TimeDelta in, + const BounceTimeDeltaCallback& callback) override { + callback.Run(in); + } + + void BounceTimeTicks(base::TimeTicks in, + const BounceTimeTicksCallback& callback) override { + callback.Run(in); + } + + private: + mojo::Binding<TestTime> binding_; +}; + +class TestValueImpl : public TestValue { + public: + explicit TestValueImpl(TestValueRequest request) + : binding_(this, std::move(request)) {} + + // TestValue implementation: + void BounceDictionaryValue( + std::unique_ptr<base::DictionaryValue> in, + const BounceDictionaryValueCallback& callback) override { + callback.Run(std::move(in)); + } + + void BounceListValue(std::unique_ptr<base::ListValue> in, + const BounceListValueCallback& callback) override { + callback.Run(std::move(in)); + } + + void BounceValue(std::unique_ptr<base::Value> in, + const BounceValueCallback& callback) override { + callback.Run(std::move(in)); + } + + private: + mojo::Binding<TestValue> binding_; +}; + +class TestString16Impl : public TestString16 { + public: + explicit TestString16Impl(TestString16Request request) + : binding_(this, std::move(request)) {} + + // TestString16 implementation: + void BounceString16(const base::string16& in, + const BounceString16Callback& callback) override { + callback.Run(in); + } + + private: + mojo::Binding<TestString16> binding_; +}; + +class TestFileImpl : public TestFile { + public: + explicit TestFileImpl(TestFileRequest request) + : binding_(this, std::move(request)) {} + + // TestFile implementation: + void BounceFile(base::File in, const BounceFileCallback& callback) override { + 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, + const BounceTextDirectionCallback& callback) override { + callback.Run(in); + } + + private: + mojo::Binding<TestTextDirection> binding_; +}; + +class CommonCustomTypesTest : public testing::Test { + protected: + CommonCustomTypesTest() {} + ~CommonCustomTypesTest() override {} + + private: + base::MessageLoop message_loop_; + + DISALLOW_COPY_AND_ASSIGN(CommonCustomTypesTest); +}; + +} // 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, 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)); + + std::unique_ptr<base::Value> output; + + ASSERT_TRUE(ptr->BounceValue(nullptr, &output)); + EXPECT_FALSE(output); + + std::unique_ptr<base::Value> input = base::Value::CreateNullValue(); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + input = base::MakeUnique<base::Value>(123); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + input = base::MakeUnique<base::Value>(1.23); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + input = base::MakeUnique<base::Value>(false); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + input = base::MakeUnique<base::Value>("test string"); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + input = base::BinaryValue::CreateWithCopiedBuffer("mojo", 4); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + auto dict = base::MakeUnique<base::DictionaryValue>(); + dict->SetBoolean("bool", false); + dict->SetInteger("int", 2); + dict->SetString("string", "some string"); + dict->SetBoolean("nested.bool", true); + dict->SetInteger("nested.int", 9); + dict->Set("some_binary", + base::BinaryValue::CreateWithCopiedBuffer("mojo", 4)); + dict->Set("null_value", base::Value::CreateNullValue()); + dict->SetIntegerWithoutPathExpansion("non_nested.int", 10); + { + std::unique_ptr<base::ListValue> dict_list(new base::ListValue()); + dict_list->AppendString("string"); + dict_list->AppendBoolean(true); + dict->Set("list", std::move(dict_list)); + } + + std::unique_ptr<base::DictionaryValue> dict_output; + ASSERT_TRUE(ptr->BounceDictionaryValue(dict->CreateDeepCopy(), &dict_output)); + EXPECT_TRUE(base::Value::Equals(dict.get(), dict_output.get())); + + input = std::move(dict); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); + + auto list = base::MakeUnique<base::ListValue>(); + list->AppendString("string"); + list->AppendDouble(42.1); + list->AppendBoolean(true); + list->Append(base::BinaryValue::CreateWithCopiedBuffer("mojo", 4)); + list->Append(base::Value::CreateNullValue()); + { + std::unique_ptr<base::DictionaryValue> list_dict( + new base::DictionaryValue()); + list_dict->SetString("string", "str"); + list->Append(std::move(list_dict)); + } + std::unique_ptr<base::ListValue> list_output; + ASSERT_TRUE(ptr->BounceListValue(list->CreateDeepCopy(), &list_output)); + EXPECT_TRUE(base::Value::Equals(list.get(), list_output.get())); + + input = std::move(list); + ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); + ASSERT_TRUE(base::Value::Equals(input.get(), output.get())); +} + +TEST_F(CommonCustomTypesTest, String16) { + base::RunLoop run_loop; + + TestString16Ptr ptr; + TestString16Impl impl(MakeRequest(&ptr)); + + base::string16 str16 = base::ASCIIToUTF16("hello world"); + + ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure())); + + run_loop.Run(); +} + +TEST_F(CommonCustomTypesTest, EmptyString16) { + base::RunLoop run_loop; + + TestString16Ptr ptr; + TestString16Impl impl(MakeRequest(&ptr)); + + base::string16 str16; + + ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure())); + + run_loop.Run(); +} + +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/mojo/common/data_pipe_drainer.cc b/mojo/common/data_pipe_drainer.cc new file mode 100644 index 0000000000..e705c8d387 --- /dev/null +++ b/mojo/common/data_pipe_drainer.cc @@ -0,0 +1,50 @@ +// 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/common/data_pipe_drainer.h" + +#include <stdint.h> + +#include <utility> + +#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), + weak_factory_(this) { + DCHECK(client_); + handle_watcher_.Watch( + source_.get(), MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&DataPipeDrainer::WaitComplete, weak_factory_.GetWeakPtr())); +} + +DataPipeDrainer::~DataPipeDrainer() {} + +void DataPipeDrainer::ReadData() { + const void* buffer = nullptr; + uint32_t num_bytes = 0; + MojoResult rv = BeginReadDataRaw(source_.get(), &buffer, &num_bytes, + MOJO_READ_DATA_FLAG_NONE); + if (rv == MOJO_RESULT_OK) { + client_->OnDataAvailable(buffer, num_bytes); + EndReadDataRaw(source_.get(), num_bytes); + } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { + client_->OnDataComplete(); + } else if (rv != MOJO_RESULT_SHOULD_WAIT) { + DCHECK(false) << "Unhandled MojoResult: " << rv; + } +} + +void DataPipeDrainer::WaitComplete(MojoResult result) { + ReadData(); +} + +} // namespace common +} // namespace mojo diff --git a/mojo/common/data_pipe_drainer.h b/mojo/common/data_pipe_drainer.h new file mode 100644 index 0000000000..5cff8203e0 --- /dev/null +++ b/mojo/common/data_pipe_drainer.h @@ -0,0 +1,49 @@ +// 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_COMMON_DATA_PIPE_DRAINER_H_ +#define MOJO_COMMON_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" + +namespace mojo { +namespace common { + +class MOJO_COMMON_EXPORT DataPipeDrainer { + public: + class Client { + public: + virtual void OnDataAvailable(const void* data, size_t num_bytes) = 0; + virtual void OnDataComplete() = 0; + + protected: + virtual ~Client() {} + }; + + DataPipeDrainer(Client*, mojo::ScopedDataPipeConsumerHandle source); + ~DataPipeDrainer(); + + private: + void ReadData(); + void WaitComplete(MojoResult result); + + Client* client_; + mojo::ScopedDataPipeConsumerHandle source_; + mojo::SimpleWatcher handle_watcher_; + + base::WeakPtrFactory<DataPipeDrainer> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DataPipeDrainer); +}; + +} // namespace common +} // namespace mojo + +#endif // MOJO_COMMON_DATA_PIPE_DRAINER_H_ diff --git a/mojo/common/data_pipe_utils.cc b/mojo/common/data_pipe_utils.cc new file mode 100644 index 0000000000..9b069b80c5 --- /dev/null +++ b/mojo/common/data_pipe_utils.cc @@ -0,0 +1,96 @@ +// 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/common/data_pipe_utils.h" + +#include <utility> + +#include "base/bind.h" +#include "mojo/public/cpp/system/wait.h" + +namespace mojo { +namespace common { +namespace { + +bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, + const base::Callback<size_t(const void*, uint32_t)>& write_bytes) { + for (;;) { + const void* buffer; + uint32_t num_bytes; + MojoResult result = BeginReadDataRaw( + source.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); + if (result == MOJO_RESULT_OK) { + size_t bytes_written = write_bytes.Run(buffer, num_bytes); + result = EndReadDataRaw(source.get(), num_bytes); + if (bytes_written < num_bytes || result != MOJO_RESULT_OK) + return false; + } else if (result == MOJO_RESULT_SHOULD_WAIT) { + result = Wait(source.get(), MOJO_HANDLE_SIGNAL_READABLE); + if (result != MOJO_RESULT_OK) { + // If the producer handle was closed, then treat as EOF. + return result == MOJO_RESULT_FAILED_PRECONDITION; + } + } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { + // If the producer handle was closed, then treat as EOF. + return true; + } else { + // Some other error occurred. + break; + } + } + + return false; +} + +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; +} + +} // namespace + +// TODO(hansmuller): Add a max_size parameter. +bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, + std::string* result) { + CHECK(result); + result->clear(); + return BlockingCopyHelper(std::move(source), + base::Bind(&CopyToStringHelper, result)); +} + +bool MOJO_COMMON_EXPORT BlockingCopyFromString( + const std::string& source, + const ScopedDataPipeProducerHandle& destination) { + auto it = source.begin(); + for (;;) { + void* buffer = nullptr; + uint32_t buffer_num_bytes = 0; + MojoResult result = + BeginWriteDataRaw(destination.get(), &buffer, &buffer_num_bytes, + MOJO_WRITE_DATA_FLAG_NONE); + if (result == MOJO_RESULT_OK) { + char* char_buffer = static_cast<char*>(buffer); + uint32_t byte_index = 0; + while (it != source.end() && byte_index < buffer_num_bytes) { + char_buffer[byte_index++] = *it++; + } + EndWriteDataRaw(destination.get(), byte_index); + if (it == source.end()) + return true; + } else if (result == MOJO_RESULT_SHOULD_WAIT) { + result = Wait(destination.get(), MOJO_HANDLE_SIGNAL_WRITABLE); + if (result != MOJO_RESULT_OK) { + // If the consumer handle was closed, then treat as EOF. + return result == MOJO_RESULT_FAILED_PRECONDITION; + } + } else { + // If the consumer handle was closed, then treat as EOF. + return result == MOJO_RESULT_FAILED_PRECONDITION; + } + } +} + +} // namespace common +} // namespace mojo diff --git a/mojo/common/data_pipe_utils.h b/mojo/common/data_pipe_utils.h new file mode 100644 index 0000000000..a3f7c093e4 --- /dev/null +++ b/mojo/common/data_pipe_utils.h @@ -0,0 +1,32 @@ +// 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_COMMON_DATA_PIPE_UTILS_H_ +#define MOJO_COMMON_DATA_PIPE_UTILS_H_ + +#include <stdint.h> + +#include <string> + +#include "mojo/common/mojo_common_export.h" +#include "mojo/public/cpp/system/data_pipe.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_COMMON_EXPORT BlockingCopyFromString( + const std::string& source, + const ScopedDataPipeProducerHandle& destination); + +} // namespace common +} // namespace mojo + +#endif // MOJO_COMMON_DATA_PIPE_UTILS_H_ diff --git a/mojo/common/file.mojom b/mojo/common/file.mojom new file mode 100644 index 0000000000..fe224734d9 --- /dev/null +++ b/mojo/common/file.mojom @@ -0,0 +1,10 @@ +// 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::File| in base/files/file.h +struct File { + handle fd; +}; diff --git a/mojo/common/file.typemap b/mojo/common/file.typemap new file mode 100644 index 0000000000..26d494139e --- /dev/null +++ b/mojo/common/file.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/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/mojo/common/file_path.mojom b/mojo/common/file_path.mojom new file mode 100644 index 0000000000..10ebe058be --- /dev/null +++ b/mojo/common/file_path.mojom @@ -0,0 +1,8 @@ +// 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; + +[Native] +struct FilePath; diff --git a/mojo/common/file_path.typemap b/mojo/common/file_path.typemap new file mode 100644 index 0000000000..66d8c54da8 --- /dev/null +++ b/mojo/common/file_path.typemap @@ -0,0 +1,12 @@ +# 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_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" ] diff --git a/mojo/common/mojo_common_export.h b/mojo/common/mojo_common_export.h new file mode 100644 index 0000000000..48d21d0d3d --- /dev/null +++ b/mojo/common/mojo_common_export.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_COMMON_MOJO_COMMON_EXPORT_H_ +#define MOJO_COMMON_MOJO_COMMON_EXPORT_H_ + +#if defined(COMPONENT_BUILD) + +#if defined(WIN32) + +#if defined(MOJO_COMMON_IMPLEMENTATION) +#define MOJO_COMMON_EXPORT __declspec(dllexport) +#else +#define MOJO_COMMON_EXPORT __declspec(dllimport) +#endif + +#else // !defined(WIN32) + +#if defined(MOJO_COMMON_IMPLEMENTATION) +#define MOJO_COMMON_EXPORT __attribute__((visibility("default"))) +#else +#define MOJO_COMMON_EXPORT +#endif + +#endif // defined(WIN32) + +#else // !defined(COMPONENT_BUILD) +#define MOJO_COMMON_EXPORT +#endif + +#endif // MOJO_COMMON_MOJO_COMMON_EXPORT_H_ diff --git a/mojo/common/string16.mojom b/mojo/common/string16.mojom new file mode 100644 index 0000000000..173c8670cd --- /dev/null +++ b/mojo/common/string16.mojom @@ -0,0 +1,12 @@ +// 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::string16| in base/strings/string16.h +// Corresponds to |WTF::String| in +// third_party/WebKit/Source/wtf/text/WTFString.h. +struct String16 { + array<uint16> data; +}; diff --git a/mojo/common/string16.typemap b/mojo/common/string16.typemap new file mode 100644 index 0000000000..223de29c0d --- /dev/null +++ b/mojo/common/string16.typemap @@ -0,0 +1,12 @@ +# 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/string16.mojom" +public_headers = [ "//base/strings/string16.h" ] +traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] +public_deps = [ + "//mojo/common:struct_traits", +] + +type_mappings = [ "mojo.common.mojom.String16=base::string16" ] diff --git a/mojo/common/struct_traits_unittest.cc b/mojo/common/struct_traits_unittest.cc new file mode 100644 index 0000000000..5ac4bc9c80 --- /dev/null +++ b/mojo/common/struct_traits_unittest.cc @@ -0,0 +1,57 @@ +// 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() { + return traits_test_bindings_.CreateInterfacePtrAndBind(this); + } + + private: + // TraitsTestService: + void EchoVersion(const base::Optional<base::Version>& m, + const EchoVersionCallback& callback) override { + 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/mojo/common/test_common_custom_types.mojom b/mojo/common/test_common_custom_types.mojom new file mode 100644 index 0000000000..0f13680f68 --- /dev/null +++ b/mojo/common/test_common_custom_types.mojom @@ -0,0 +1,61 @@ +// 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.test; + +import "mojo/common/file.mojom"; +import "mojo/common/file_path.mojom"; +import "mojo/common/string16.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) + => (mojo.common.mojom.DictionaryValue out); + [Sync] + BounceListValue(mojo.common.mojom.ListValue in) + => (mojo.common.mojom.ListValue out); + [Sync] + BounceValue(mojo.common.mojom.Value? in) + => (mojo.common.mojom.Value? out); +}; + +interface TestString16 { + [Sync] + BounceString16(mojo.common.mojom.String16 in) + => (mojo.common.mojom.String16 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/mojo/common/text_direction.mojom b/mojo/common/text_direction.mojom new file mode 100644 index 0000000000..7d651245ed --- /dev/null +++ b/mojo/common/text_direction.mojom @@ -0,0 +1,12 @@ +// 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. + +module mojo.common.mojom; + +// Corresponds to |base::i18n::TextDirection| in base/i18n/rtl.h +enum TextDirection { + UNKNOWN_DIRECTION, + RIGHT_TO_LEFT, + LEFT_TO_RIGHT +}; diff --git a/mojo/common/text_direction.typemap b/mojo/common/text_direction.typemap new file mode 100644 index 0000000000..1f5be8edba --- /dev/null +++ b/mojo/common/text_direction.typemap @@ -0,0 +1,12 @@ +# 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/mojo/common/time.mojom b/mojo/common/time.mojom new file mode 100644 index 0000000000..b403bcac3a --- /dev/null +++ b/mojo/common/time.mojom @@ -0,0 +1,21 @@ +// 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; + +struct Time { + // The internal value is expressed in terms of microseconds since a fixed but + // intentionally unspecified epoch. + int64 internal_value; +}; + +struct TimeDelta { + int64 microseconds; +}; + +struct TimeTicks { + // The internal value is expressed in terms of microseconds since a fixed but + // intentionally unspecified epoch. + int64 internal_value; +}; diff --git a/mojo/common/time.typemap b/mojo/common/time.typemap new file mode 100644 index 0000000000..99e9e3ae8d --- /dev/null +++ b/mojo/common/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/common/time.mojom" +public_headers = [ "//base/time/time.h" ] +traits_headers = [ + "//ipc/ipc_message_utils.h", + "//mojo/common/common_custom_types_struct_traits.h", +] +public_deps = [ + "//ipc", + "//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/mojo/common/time_struct_traits.h b/mojo/common/time_struct_traits.h new file mode 100644 index 0000000000..b480edb648 --- /dev/null +++ b/mojo/common/time_struct_traits.h @@ -0,0 +1,55 @@ +// 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/mojo/common/traits_test_service.mojom b/mojo/common/traits_test_service.mojom new file mode 100644 index 0000000000..7659eea8ab --- /dev/null +++ b/mojo/common/traits_test_service.mojom @@ -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. + +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/mojo/common/typemaps.gni b/mojo/common/typemaps.gni new file mode 100644 index 0000000000..ae360310f1 --- /dev/null +++ b/mojo/common/typemaps.gni @@ -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. + +typemaps = [ + "//mojo/common/file.typemap", + "//mojo/common/file_path.typemap", + "//mojo/common/string16.typemap", + "//mojo/common/text_direction.typemap", + "//mojo/common/time.typemap", + "//mojo/common/unguessable_token.typemap", + "//mojo/common/values.typemap", + "//mojo/common/version.typemap", +] diff --git a/mojo/common/unguessable_token.mojom b/mojo/common/unguessable_token.mojom new file mode 100644 index 0000000000..32797171ca --- /dev/null +++ b/mojo/common/unguessable_token.mojom @@ -0,0 +1,11 @@ +// 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::UnguessableToken| in base/unguessable_token.h +struct UnguessableToken { + uint64 high; + uint64 low; +}; diff --git a/mojo/common/unguessable_token.typemap b/mojo/common/unguessable_token.typemap new file mode 100644 index 0000000000..ec7b1942b3 --- /dev/null +++ b/mojo/common/unguessable_token.typemap @@ -0,0 +1,12 @@ +# 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/mojo/common/values.mojom b/mojo/common/values.mojom new file mode 100644 index 0000000000..722198c56a --- /dev/null +++ b/mojo/common/values.mojom @@ -0,0 +1,32 @@ +// 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; + +union Value { + NullValue? null_value; + bool bool_value; + int32 int_value; + double double_value; + string string_value; + array<uint8> binary_value; + DictionaryValue dictionary_value; + ListValue list_value; +}; + +struct ListValue { + array<Value> values; +}; + +struct DictionaryValue { + map<string, Value> values; +}; + +// An empty struct representing a null base::Value. +struct NullValue { +}; + +// To avoid versioning problems for arc. TODO(sammc): Remove ASAP. +[Native] +struct LegacyListValue; diff --git a/mojo/common/values.typemap b/mojo/common/values.typemap new file mode 100644 index 0000000000..f1f3fc2772 --- /dev/null +++ b/mojo/common/values.typemap @@ -0,0 +1,25 @@ +# 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/values.mojom" +public_headers = [ "//base/values.h" ] +traits_headers = [ + "//ipc/ipc_message_utils.h", + "//mojo/common/values_struct_traits.h", +] +public_deps = [ + "//base", + "//ipc", +] +sources = [ + "values_struct_traits.cc", + "values_struct_traits.h", +] + +type_mappings = [ + "mojo.common.mojom.DictionaryValue=std::unique_ptr<base::DictionaryValue>[move_only,nullable_is_same_type]", + "mojo.common.mojom.LegacyListValue=base::ListValue[non_copyable_non_movable]", + "mojo.common.mojom.ListValue=std::unique_ptr<base::ListValue>[move_only,nullable_is_same_type]", + "mojo.common.mojom.Value=std::unique_ptr<base::Value>[move_only,nullable_is_same_type]", +] diff --git a/mojo/common/values_struct_traits.cc b/mojo/common/values_struct_traits.cc new file mode 100644 index 0000000000..6af7a39533 --- /dev/null +++ b/mojo/common/values_struct_traits.cc @@ -0,0 +1,109 @@ +// 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/memory/ptr_util.h" +#include "mojo/common/values_struct_traits.h" + +namespace mojo { + +bool StructTraits<common::mojom::ListValueDataView, + std::unique_ptr<base::ListValue>>:: + Read(common::mojom::ListValueDataView data, + std::unique_ptr<base::ListValue>* value_out) { + mojo::ArrayDataView<common::mojom::ValueDataView> view; + data.GetValuesDataView(&view); + + auto list_value = base::MakeUnique<base::ListValue>(); + for (size_t i = 0; i < view.size(); ++i) { + std::unique_ptr<base::Value> value; + if (!view.Read(i, &value)) + return false; + + list_value->Append(std::move(value)); + } + *value_out = std::move(list_value); + return true; +} + +bool StructTraits<common::mojom::DictionaryValueDataView, + std::unique_ptr<base::DictionaryValue>>:: + Read(common::mojom::DictionaryValueDataView data, + std::unique_ptr<base::DictionaryValue>* value_out) { + mojo::MapDataView<mojo::StringDataView, common::mojom::ValueDataView> view; + data.GetValuesDataView(&view); + auto dictionary_value = base::MakeUnique<base::DictionaryValue>(); + for (size_t i = 0; i < view.size(); ++i) { + base::StringPiece key; + std::unique_ptr<base::Value> value; + if (!view.keys().Read(i, &key) || !view.values().Read(i, &value)) + return false; + + dictionary_value->SetWithoutPathExpansion(key, std::move(value)); + } + *value_out = std::move(dictionary_value); + return true; +} + +std::unique_ptr<base::DictionaryValue> +CloneTraits<std::unique_ptr<base::DictionaryValue>, false>::Clone( + const std::unique_ptr<base::DictionaryValue>& input) { + auto result = base::MakeUnique<base::DictionaryValue>(); + result->MergeDictionary(input.get()); + return result; +} + +bool UnionTraits<common::mojom::ValueDataView, std::unique_ptr<base::Value>>:: + Read(common::mojom::ValueDataView data, + std::unique_ptr<base::Value>* value_out) { + switch (data.tag()) { + case common::mojom::ValueDataView::Tag::NULL_VALUE: { + *value_out = base::Value::CreateNullValue(); + return true; + } + case common::mojom::ValueDataView::Tag::BOOL_VALUE: { + *value_out = base::MakeUnique<base::Value>(data.bool_value()); + return true; + } + case common::mojom::ValueDataView::Tag::INT_VALUE: { + *value_out = base::MakeUnique<base::Value>(data.int_value()); + return true; + } + case common::mojom::ValueDataView::Tag::DOUBLE_VALUE: { + *value_out = base::MakeUnique<base::Value>(data.double_value()); + return true; + } + case common::mojom::ValueDataView::Tag::STRING_VALUE: { + base::StringPiece string_value; + if (!data.ReadStringValue(&string_value)) + return false; + *value_out = base::MakeUnique<base::Value>(string_value); + return true; + } + case common::mojom::ValueDataView::Tag::BINARY_VALUE: { + mojo::ArrayDataView<uint8_t> binary_data; + data.GetBinaryValueDataView(&binary_data); + *value_out = base::BinaryValue::CreateWithCopiedBuffer( + reinterpret_cast<const char*>(binary_data.data()), + binary_data.size()); + return true; + } + case common::mojom::ValueDataView::Tag::DICTIONARY_VALUE: { + std::unique_ptr<base::DictionaryValue> dictionary_value; + if (!data.ReadDictionaryValue(&dictionary_value)) + return false; + *value_out = std::move(dictionary_value); + return true; + } + case common::mojom::ValueDataView::Tag::LIST_VALUE: { + std::unique_ptr<base::ListValue> list_value; + if (!data.ReadListValue(&list_value)) + return false; + *value_out = std::move(list_value); + return true; + } + } + return false; +} + +} // namespace mojo diff --git a/mojo/common/values_struct_traits.h b/mojo/common/values_struct_traits.h new file mode 100644 index 0000000000..befcf3a6ea --- /dev/null +++ b/mojo/common/values_struct_traits.h @@ -0,0 +1,257 @@ +// 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_VALUES_STRUCT_TRAITS_H_ +#define MOJO_COMMON_VALUES_STRUCT_TRAITS_H_ + +#include "base/values.h" +#include "mojo/common/values.mojom.h" +#include "mojo/public/cpp/bindings/array_traits.h" +#include "mojo/public/cpp/bindings/clone_traits.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" + +namespace mojo { + +template <> +struct ArrayTraits<base::ListValue> { + using Element = std::unique_ptr<base::Value>; + using ConstIterator = base::ListValue::const_iterator; + + static size_t GetSize(const base::ListValue& input) { + return input.GetSize(); + } + + static ConstIterator GetBegin(const base::ListValue& input) { + return input.begin(); + } + + static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } + + static const Element& GetValue(ConstIterator& iterator) { return *iterator; } +}; + +template <> +struct StructTraits<common::mojom::ListValueDataView, base::ListValue> { + static const base::ListValue& values(const base::ListValue& value) { + return value; + } +}; + +template <> +struct StructTraits<common::mojom::ListValueDataView, + std::unique_ptr<base::ListValue>> { + static bool IsNull(const std::unique_ptr<base::ListValue>& value) { + return !value; + } + + static void SetToNull(std::unique_ptr<base::ListValue>* value) { + value->reset(); + } + + static const base::ListValue& values( + const std::unique_ptr<base::ListValue>& value) { + return *value; + } + + static bool Read(common::mojom::ListValueDataView data, + std::unique_ptr<base::ListValue>* value); +}; + +template <> +struct MapTraits<base::DictionaryValue> { + using Key = std::string; + using Value = base::Value; + using Iterator = base::DictionaryValue::Iterator; + + static size_t GetSize(const base::DictionaryValue& input) { + return input.size(); + } + + static Iterator GetBegin(const base::DictionaryValue& input) { + return Iterator(input); + } + + static void AdvanceIterator(Iterator& iterator) { iterator.Advance(); } + + static const Key& GetKey(Iterator& iterator) { return iterator.key(); } + + static const Value& GetValue(Iterator& iterator) { return iterator.value(); } +}; + +template <> +struct StructTraits<common::mojom::DictionaryValueDataView, + base::DictionaryValue> { + static const base::DictionaryValue& values( + const base::DictionaryValue& value) { + return value; + } +}; + +template <> +struct StructTraits<common::mojom::DictionaryValueDataView, + std::unique_ptr<base::DictionaryValue>> { + static bool IsNull(const std::unique_ptr<base::DictionaryValue>& value) { + return !value; + } + + static void SetToNull(std::unique_ptr<base::DictionaryValue>* value) { + value->reset(); + } + + static const base::DictionaryValue& values( + const std::unique_ptr<base::DictionaryValue>& value) { + return *value; + } + static bool Read(common::mojom::DictionaryValueDataView data, + std::unique_ptr<base::DictionaryValue>* value); +}; + +template <> +struct CloneTraits<std::unique_ptr<base::DictionaryValue>, false> { + static std::unique_ptr<base::DictionaryValue> Clone( + const std::unique_ptr<base::DictionaryValue>& input); +}; + +template <> +struct UnionTraits<common::mojom::ValueDataView, base::Value> { + static common::mojom::ValueDataView::Tag GetTag(const base::Value& data) { + switch (data.GetType()) { + case base::Value::Type::NONE: + return common::mojom::ValueDataView::Tag::NULL_VALUE; + case base::Value::Type::BOOLEAN: + return common::mojom::ValueDataView::Tag::BOOL_VALUE; + case base::Value::Type::INTEGER: + return common::mojom::ValueDataView::Tag::INT_VALUE; + case base::Value::Type::DOUBLE: + return common::mojom::ValueDataView::Tag::DOUBLE_VALUE; + case base::Value::Type::STRING: + return common::mojom::ValueDataView::Tag::STRING_VALUE; + case base::Value::Type::BINARY: + return common::mojom::ValueDataView::Tag::BINARY_VALUE; + case base::Value::Type::DICTIONARY: + return common::mojom::ValueDataView::Tag::DICTIONARY_VALUE; + case base::Value::Type::LIST: + return common::mojom::ValueDataView::Tag::LIST_VALUE; + } + NOTREACHED(); + return common::mojom::ValueDataView::Tag::NULL_VALUE; + } + + static common::mojom::NullValuePtr null_value(const base::Value& value) { + return common::mojom::NullValuePtr(); + } + + static bool bool_value(const base::Value& value) { + bool bool_value{}; + if (!value.GetAsBoolean(&bool_value)) + NOTREACHED(); + return bool_value; + } + + static int32_t int_value(const base::Value& value) { + int int_value{}; + if (!value.GetAsInteger(&int_value)) + NOTREACHED(); + return int_value; + } + + static double double_value(const base::Value& value) { + double double_value{}; + if (!value.GetAsDouble(&double_value)) + NOTREACHED(); + return double_value; + } + + static base::StringPiece string_value(const base::Value& value) { + base::StringPiece string_piece; + if (!value.GetAsString(&string_piece)) + NOTREACHED(); + return string_piece; + } + + static mojo::ConstCArray<uint8_t> binary_value(const base::Value& value) { + const base::BinaryValue* binary_value = nullptr; + if (!value.GetAsBinary(&binary_value)) + NOTREACHED(); + return mojo::ConstCArray<uint8_t>( + binary_value->GetSize(), + reinterpret_cast<const uint8_t*>(binary_value->GetBuffer())); + } + + static const base::ListValue& list_value(const base::Value& value) { + const base::ListValue* list_value = nullptr; + if (!value.GetAsList(&list_value)) + NOTREACHED(); + return *list_value; + } + static const base::DictionaryValue& dictionary_value( + const base::Value& value) { + const base::DictionaryValue* dictionary_value = nullptr; + if (!value.GetAsDictionary(&dictionary_value)) + NOTREACHED(); + return *dictionary_value; + } +}; + +template <> +struct UnionTraits<common::mojom::ValueDataView, std::unique_ptr<base::Value>> { + static bool IsNull(const std::unique_ptr<base::Value>& value) { + return !value; + } + + static void SetToNull(std::unique_ptr<base::Value>* value) { value->reset(); } + + static common::mojom::ValueDataView::Tag GetTag( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::GetTag( + *value); + } + + static common::mojom::NullValuePtr null_value( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::null_value( + *value); + } + static bool bool_value(const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::bool_value( + *value); + } + static int32_t int_value(const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::int_value( + *value); + } + static double double_value(const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::double_value( + *value); + } + static base::StringPiece string_value( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::string_value( + *value); + } + static mojo::ConstCArray<uint8_t> binary_value( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::binary_value( + *value); + } + static const base::ListValue& list_value( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, base::Value>::list_value( + *value); + } + static const base::DictionaryValue& dictionary_value( + const std::unique_ptr<base::Value>& value) { + return UnionTraits<common::mojom::ValueDataView, + base::Value>::dictionary_value(*value); + } + + static bool Read(common::mojom::ValueDataView data, + std::unique_ptr<base::Value>* value); +}; + +} // namespace mojo + +#endif // MOJO_COMMON_VALUES_STRUCT_TRAITS_H_ diff --git a/mojo/common/version.mojom b/mojo/common/version.mojom new file mode 100644 index 0000000000..6ddf6e6b8c --- /dev/null +++ b/mojo/common/version.mojom @@ -0,0 +1,10 @@ +// 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/mojo/common/version.typemap b/mojo/common/version.typemap new file mode 100644 index 0000000000..fa7fed9acf --- /dev/null +++ b/mojo/common/version.typemap @@ -0,0 +1,12 @@ +# 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" ] |