diff options
author | yzshen <yzshen@chromium.org> | 2016-03-14 15:26:22 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-14 22:28:22 +0000 |
commit | 791f9b24ca1758ced39235bda1a4e0411801309c (patch) | |
tree | 4cd8c431ca80ccca68c2be36819a40aeb7978b74 | |
parent | 10fd187c1de8dff86eb165deaecec7a5b5f6cc36 (diff) | |
download | chromium_src-791f9b24ca1758ced39235bda1a4e0411801309c.zip chromium_src-791f9b24ca1758ced39235bda1a4e0411801309c.tar.gz chromium_src-791f9b24ca1758ced39235bda1a4e0411801309c.tar.bz2 |
Mojo C++ bindings: support mapping mojo string to WTF::String.
The generator now supports a "--for_blink" flag. When it is specified, the generator will map mojo string to WTF::String.
BUG=583738
Review URL: https://codereview.chromium.org/1751563002
Cr-Commit-Position: refs/heads/master@{#381091}
31 files changed, 574 insertions, 44 deletions
diff --git a/mojo/mojo_edk_tests.gyp b/mojo/mojo_edk_tests.gyp index b8ff828..e1a51de 100644 --- a/mojo/mojo_edk_tests.gyp +++ b/mojo/mojo_edk_tests.gyp @@ -101,6 +101,21 @@ ], }, { + # GN version: //mojo/public/cpp/bindings/tests:for_blink_tests + 'target_name': 'mojo_public_bindings_for_blink_tests', + 'type': 'static_library', + 'dependencies': [ + '../testing/gtest.gyp:gtest', + 'mojo_public.gyp:mojo_cpp_bindings', + 'mojo_public.gyp:mojo_public_test_utils', + 'mojo_public.gyp:mojo_public_test_wtf_types', + 'mojo_public.gyp:mojo_public_test_wtf_types_blink', + ], + 'sources': [ + 'public/cpp/bindings/tests/wtf_types_unittest.cc', + ], + }, + { # GN version: //mojo/edk/test:mojo_public_bindings_perftests 'target_name': 'mojo_public_bindings_perftests', 'type': 'executable', diff --git a/mojo/mojo_public.gyp b/mojo/mojo_public.gyp index 2844195..da318ae 100644 --- a/mojo/mojo_public.gyp +++ b/mojo/mojo_public.gyp @@ -177,6 +177,9 @@ 'public/cpp/bindings/lib/validation_util.cc', 'public/cpp/bindings/lib/validation_util.h', 'public/cpp/bindings/lib/value_traits.h', + # Include the .h but not the .cc file. The .h file is used by + # serialization_forward.h. + 'public/cpp/bindings/lib/wtf_string_serialization.h', 'public/cpp/bindings/message.h', 'public/cpp/bindings/message_filter.h', 'public/cpp/bindings/no_interface.h', @@ -194,6 +197,33 @@ ], }, { + # GN version: //mojo/public/cpp/bindings:wtf_support + 'target_name': 'mojo_cpp_bindings_wtf_support', + 'type': 'static_library', + 'include_dirs': [ + '..' + ], + 'sources': [ + 'public/cpp/bindings/lib/wtf_serialization.h', + 'public/cpp/bindings/lib/wtf_string_serialization.cc', + 'public/cpp/bindings/lib/wtf_string_serialization.h', + ], + 'dependencies': [ + 'mojo_cpp_bindings', + '../third_party/WebKit/Source/config.gyp:config', + '../third_party/WebKit/Source/wtf/wtf.gyp:wtf', + ], + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + '../third_party/WebKit/Source/config.gyp:config', + ], + 'direct_dependent_settings': { + 'variables': { + 'clang_warning_flags_unset': [ '-Wglobal-constructors' ], + }, + }, + }, + { # GN version: //mojo/message_pump 'target_name': 'mojo_message_pump_lib', 'type': '<(component)', @@ -456,6 +486,26 @@ 'mojo_cpp_bindings', ], }, + { + 'target_name': 'mojo_public_test_wtf_types', + 'type': 'static_library', + 'sources': [ + 'public/interfaces/bindings/tests/test_wtf_types.mojom', + ], + 'includes': [ 'mojom_bindings_generator.gypi' ], + }, + { + 'target_name': 'mojo_public_test_wtf_types_blink', + 'type': 'static_library', + 'variables': { + 'mojom_variant': 'blink', + 'for_blink': 'true', + }, + 'sources': [ + 'public/interfaces/bindings/tests/test_wtf_types.mojom', + ], + 'includes': [ 'mojom_bindings_generator.gypi' ], + }, ], 'conditions': [ ['OS == "android"', { diff --git a/mojo/mojom_bindings_generator.gypi b/mojo/mojom_bindings_generator.gypi index 3b2e1bb..6518ee4 100644 --- a/mojo/mojom_bindings_generator.gypi +++ b/mojo/mojom_bindings_generator.gypi @@ -11,10 +11,12 @@ 'mojom_typemap_dependencies%': [], 'mojom_typemaps%': [], 'mojom_variant%': 'none', + 'for_blink%': 'false', }, 'mojom_typemap_dependencies%': ['<@(mojom_typemap_dependencies)'], 'mojom_typemaps%': ['<@(mojom_typemaps)'], 'mojom_variant%': '<(mojom_variant)', + 'for_blink%': '<(for_blink)', 'mojom_base_output_dir': '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))', 'mojom_generated_outputs': [ @@ -30,6 +32,18 @@ }, { 'mojom_output_languages%': 'c++', }], + ['for_blink=="true"', { + 'mojom_generator_wtf_arg%': [ + '--for_blink', + ], + 'wtf_dependencies%': [ + 'mojo_public.gyp:mojo_cpp_bindings_wtf_support', + '../third_party/WebKit/Source/wtf/wtf.gyp:wtf', + ], + }, { + 'mojom_generator_wtf_arg%': [], + 'wtf_dependencies%': [], + }], ], }, 'actions': [ @@ -98,6 +112,7 @@ '-g', '<(mojom_output_languages)', '<@(mojom_generator_typemap_args)', '<@(mojom_extra_generator_args)', + '<@(mojom_generator_wtf_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', ], @@ -110,9 +125,11 @@ '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation', '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates', '<@(mojom_typemap_dependencies)', + '<@(wtf_dependencies)', ], 'export_dependent_settings': [ '<@(mojom_typemap_dependencies)', + '<@(wtf_dependencies)', ], 'include_dirs': [ '<(DEPTH)', diff --git a/mojo/mojom_bindings_generator_explicit.gypi b/mojo/mojom_bindings_generator_explicit.gypi index 319c4ff..0ca10c6 100644 --- a/mojo/mojom_bindings_generator_explicit.gypi +++ b/mojo/mojom_bindings_generator_explicit.gypi @@ -9,8 +9,10 @@ 'variables': { 'variables': { 'mojom_variant%': 'none', + 'for_blink%': 'false', }, 'mojom_variant%': '<(mojom_variant)', + 'for_blink%': '<(for_blink)', 'mojom_base_output_dir': '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))', 'mojom_generated_outputs': [ @@ -25,6 +27,18 @@ }, { 'mojom_output_languages%': 'c++', }], + ['for_blink=="true"', { + 'mojom_generator_wtf_arg%': [ + '--for_blink', + ], + 'wtf_dependencies%': [ + 'mojo_public.gyp:mojo_cpp_bindings_wtf_support', + '../third_party/WebKit/Source/wtf/wtf.gyp:wtf', + ], + }, { + 'mojom_generator_wtf_arg%': [], + 'wtf_dependencies%': [], + }], ], }, # Given mojom files as inputs, generate sources. These sources will be @@ -83,6 +97,7 @@ '--variant', '<(mojom_variant)', '-g', '<(mojom_output_languages)', '<@(mojom_extra_generator_args)', + '<@(mojom_generator_wtf_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', ], @@ -99,6 +114,10 @@ ], 'dependencies': [ '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates', + '<@(wtf_dependencies)', + ], + 'export_dependent_settings': [ + '<@(wtf_dependencies)', ], # Prevent the generated sources from being injected into the "all" target by # preventing the code generator from being directly depended on by the "all" diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 0486a52..1939ff6 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn @@ -81,6 +81,10 @@ source_set("bindings") { "lib/validation_util.cc", "lib/validation_util.h", "lib/value_traits.h", + + # Include the .h but not the .cc file. The .h file is used by + # serialization_forward.h. + "lib/wtf_string_serialization.h", "map.h", "message.h", "message_filter.h", @@ -120,3 +124,18 @@ source_set("callback") { "//mojo/public/cpp/system", ] } + +source_set("wtf_support") { + sources = [ + "lib/wtf_serialization.h", + "lib/wtf_string_serialization.cc", + "lib/wtf_string_serialization.h", + ] + + public_deps = [ + ":bindings", + "//third_party/WebKit/Source/wtf", + ] + + public_configs = [ "//third_party/WebKit/Source:config" ] +} diff --git a/mojo/public/cpp/bindings/DEPS b/mojo/public/cpp/bindings/DEPS new file mode 100644 index 0000000..36eba44 --- /dev/null +++ b/mojo/public/cpp/bindings/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/WebKit/Source/wtf", +] diff --git a/mojo/public/cpp/bindings/lib/array_serialization_traits.h b/mojo/public/cpp/bindings/lib/array_serialization_traits.h index e73d352..35b12f1 100644 --- a/mojo/public/cpp/bindings/lib/array_serialization_traits.h +++ b/mojo/public/cpp/bindings/lib/array_serialization_traits.h @@ -19,6 +19,10 @@ #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" +namespace WTF { +class String; +} + namespace mojo { namespace internal { @@ -191,7 +195,8 @@ struct ArraySerializer< private: template <typename T, bool is_array = IsSpecializationOf<Array, T>::value, - bool is_string = std::is_same<T, String>::value> + bool is_string = std::is_same<T, String>::value || + std::is_same<T, WTF::String>::value> struct SerializeCaller { static void Run(T input, Buffer* buf, diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index a467acd..8d32082 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h @@ -11,6 +11,9 @@ #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/system/core.h" +namespace WTF { +class String; +} namespace mojo { class String; @@ -162,6 +165,11 @@ struct WrapperTraits<String, false> { typedef String_Data* DataType; }; +template <> +struct WrapperTraits<WTF::String, false> { + typedef String_Data* DataType; +}; + } // namespace internal } // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/bindings_serialization.h b/mojo/public/cpp/bindings/lib/bindings_serialization.h index 017448b..7a10b1c 100644 --- a/mojo/public/cpp/bindings/lib/bindings_serialization.h +++ b/mojo/public/cpp/bindings/lib/bindings_serialization.h @@ -112,6 +112,11 @@ inline void AssociatedInterfaceDataToPtrInfo( output->set_version(input->version); } +class WTFStringContext { + public: + virtual ~WTFStringContext() {} +}; + // Context information for serialization/deserialization routines. struct SerializationContext { SerializationContext(); @@ -121,6 +126,8 @@ struct SerializationContext { // Used to serialize/deserialize associated interface pointers and requests. scoped_refptr<MultiplexRouter> router; + + scoped_ptr<WTFStringContext> wtf_string_context; }; } // namespace internal diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h index 1f809b0..39d046c 100644 --- a/mojo/public/cpp/bindings/lib/serialization_forward.h +++ b/mojo/public/cpp/bindings/lib/serialization_forward.h @@ -8,10 +8,12 @@ #include <stddef.h> #include "mojo/public/cpp/bindings/lib/string_serialization.h" +#include "mojo/public/cpp/bindings/lib/wtf_string_serialization.h" // This file is included by serialization implementation files to avoid circular // includes. -// Users of the serialization funtions should include serialization.h. +// Users of the serialization funtions should include serialization.h (and also +// wtf_serialization.h if necessary). namespace mojo { diff --git a/mojo/public/cpp/bindings/lib/wtf_serialization.h b/mojo/public/cpp/bindings/lib/wtf_serialization.h new file mode 100644 index 0000000..11733ec --- /dev/null +++ b/mojo/public/cpp/bindings/lib/wtf_serialization.h @@ -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. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ + +#include "mojo/public/cpp/bindings/lib/wtf_string_serialization.h" + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc b/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc new file mode 100644 index 0000000..d1b749d --- /dev/null +++ b/mojo/public/cpp/bindings/lib/wtf_string_serialization.cc @@ -0,0 +1,119 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/bindings/lib/wtf_string_serialization.h" + +#include <string.h> + +#include <queue> + +#include "base/logging.h" +#include "third_party/WebKit/Source/wtf/text/StringUTF8Adaptor.h" +#include "third_party/WebKit/Source/wtf/text/WTFString.h" + +namespace WTF { +namespace { + +struct UTF8AdaptorWithPointer { + explicit UTF8AdaptorWithPointer(const WTF::String& input) + : utf8_adaptor(input) { +#if DCHECK_IS_ON() + original_input = reinterpret_cast<uintptr_t>(&input); +#endif + } + + ~UTF8AdaptorWithPointer() {} + + WTF::StringUTF8Adaptor utf8_adaptor; + +#if DCHECK_IS_ON() + // For sanity check only. Never dereferenced. + uintptr_t original_input; +#endif +}; + +class WTFStringContextImpl : public mojo::internal::WTFStringContext { + public: + WTFStringContextImpl() {} + ~WTFStringContextImpl() override {} + + std::queue<UTF8AdaptorWithPointer>& utf8_adaptors() { return utf8_adaptors_; } + + private: + // When serializing an object, we call GetSerializedSize_() recursively on + // all its elements/members to compute the total size, and then call + // Serialize*_() recursively in the same order to do the actual + // serialization. If some WTF::Strings need to be converted to UTF8, we don't + // want to do that twice. Therefore, we store a WTF::StringUTF8Adaptor for + // each in the first pass, and reuse it in the second pass. + std::queue<UTF8AdaptorWithPointer> utf8_adaptors_; + + DISALLOW_COPY_AND_ASSIGN(WTFStringContextImpl); +}; + +} // namespace + +size_t GetSerializedSize_(const WTF::String& input, + mojo::internal::SerializationContext* context) { + if (input.isNull()) + return 0; + + if (!context->wtf_string_context) + context->wtf_string_context.reset(new WTFStringContextImpl); + + auto& utf8_adaptors = + static_cast<WTFStringContextImpl*>(context->wtf_string_context.get()) + ->utf8_adaptors(); + + utf8_adaptors.emplace(input); + + return mojo::internal::Align(sizeof(mojo::internal::String_Data) + + utf8_adaptors.back().utf8_adaptor.length()); +} + +void Serialize_(const WTF::String& input, + mojo::internal::Buffer* buf, + mojo::internal::String_Data** output, + mojo::internal::SerializationContext* context) { + if (input.isNull()) { + *output = nullptr; + return; + } + + auto& utf8_adaptors = + static_cast<WTFStringContextImpl*>(context->wtf_string_context.get()) + ->utf8_adaptors(); + + DCHECK(!utf8_adaptors.empty()); +#if DCHECK_IS_ON() + DCHECK_EQ(utf8_adaptors.front().original_input, + reinterpret_cast<uintptr_t>(&input)); +#endif + + const WTF::StringUTF8Adaptor& adaptor = utf8_adaptors.front().utf8_adaptor; + + mojo::internal::String_Data* result = + mojo::internal::String_Data::New(adaptor.length(), buf); + if (result) + memcpy(result->storage(), adaptor.data(), adaptor.length()); + + utf8_adaptors.pop(); + + *output = result; +} + +bool Deserialize_(mojo::internal::String_Data* input, + WTF::String* output, + mojo::internal::SerializationContext* context) { + if (input) { + WTF::String result = WTF::String::fromUTF8(input->storage(), input->size()); + output->swap(result); + } else if (!output->isNull()) { + WTF::String result; + output->swap(result); + } + return true; +} + +} // namespace WTF diff --git a/mojo/public/cpp/bindings/lib/wtf_string_serialization.h b/mojo/public/cpp/bindings/lib/wtf_string_serialization.h new file mode 100644 index 0000000..a110265 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/wtf_string_serialization.h @@ -0,0 +1,28 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ + +#include <stddef.h> + +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" + +namespace WTF { +class String; + +size_t GetSerializedSize_(const WTF::String& input, + mojo::internal::SerializationContext* context); +void Serialize_(const WTF::String& input, + mojo::internal::Buffer* buffer, + mojo::internal::String_Data** output, + mojo::internal::SerializationContext* context); +bool Deserialize_(mojo::internal::String_Data* input, + WTF::String* output, + mojo::internal::SerializationContext* context); + +} // namespace WTF + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_STRING_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index c689fe31..6a516bb 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn @@ -68,6 +68,24 @@ source_set("tests") { ] } +source_set("for_blink_tests") { + testonly = true + + sources = [ + "wtf_types_unittest.cc", + ] + + deps = [ + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/bindings:callback", + "//mojo/public/cpp/system", + "//mojo/public/cpp/test_support:test_utils", + "//mojo/public/interfaces/bindings/tests:test_wtf_types", + "//mojo/public/interfaces/bindings/tests:test_wtf_types_blink", + "//testing/gtest", + ] +} + source_set("perftests") { testonly = true diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc index bc77298..17b1724 100644 --- a/mojo/public/cpp/bindings/tests/pickle_unittest.cc +++ b/mojo/public/cpp/bindings/tests/pickle_unittest.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <string.h> - #include <string> #include "base/bind.h" @@ -15,6 +13,7 @@ #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/tests/pickled_struct_blink.h" #include "mojo/public/cpp/bindings/tests/pickled_struct_chromium.h" +#include "mojo/public/cpp/bindings/tests/variant_test_util.h" #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h" #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-chromium.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,19 +22,6 @@ namespace mojo { namespace test { namespace { -// Converts a request of Interface1 to a request of Interface0. Interface0 and -// Interface1 are expected to be two variants of the same mojom interface. -// In real-world use cases, users shouldn't need to worry about this. Because it -// is rare to deal with two variants of the same interface in the same app. -template <typename Interface0, typename Interface1> -InterfaceRequest<Interface0> ConvertInterfaceRequest( - InterfaceRequest<Interface1> request) { - DCHECK_EQ(0, strcmp(Interface0::Name_, Interface1::Name_)); - InterfaceRequest<Interface0> result; - result.Bind(request.PassMessagePipe()); - return result; -} - template <typename T> void DoExpectResult(int foo, int bar, diff --git a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc b/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc index e1ffacb..cd99785 100644 --- a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc +++ b/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc @@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/tests/rect_blink.h" #include "mojo/public/cpp/bindings/tests/rect_chromium.h" #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl.h" +#include "mojo/public/cpp/bindings/tests/variant_test_util.h" #include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h" #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h" #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-chromium.h" @@ -21,19 +22,6 @@ namespace mojo { namespace test { namespace { -// Converts a request of Interface1 to a request of Interface0. Interface0 and -// Interface1 are expected to be two variants of the same mojom interface. -// In real-world use cases, users shouldn't need to worry about this. Because it -// is rare to deal with two variants of the same interface in the same app. -template <typename Interface0, typename Interface1> -InterfaceRequest<Interface0> ConvertInterfaceRequest( - InterfaceRequest<Interface1> request) { - DCHECK_EQ(0, strcmp(Interface0::Name_, Interface1::Name_)); - InterfaceRequest<Interface0> result; - result.Bind(request.PassMessagePipe()); - return result; -} - template <typename T> void DoExpectResult(const T& expected, const base::Closure& callback, diff --git a/mojo/public/cpp/bindings/tests/variant_test_util.h b/mojo/public/cpp/bindings/tests/variant_test_util.h new file mode 100644 index 0000000..3f6b1f1 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/variant_test_util.h @@ -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. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_VARIANT_TEST_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_VARIANT_TEST_UTIL_H_ + +#include <string.h> + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/interface_request.h" + +namespace mojo { +namespace test { + +// Converts a request of Interface1 to a request of Interface0. Interface0 and +// Interface1 are expected to be two variants of the same mojom interface. +// In real-world use cases, users shouldn't need to worry about this. Because it +// is rare to deal with two variants of the same interface in the same app. +template <typename Interface0, typename Interface1> +InterfaceRequest<Interface0> ConvertInterfaceRequest( + InterfaceRequest<Interface1> request) { + DCHECK_EQ(0, strcmp(Interface0::Name_, Interface1::Name_)); + InterfaceRequest<Interface0> result; + result.Bind(request.PassMessagePipe()); + return result; +} + +} // namespace test +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_VARIANT_TEST_UTIL_H_ diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc new file mode 100644 index 0000000..20486eb --- /dev/null +++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc @@ -0,0 +1,134 @@ +// 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/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" +#include "mojo/public/cpp/bindings/lib/wtf_serialization.h" +#include "mojo/public/cpp/bindings/tests/variant_test_util.h" +#include "mojo/public/interfaces/bindings/tests/test_wtf_types.mojom-blink.h" +#include "mojo/public/interfaces/bindings/tests/test_wtf_types.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { +namespace { + +const char kHelloWorld[] = "hello world"; + +// Replace the "o"s in "hello world" with "o"s with acute. +const char kUTF8HelloWorld[] = "hell\xC3\xB3 w\xC3\xB3rld"; + +class TestWTFImpl : public TestWTF { + public: + explicit TestWTFImpl(TestWTFRequest request) + : binding_(this, std::move(request)) {} + + // mojo::test::TestWTF implementation: + void EchoString(const String& str, + const EchoStringCallback& callback) override { + callback.Run(str); + } + + private: + Binding<TestWTF> binding_; +}; + +class WTFTypesTest : public testing::Test { + public: + WTFTypesTest() {} + + private: + base::MessageLoop loop_; +}; + +} // namespace + +TEST_F(WTFTypesTest, WTFToWTFStringSerialization) { + Array<WTF::String> strs(4); + // strs[0] is null. + // strs[1] is empty. + strs[1] = ""; + strs[2] = kHelloWorld; + strs[3] = WTF::String::fromUTF8(kUTF8HelloWorld); + + Array<WTF::String> cloned_strs = strs.Clone(); + + mojo::internal::SerializationContext context; + size_t size = GetSerializedSize_(cloned_strs, &context); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<mojo::internal::String_Data*>* data; + mojo::internal::ArrayValidateParams validate_params( + 0, true, new mojo::internal::ArrayValidateParams(0, false, nullptr)); + SerializeArray_(std::move(cloned_strs), &buf, &data, &validate_params, + &context); + + Array<WTF::String> strs2; + Deserialize_(data, &strs2, nullptr); + + EXPECT_TRUE(strs.Equals(strs2)); +} + +TEST_F(WTFTypesTest, WTFToMojoStringSerialization) { + Array<WTF::String> strs(4); + // strs[0] is null. + // strs[1] is empty. + strs[1] = ""; + strs[2] = kHelloWorld; + strs[3] = WTF::String::fromUTF8(kUTF8HelloWorld); + + Array<WTF::String> cloned_strs = strs.Clone(); + + mojo::internal::SerializationContext context; + size_t size = GetSerializedSize_(cloned_strs, &context); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<mojo::internal::String_Data*>* data; + mojo::internal::ArrayValidateParams validate_params( + 0, true, new mojo::internal::ArrayValidateParams(0, false, nullptr)); + SerializeArray_(std::move(cloned_strs), &buf, &data, &validate_params, + &context); + + Array<mojo::String> strs2; + Deserialize_(data, &strs2, nullptr); + + ASSERT_EQ(4u, strs2.size()); + EXPECT_TRUE(strs2[0].is_null()); + EXPECT_TRUE("" == strs2[1]); + EXPECT_TRUE(kHelloWorld == strs2[2]); + EXPECT_TRUE(kUTF8HelloWorld == strs2[3]); +} + +TEST_F(WTFTypesTest, SendString) { + blink::TestWTFPtr ptr; + TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr))); + + WTF::String strs[4]; + // strs[0] is null. + // strs[1] is empty. + strs[1] = ""; + strs[2] = kHelloWorld; + strs[3] = WTF::String::fromUTF8(kUTF8HelloWorld); + + for (size_t i = 0; i < arraysize(strs); ++i) { + base::RunLoop loop; + // Test that a WTF::String is unchanged after the following conversion: + // - serialized; + // - deserialized as mojo::String; + // - serialized; + // - deserialized as WTF::String. + ptr->EchoString(strs[i], [&loop, &strs, &i](const WTF::String& str) { + EXPECT_EQ(strs[i], str); + loop.Quit(); + }); + loop.Run(); + } +} + +} // namespace test +} // namespace mojo diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn index 464566c..c9b01b4 100644 --- a/mojo/public/interfaces/bindings/tests/BUILD.gn +++ b/mojo/public/interfaces/bindings/tests/BUILD.gn @@ -97,3 +97,26 @@ mojom("test_interfaces_blink") { ":test_interfaces", ] } + +mojom("test_wtf_types") { + testonly = true + + sources = [ + "test_wtf_types.mojom", + ] +} + +mojom("test_wtf_types_blink") { + testonly = true + + sources = [ + "test_wtf_types.mojom", + ] + + deps = [ + ":test_wtf_types", + ] + + for_blink = true + variant = "blink" +} diff --git a/mojo/public/interfaces/bindings/tests/test_wtf_types.mojom b/mojo/public/interfaces/bindings/tests/test_wtf_types.mojom new file mode 100644 index 0000000..f776309 --- /dev/null +++ b/mojo/public/interfaces/bindings/tests/test_wtf_types.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.test; + +struct TestWTFCodeGeneration { + string str; + string? nullable_str; +}; + +interface TestWTF { + EchoString(string? str) => (string? str); +}; diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl index dddbbd3..76888c7 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl @@ -53,7 +53,7 @@ class {{interface.name}} { } {%- endif %} - using {{method.name}}Callback = {{interface_macros.declare_callback(method)}}; + using {{method.name}}Callback = {{interface_macros.declare_callback(method, for_blink)}}; {%- endif %} virtual void {{method.name}}({{interface_macros.declare_request_params("", method)}}) = 0; {%- endfor %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl index b00b1da..f6056e8 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl @@ -5,13 +5,13 @@ {%- endfor %} {%- endmacro %} -{%- macro declare_callback(method) -%} +{%- macro declare_callback(method, for_blink) -%} mojo::Callback<void( {%- for param in method.response_parameters -%} {#- TODO(yzshen): Previously |cpp_result_type| is used here incorrectly. The outcome is we will use mojo::String instead of const mojo::String&. Preserve the behavior temporarily. #} -{%- if not param.kind|is_string_kind -%} +{%- if (not param.kind|is_string_kind) or for_blink -%} {{param.kind|cpp_const_wrapper_type}} {%- else -%} mojo::String diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index 8c9c0fb..4d1dc90 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl @@ -36,6 +36,10 @@ #include "mojo/public/cpp/bindings/lib/validation_util.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" +{%- if for_blink %} +#include "mojo/public/cpp/bindings/lib/wtf_serialization.h" +{%- endif %} + {%- for namespace in namespaces_as_array %} namespace {{namespace}} { {%- endfor %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index af93b84..8046116e 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -32,13 +32,17 @@ #include "mojo/public/cpp/bindings/map.h" #include "mojo/public/cpp/bindings/message_filter.h" #include "mojo/public/cpp/bindings/no_interface.h" -#include "mojo/public/cpp/bindings/string.h" #include "mojo/public/cpp/bindings/struct_ptr.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "{{variant_path}}-internal.h" {%- for import in imports %} #include "{{import.module.path}}.h" {%- endfor %} +{%- if not for_blink %} +#include "mojo/public/cpp/bindings/string.h" +{%- else %} +#include "third_party/WebKit/Source/wtf/text/WTFString.h" +{%- endif %} {%- for namespace in namespaces_as_array %} namespace {{namespace}} { diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index c2d3a1c..4433740 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py @@ -42,9 +42,10 @@ _kind_to_cpp_literal_suffix = { mojom.UINT64: "ULL", } -# TODO(rockot): Get rid of this global. This requires some refactoring of the +# TODO(rockot): Get rid of these globals. This requires some refactoring of the # generator library code so that filters can use the generator as context. _current_typemap = {} +_for_blink = False def ConstantValue(constant): @@ -56,9 +57,10 @@ def DefaultValue(field): assert field.default == "default" return "%s::New()" % GetNameForKind(field.kind) return ExpressionToText(field.default, kind=field.kind) - if (mojom.IsStringKind(field.kind) or mojom.IsArrayKind(field.kind) or - mojom.IsMapKind(field.kind)): + if mojom.IsArrayKind(field.kind) or mojom.IsMapKind(field.kind): return "nullptr"; + if mojom.IsStringKind(field.kind): + return "" if _for_blink else "nullptr" return "" def NamespaceToArray(namespace): @@ -187,7 +189,7 @@ def GetCppArrayArgWrapperType(kind): raise Exception("Arrays of associated interface requests not yet " "supported!") if mojom.IsStringKind(kind): - return "mojo::String" + return "WTF::String" if _for_blink else "mojo::String" if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): @@ -223,7 +225,7 @@ def GetCppResultWrapperType(kind): if mojom.IsAssociatedInterfaceRequestKind(kind): return "%sAssociatedRequest" % GetNameForKind(kind.kind) if mojom.IsStringKind(kind): - return "mojo::String" + return "WTF::String" if _for_blink else "mojo::String" if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): @@ -265,7 +267,7 @@ def GetCppWrapperType(kind): if mojom.IsAssociatedInterfaceRequestKind(kind): return "%sAssociatedRequest" % GetNameForKind(kind.kind) if mojom.IsStringKind(kind): - return "mojo::String" + return "WTF::String" if _for_blink else "mojo::String" if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): @@ -301,7 +303,7 @@ def GetCppConstWrapperType(kind): if mojom.IsEnumKind(kind): return GetNameForKind(kind) if mojom.IsStringKind(kind): - return "const mojo::String&" + return "const WTF::String&" if _for_blink else "const mojo::String&" if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): @@ -525,6 +527,7 @@ class Generator(generator.Generator): "interfaces": self.GetInterfaces(), "variant": self.variant, "extra_headers": self.GetExtraHeaders(), + "for_blink": self.for_blink, } @staticmethod @@ -550,6 +553,8 @@ class Generator(generator.Generator): def GenerateFiles(self, args): global _current_typemap _current_typemap = self.typemap + global _for_blink + _for_blink = self.for_blink suffix = "-%s" % self.variant if self.variant else "" self.Write(self.GenerateModuleHeader(), self.MatchMojomFilePath("%s%s.h" % (self.module.name, suffix))) diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index d8923dd..9ff1af1 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni @@ -59,6 +59,9 @@ mojom_generator_sources = [ # testonly (optional) # # visibility (optional) +# +# for_blink (optional, C++ only) +# Use WTF types as generated type for mojo string/array/map. template("mojom") { assert( defined(invoker.sources) || defined(invoker.deps) || @@ -158,6 +161,10 @@ template("mojom") { } inputs += invoker.typemaps } + + if (defined(invoker.for_blink) && invoker.for_blink) { + args += [ "--for_blink" ] + } } } @@ -245,6 +252,9 @@ template("mojom") { full_name = get_label_info(d, "label_no_toolchain") deps += [ "${full_name}_${cpp_sources_suffix}" ] } + if (defined(invoker.for_blink) && invoker.for_blink) { + public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] + } } } diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py index 18b9496..130e730 100755 --- a/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py @@ -143,7 +143,8 @@ class MojomProcessor(object): for language, generator_module in generator_modules.iteritems(): generator = generator_module.Generator( module, args.output_dir, typemap=self._typemap.get(language, {}), - variant=args.variant, bytecode_path=args.bytecode_path) + variant=args.variant, bytecode_path=args.bytecode_path, + for_blink=args.for_blink) filtered_args = [] if hasattr(generator_module, 'GENERATOR_PREFIX'): prefix = '--' + generator_module.GENERATOR_PREFIX + '_' @@ -252,6 +253,9 @@ def main(): "the path from which to load template bytecode; to generate template " "bytecode, run %s precompile BYTECODE_PATH" % os.path.basename( sys.argv[0]))) + generate_parser.add_argument("--for_blink", action="store_true", + help="Use WTF types as generated types for mojo " + "string/array/map.") generate_parser.set_defaults(func=_Generate) precompile_parser = subparsers.add_parser("precompile", diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index 0ecc615..a97d2ea 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py @@ -37,12 +37,13 @@ class Generator(object): # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all # files to stdout. def __init__(self, module, output_dir=None, typemap=None, variant=None, - bytecode_path=None): + bytecode_path=None, for_blink=False): self.module = module self.output_dir = output_dir self.typemap = typemap or {} self.variant = variant self.bytecode_path = bytecode_path + self.for_blink = for_blink def GetStructsFromMethods(self): result = [] diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index ce0600d..3254fb5 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn @@ -542,6 +542,7 @@ test("blink_platform_unittests") { "//cc/blink", "//mojo/edk/embedder:headers", "//mojo/edk/test:test_support", + "//mojo/public/cpp/bindings/tests:for_blink_tests", "//skia", "//testing/gmock", "//testing/gtest", diff --git a/third_party/WebKit/Source/platform/blink_platform_tests.gyp b/third_party/WebKit/Source/platform/blink_platform_tests.gyp index 7254d69..72a1fb0 100644 --- a/third_party/WebKit/Source/platform/blink_platform_tests.gyp +++ b/third_party/WebKit/Source/platform/blink_platform_tests.gyp @@ -76,6 +76,7 @@ '<(DEPTH)/cc/cc_tests.gyp:cc_test_support', '<(DEPTH)/cc/blink/cc_blink.gyp:cc_blink', '<(DEPTH)/mojo/mojo_edk.gyp:mojo_common_test_support', + '<(DEPTH)/mojo/mojo_edk_tests.gyp:mojo_public_bindings_for_blink_tests', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', diff --git a/third_party/WebKit/Source/wtf/BUILD.gn b/third_party/WebKit/Source/wtf/BUILD.gn index 9115470..fd3b292 100644 --- a/third_party/WebKit/Source/wtf/BUILD.gn +++ b/third_party/WebKit/Source/wtf/BUILD.gn @@ -11,7 +11,10 @@ gypi_values = exec_script("//build/gypi_to_gn.py", "scope", [ "wtf.gypi" ]) -visibility = [ "//third_party/WebKit/*" ] +visibility = [ + "//mojo/public/cpp/bindings/*", + "//third_party/WebKit/*", +] config("wtf_config") { if (is_win) { |