summaryrefslogtreecommitdiff
path: root/mojo/common
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/common')
-rw-r--r--mojo/common/BUILD.gn93
-rw-r--r--mojo/common/DEPS6
-rw-r--r--mojo/common/common_custom_types_struct_traits.cc108
-rw-r--r--mojo/common/common_custom_types_struct_traits.h85
-rw-r--r--mojo/common/common_custom_types_unittest.cc433
-rw-r--r--mojo/common/data_pipe_drainer.cc50
-rw-r--r--mojo/common/data_pipe_drainer.h49
-rw-r--r--mojo/common/data_pipe_utils.cc96
-rw-r--r--mojo/common/data_pipe_utils.h32
-rw-r--r--mojo/common/file.mojom10
-rw-r--r--mojo/common/file.typemap13
-rw-r--r--mojo/common/file_path.mojom8
-rw-r--r--mojo/common/file_path.typemap12
-rw-r--r--mojo/common/mojo_common_export.h32
-rw-r--r--mojo/common/string16.mojom12
-rw-r--r--mojo/common/string16.typemap12
-rw-r--r--mojo/common/struct_traits_unittest.cc57
-rw-r--r--mojo/common/test_common_custom_types.mojom61
-rw-r--r--mojo/common/text_direction.mojom12
-rw-r--r--mojo/common/text_direction.typemap12
-rw-r--r--mojo/common/time.mojom21
-rw-r--r--mojo/common/time.typemap20
-rw-r--r--mojo/common/time_struct_traits.h55
-rw-r--r--mojo/common/traits_test_service.mojom14
-rw-r--r--mojo/common/typemaps.gni14
-rw-r--r--mojo/common/unguessable_token.mojom11
-rw-r--r--mojo/common/unguessable_token.typemap12
-rw-r--r--mojo/common/values.mojom32
-rw-r--r--mojo/common/values.typemap25
-rw-r--r--mojo/common/values_struct_traits.cc109
-rw-r--r--mojo/common/values_struct_traits.h257
-rw-r--r--mojo/common/version.mojom10
-rw-r--r--mojo/common/version.typemap12
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" ]