diff options
author | Hidehiko Abe <hidehiko@google.com> | 2018-04-24 02:15:00 +0900 |
---|---|---|
committer | Hidehiko Abe <hidehiko@google.com> | 2018-04-24 10:13:47 +0900 |
commit | 920588a1acdc4721abb713d8162010e4b85ae53e (patch) | |
tree | 5d0b02a305d2ce5e91eb915695a338dabff2ed6b /mojo/public/cpp | |
parent | ca6c42abc66e142da1036f0061976d671862c457 (diff) | |
download | libmojo-920588a1acdc4721abb713d8162010e4b85ae53e.tar.gz |
Migrate libmojo repository into libchrome, part 2.HEADandroid-o-mr1-iot-release-smart-display-r9android-o-mr1-iot-release-smart-display-r8android-o-mr1-iot-release-smart-display-r5android-o-mr1-iot-release-smart-display-r40.1Jandroid-o-mr1-iot-release-smart-display-r4android-o-mr1-iot-release-smart-display-r39android-o-mr1-iot-release-smart-display-r30android-o-mr1-iot-release-smart-display-r3android-o-mr1-iot-release-smart-display-r22android-o-mr1-iot-release-smart-display-r14android-o-mr1-iot-release-smart-clock-r6android-o-mr1-iot-release-smart-clock-r2android-o-mr1-iot-release-smart-clock-fsiandroid-o-mr1-iot-release-smart-clock-fcsandroid-o-mr1-iot-release-cube_r2android-o-mr1-iot-release-cube-fsiandroid-o-mr1-iot-release-cube-fcsandroid-o-mr1-iot-release-1.0.8android-o-mr1-iot-release-1.0.7android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3android-o-mr1-iot-release-1.0.2android-o-mr1-iot-release-1.0.14android-o-mr1-iot-release-1.0.13android-o-mr1-iot-release-1.0.12android-o-mr1-iot-release-1.0.10android-o-mr1-iot-release-1.0.1android-o-mr1-iot-release-1.0.0oreo-mr1-iot-releaseoreo-mr1-1.2-iot-releasemastermain
This CL moves following files.
- .gitignore
- Android.bp is merged into libchrome's Android.bp.
- base/android/*
- build/* except build_config.h which is exactly same with libchrome's.
- ipc/*
- mojo/*
- soong/* into libchrome_tools/
- third_party/{catapult,jinja2,markupsafe,ply}/*
- ui/gfx/{geometry,range}/mojo/*
Then removed following files:
- Android.bp
- CleanSpec.mk
- build/build_config.h
And added README.md to notify the migration.
Bug: 73606903
Test: Built locally. Ran on DUT.
Change-Id: I94aa1b43ff0854f48f30fdf03025bd1c8a346038
Diffstat (limited to 'mojo/public/cpp')
238 files changed, 0 insertions, 36920 deletions
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn deleted file mode 100644 index bd87965..0000000 --- a/mojo/public/cpp/bindings/BUILD.gn +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings" - -component("bindings") { - sources = [ - # Normally, targets should depend on the source_sets generated by mojom - # targets. However, the generated source_sets use portions of the bindings - # library. In order to avoid linker warnings about locally-defined imports - # in Windows components build, this target depends on the generated C++ - # files directly so that the EXPORT macro defintions match. - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared-internal.h", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.cc", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.h", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom.cc", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared-internal.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.cc", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.cc", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.h", - "array_data_view.h", - "array_traits.h", - "array_traits_carray.h", - "array_traits_stl.h", - "associated_binding.h", - "associated_binding_set.h", - "associated_group.h", - "associated_group_controller.h", - "associated_interface_ptr.h", - "associated_interface_ptr_info.h", - "associated_interface_request.h", - "binding.h", - "binding_set.h", - "bindings_export.h", - "clone_traits.h", - "connection_error_callback.h", - "connector.h", - "disconnect_reason.h", - "filter_chain.h", - "interface_data_view.h", - "interface_endpoint_client.h", - "interface_endpoint_controller.h", - "interface_id.h", - "interface_ptr.h", - "interface_ptr_info.h", - "interface_ptr_set.h", - "interface_request.h", - "lib/array_internal.cc", - "lib/array_internal.h", - "lib/array_serialization.h", - "lib/associated_binding.cc", - "lib/associated_group.cc", - "lib/associated_group_controller.cc", - "lib/associated_interface_ptr.cc", - "lib/associated_interface_ptr_state.h", - "lib/binding_state.cc", - "lib/binding_state.h", - "lib/bindings_internal.h", - "lib/buffer.h", - "lib/connector.cc", - "lib/control_message_handler.cc", - "lib/control_message_handler.h", - "lib/control_message_proxy.cc", - "lib/control_message_proxy.h", - "lib/equals_traits.h", - "lib/filter_chain.cc", - "lib/fixed_buffer.cc", - "lib/fixed_buffer.h", - "lib/handle_interface_serialization.h", - "lib/hash_util.h", - "lib/interface_endpoint_client.cc", - "lib/interface_ptr_state.h", - "lib/map_data_internal.h", - "lib/map_serialization.h", - "lib/may_auto_lock.h", - "lib/message.cc", - "lib/message_buffer.cc", - "lib/message_buffer.h", - "lib/message_builder.cc", - "lib/message_builder.h", - "lib/message_header_validator.cc", - "lib/message_internal.h", - "lib/multiplex_router.cc", - "lib/multiplex_router.h", - "lib/native_enum_data.h", - "lib/native_enum_serialization.h", - "lib/native_struct.cc", - "lib/native_struct_data.cc", - "lib/native_struct_data.h", - "lib/native_struct_serialization.cc", - "lib/native_struct_serialization.h", - "lib/pipe_control_message_handler.cc", - "lib/pipe_control_message_proxy.cc", - "lib/scoped_interface_endpoint_handle.cc", - "lib/serialization.h", - "lib/serialization_context.cc", - "lib/serialization_context.h", - "lib/serialization_forward.h", - "lib/serialization_util.h", - "lib/string_serialization.h", - "lib/string_traits_string16.cc", - "lib/sync_call_restrictions.cc", - "lib/sync_event_watcher.cc", - "lib/sync_handle_registry.cc", - "lib/sync_handle_watcher.cc", - "lib/template_util.h", - "lib/union_accessor.h", - "lib/validate_params.h", - "lib/validation_context.cc", - "lib/validation_context.h", - "lib/validation_errors.cc", - "lib/validation_errors.h", - "lib/validation_util.cc", - "lib/validation_util.h", - "map.h", - "map_data_view.h", - "map_traits.h", - "map_traits_stl.h", - "message.h", - "message_header_validator.h", - "native_enum.h", - "native_struct.h", - "native_struct_data_view.h", - "pipe_control_message_handler.h", - "pipe_control_message_handler_delegate.h", - "pipe_control_message_proxy.h", - "raw_ptr_impl_ref_traits.h", - "scoped_interface_endpoint_handle.h", - "string_data_view.h", - "string_traits.h", - "string_traits_stl.h", - "string_traits_string16.h", - "string_traits_string_piece.h", - "strong_associated_binding.h", - "strong_binding.h", - "strong_binding_set.h", - "struct_ptr.h", - "sync_call_restrictions.h", - "sync_event_watcher.h", - "sync_handle_registry.h", - "sync_handle_watcher.h", - "thread_safe_interface_ptr.h", - "type_converter.h", - "union_traits.h", - "unique_ptr_impl_ref_traits.h", - ] - - public_deps = [ - ":struct_traits", - "//base", - "//ipc:param_traits", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - "//mojo/public/interfaces/bindings:bindings__generator", - "//mojo/public/interfaces/bindings:bindings_shared__generator", - ] - - defines = [ "MOJO_CPP_BINDINGS_IMPLEMENTATION" ] -} - -source_set("struct_traits") { - sources = [ - "enum_traits.h", - "struct_traits.h", - ] -} - -if (!is_ios) { - # TODO(yzshen): crbug.com/617718 Consider moving this into blink. - source_set("wtf_support") { - sources = [ - "array_traits_wtf_vector.h", - "lib/string_traits_wtf.cc", - "lib/wtf_clone_equals_util.h", - "lib/wtf_hash_util.h", - "lib/wtf_serialization.h", - "map_traits_wtf_hash_map.h", - "string_traits_wtf.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 deleted file mode 100644 index 36eba44..0000000 --- a/mojo/public/cpp/bindings/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+third_party/WebKit/Source/wtf", -] diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md deleted file mode 100644 index b37267a..0000000 --- a/mojo/public/cpp/bindings/README.md +++ /dev/null @@ -1,1231 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo C++ Bindings API -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Overview -The Mojo C++ Bindings API leverages the -[C++ System API](/mojo/public/cpp/system) to provide a more natural set of -primitives for communicating over Mojo message pipes. Combined with generated -code from the [Mojom IDL and bindings generator](/mojo/public/tools/bindings), -users can easily connect interface clients and implementations across arbitrary -intra- and inter-process bounaries. - -This document provides a detailed guide to bindings API usage with example code -snippets. For a detailed API references please consult the headers in -[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/). - -## Getting Started - -When a Mojom IDL file is processed by the bindings generator, C++ code is -emitted in a series of `.h` and `.cc` files with names based on the input -`.mojom` file. Suppose we create the following Mojom file at -`//services/db/public/interfaces/db.mojom`: - -``` -module db.mojom; - -interface Table { - AddRow(int32 key, string data); -}; - -interface Database { - CreateTable(Table& table); -}; -``` - -And a GN target to generate the bindings in -`//services/db/public/interfaces/BUILD.gn`: - -``` -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "db.mojom", - ] -} -``` - -If we then build this target: - -``` -ninja -C out/r services/db/public/interfaces -``` - -This will produce several generated source files, some of which are relevant to -C++ bindings. Two of these files are: - -``` -out/gen/services/business/public/interfaces/factory.mojom.cc -out/gen/services/business/public/interfaces/factory.mojom.h -``` - -You can include the above generated header in your sources in order to use the -definitions therein: - -``` cpp -#include "services/business/public/interfaces/factory.mojom.h" - -class TableImpl : public db::mojom::Table { - // ... -}; -``` - -This document covers the different kinds of definitions generated by Mojom IDL -for C++ consumers and how they can effectively be used to communicate across -message pipes. - -*** note -**NOTE:** Using C++ bindings from within Blink code is typically subject to -special constraints which require the use of a different generated header. -For details, see [Blink Type Mapping](#Blink-Type-Mapping). -*** - -## Interfaces - -Mojom IDL interfaces are translated to corresponding C++ (pure virtual) class -interface definitions in the generated header, consisting of a single generated -method signature for each request message on the interface. Internally there is -also generated code for serialization and deserialization of messages, but this -detail is hidden from bindings consumers. - -### Basic Usage - -Let's consider a new `//sample/logger.mojom` to define a simple logging -interface which clients can use to log simple string messages: - -``` cpp -module sample.mojom; - -interface Logger { - Log(string message); -}; -``` - -Running this through the bindings generator will produce a `logging.mojom.h` -with the following definitions (modulo unimportant details): - -``` cpp -namespace sample { -namespace mojom { - -class Logger { - virtual ~Logger() {} - - virtual void Log(const std::string& message) = 0; -}; - -using LoggerPtr = mojo::InterfacePtr<Logger>; -using LoggerRequest = mojo::InterfaceRequest<Logger>; - -} // namespace mojom -} // namespace sample -``` - -Makes sense. Let's take a closer look at those type aliases at the end. - -### InterfacePtr and InterfaceRequest - -You will notice the type aliases for `LoggerPtr` and -`LoggerRequest` are using two of the most fundamental template types in the C++ -bindings library: **`InterfacePtr<T>`** and **`InterfaceRequest<T>`**. - -In the world of Mojo bindings libraries these are effectively strongly-typed -message pipe endpoints. If an `InterfacePtr<T>` is bound to a message pipe -endpoint, it can be dereferenced to make calls on an opaque `T` interface. These -calls immediately serialize their arguments (using generated code) and write a -corresponding message to the pipe. - -An `InterfaceRequest<T>` is essentially just a typed container to hold the other -end of an `InterfacePtr<T>`'s pipe -- the receiving end -- until it can be -routed to some implementation which will **bind** it. The `InterfaceRequest<T>` -doesn't actually *do* anything other than hold onto a pipe endpoint and carry -useful compile-time type information. - -![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](https://docs.google.com/drawings/d/17d5gvErbQ6DthEBMS7I1WhCh9bz0n12pvNjydzuRfTI/pub?w=600&h=100) - -So how do we create a strongly-typed message pipe? - -### Creating Interface Pipes - -One way to do this is by manually creating a pipe and binding each end: - -``` cpp -#include "sample/logger.mojom.h" - -mojo::MessagePipe pipe; -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request; - -logger.Bind(sample::mojom::LoggerPtrInfo(std::move(pipe.handle0), 0u)); -request.Bind(std::move(pipe.handle1)); -``` - -That's pretty verbose, but the C++ Bindings library provides more convenient -ways to accomplish the same thing. [interface_request.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_request.h) -defines a `MakeRequest` function: - -``` cpp -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request = mojo::MakeRequest(&logger); -``` - -and the `InterfaceRequest<T>` constructor can also take an explicit -`InterfacePtr<T>*` output argument: - -``` cpp -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request(&logger); -``` - -Both of these last two snippets are equivalent to the first one. - -*** note -**NOTE:** In the first example above you may notice usage of the `LoggerPtrInfo` -type, which is a generated alias for `mojo::InterfacePtrInfo<Logger>`. This is -similar to an `InterfaceRequest<T>` in that it merely holds onto a pipe handle -and cannot actually read or write messages on the pipe. Both this type and -`InterfaceRequest<T>` are safe to move freely from thread to thread, whereas a -bound `InterfacePtr<T>` is bound to a single thread. - -An `InterfacePtr<T>` may be unbound by calling its `PassInterface()` method, -which returns a new `InterfacePtrInfo<T>`. Conversely, an `InterfacePtr<T>` may -bind (and thus take ownership of) an `InterfacePtrInfo<T>` so that interface -calls can be made on the pipe. - -The thread-bound nature of `InterfacePtr<T>` is necessary to support safe -dispatch of its [message responses](#Receiving-Responses) and -[connection error notifications](#Connection-Errors). -*** - -Once the `LoggerPtr` is bound we can immediately begin calling `Logger` -interface methods on it, which will immediately write messages into the pipe. -These messages will stay queued on the receiving end of the pipe until someone -binds to it and starts reading them. - -``` cpp -logger->Log("Hello!"); -``` - -This actually writes a `Log` message to the pipe. - -![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](https://docs.google.com/a/google.com/drawings/d/1jWEc6jJIP2ed77Gg4JJ3EVC7hvnwcImNqQJywFwpT8g/pub?w=648&h=123) - -But as mentioned above, `InterfaceRequest` *doesn't actually do anything*, so -that message will just sit on the pipe forever. We need a way to read messages -off the other end of the pipe and dispatch them. We have to -**bind the interface request**. - -### Binding an Interface Request - -There are many different helper classes in the bindings library for binding the -receiving end of a message pipe. The most primitive among them is the aptly -named `mojo::Binding<T>`. A `mojo::Binding<T>` bridges an implementation of `T` -with a single bound message pipe endpoint (via a `mojo::InterfaceRequest<T>`), -which it continuously watches for readability. - -Any time the bound pipe becomes readable, the `Binding` will schedule a task to -read, deserialize (using generated code), and dispatch all available messages to -the bound `T` implementation. Below is a sample implementation of the `Logger` -interface. Notice that the implementation itself owns a `mojo::Binding`. This is -a common pattern, since a bound implementation must outlive any `mojo::Binding` -which binds it. - -``` cpp -#include "base/logging.h" -#include "base/macros.h" -#include "sample/logger.mojom.h" - -class LoggerImpl : public sample::mojom::Logger { - public: - // NOTE: A common pattern for interface implementations which have one - // instance per client is to take an InterfaceRequest in the constructor. - - explicit LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) {} - ~Logger() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - mojo::Binding<sample::mojom::Logger> binding_; - - DISALLOW_COPY_AND_ASSIGN(LoggerImpl); -}; -``` - -Now we can construct a `LoggerImpl` over our pending `LoggerRequest`, and the -previously queued `Log` message will be dispatched ASAP on the `LoggerImpl`'s -thread: - -``` cpp -LoggerImpl impl(std::move(request)); -``` - -The diagram below illustrates the following sequence of events, all set in -motion by the above line of code: - -1. The `LoggerImpl` constructor is called, passing the `LoggerRequest` along - to the `Binding`. -2. The `Binding` takes ownership of the `LoggerRequest`'s pipe endpoint and - begins watching it for readability. The pipe is readable immediately, so a - task is scheduled to read the pending `Log` message from the pipe ASAP. -3. The `Log` message is read and deserialized, causing the `Binding` to invoke - the `Logger::Log` implementation on its bound `LoggerImpl`. - -![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](https://docs.google.com/drawings/d/1c73-PegT4lmjfHoxhWrHTQXRvzxgb0wdeBa35WBwZ3Q/pub?w=550&h=500) - -As a result, our implementation will eventually log the client's `"Hello!"` -message via `LOG(ERROR)`. - -*** note -**NOTE:** Messages will only be read and dispatched from a pipe as long as the -object which binds it (*i.e.* the `mojo::Binding` in the above example) remains -alive. -*** - -### Receiving Responses - -Some Mojom interface methods expect a response. Suppose we modify our `Logger` -interface so that the last logged line can be queried like so: - -``` cpp -module sample.mojom; - -interface Logger { - Log(string message); - GetTail() => (string message); -}; -``` - -The generated C++ interface will now look like: - -``` cpp -namespace sample { -namespace mojom { - -class Logger { - public: - virtual ~Logger() {} - - virtual void Log(const std::string& message) = 0; - - using GetTailCallback = base::Callback<void(const std::string& message)>; - - virtual void GetTail(const GetTailCallback& callback) = 0; -} - -} // namespace mojom -} // namespace sample -``` - -As before, both clients and implementations of this interface use the same -signature for the `GetTail` method: implementations use the `callback` argument -to *respond* to the request, while clients pass a `callback` argument to -asynchronously `receive` the response. Here's an updated implementation: - -```cpp -class LoggerImpl : public sample::mojom::Logger { - public: - // NOTE: A common pattern for interface implementations which have one - // instance per client is to take an InterfaceRequest in the constructor. - - explicit LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) {} - ~Logger() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - lines_.push_back(message); - } - - void GetTail(const GetTailCallback& callback) override { - callback.Run(lines_.back()); - } - - private: - mojo::Binding<sample::mojom::Logger> binding_; - std::vector<std::string> lines_; - - DISALLOW_COPY_AND_ASSIGN(LoggerImpl); -}; -``` - -And an updated client call: - -``` cpp -void OnGetTail(const std::string& message) { - LOG(ERROR) << "Tail was: " << message; -} - -logger->GetTail(base::Bind(&OnGetTail)); -``` - -Behind the scenes, the implementation-side callback is actually serializing the -response arguments and writing them onto the pipe for delivery back to the -client. Meanwhile the client-side callback is invoked by some internal logic -which watches the pipe for an incoming response message, reads and deserializes -it once it arrives, and then invokes the callback with the deserialized -parameters. - -### Connection Errors - -If there are no remaining messages available on a pipe and the remote end has -been closed, a connection error will be triggered on the local end. Connection -errors may also be triggered by automatic forced local pipe closure due to -*e.g.* a validation error when processing a received message. - -Regardless of the underlying cause, when a connection error is encountered on -a binding endpoint, that endpoint's **connection error handler** (if set) is -invoked. This handler is a simple `base::Closure` and may only be invoked -*once* as long as the endpoint is bound to the same pipe. Typically clients and -implementations use this handler to do some kind of cleanup or -- particuarly if -the error was unexpected -- create a new pipe and attempt to establish a new -connection with it. - -All message pipe-binding C++ objects (*e.g.*, `mojo::Binding<T>`, -`mojo::InterfacePtr<T>`, *etc.*) support setting their connection error handler -via a `set_connection_error_handler` method. - -We can set up another end-to-end `Logger` example to demonstrate error handler -invocation: - -``` cpp -sample::mojom::LoggerPtr logger; -LoggerImpl impl(mojo::MakeRequest(&logger)); -impl.set_connection_error_handler(base::Bind([] { LOG(ERROR) << "Bye."; })); -logger->Log("OK cool"); -logger.reset(); // Closes the client end. -``` - -As long as `impl` stays alive here, it will eventually receive the `Log` message -followed immediately by an invocation of the bound callback which outputs -`"Bye."`. Like all other bindings callbacks, a connection error handler will -**never** be invoked once its corresponding binding object has been destroyed. - -In fact, suppose instead that `LoggerImpl` had set up the following error -handler within its constructor: - -``` cpp -LoggerImpl::LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) { - binding_.set_connection_error_handler( - base::Bind(&LoggerImpl::OnError, base::Unretained(this))); -} - -void LoggerImpl::OnError() { - LOG(ERROR) << "Client disconnected! Purging log lines."; - lines_.clear(); -} -``` - -The use of `base::Unretained` is *safe* because the error handler will never be -invoked beyond the lifetime of `binding_`, and `this` owns `binding_`. - -### A Note About Ordering - -As mentioned in the previous section, closing one end of a pipe will eventually -trigger a connection error on the other end. However it's important to note that -this event is itself ordered with respect to any other event (*e.g.* writing a -message) on the pipe. - -This means that it's safe to write something contrived like: - -``` cpp -void GoBindALogger(sample::mojom::LoggerRequest request) { - LoggerImpl impl(std::move(request)); - base::RunLoop loop; - impl.set_connection_error_handler(loop.QuitClosure()); - loop.Run(); -} - -void LogSomething() { - sample::mojom::LoggerPtr logger; - bg_thread->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&GoBindALogger, mojo::MakeRequest(&logger))); - logger->Log("OK Computer"); -} -``` - -When `logger` goes out of scope it immediately closes its end of the message -pipe, but the impl-side won't notice this until it receives the sent `Log` -message. Thus the `impl` above will first log our message and *then* see a -connection error and break out of the run loop. - -### Sending Interfaces Over Interfaces - -Now we know how to create interface pipes and use their Ptr and Request -endpoints in some interesting ways. This still doesn't add up to interesting -IPC! The bread and butter of Mojo IPC is the ability to transfer interface -endpoints across other interfaces, so let's take a look at how to accomplish -that. - -#### Sending Interface Requests - -Consider a new example Mojom in `//sample/db.mojom`: - -``` cpp -module db.mojom; - -interface Table { - void AddRow(int32 key, string data); -}; - -interface Database { - AddTable(Table& table); -}; -``` - -As noted in the -[Mojom IDL documentation](/mojo/public/tools/bindings#Primitive-Types), -the `Table&` syntax denotes a `Table` interface request. This corresponds -precisely to the `InterfaceRequest<T>` type discussed in the sections above, and -in fact the generated code for these interfaces is approximately: - -``` cpp -namespace db { -namespace mojom { - -class Table { - public: - virtual ~Table() {} - - virtual void AddRow(int32_t key, const std::string& data) = 0; -} - -using TablePtr = mojo::InterfacePtr<Table>; -using TableRequest = mojo::InterfaceRequest<Table>; - -class Database { - public: - virtual ~Database() {} - - virtual void AddTable(TableRequest table); -}; - -using DatabasePtr = mojo::InterfacePtr<Database>; -using DatabaseRequest = mojo::InterfaceRequest<Database>; - -} // namespace mojom -} // namespace db -``` - -We can put this all together now with an implementation of `Table` and -`Database`: - -``` cpp -#include "sample/db.mojom.h" - -class TableImpl : public db::mojom:Table { - public: - explicit TableImpl(db::mojom::TableRequest request) - : binding_(this, std::move(request)) {} - ~TableImpl() override {} - - // db::mojom::Table: - void AddRow(int32_t key, const std::string& data) override { - rows_.insert({key, data}); - } - - private: - mojo::Binding<db::mojom::Table> binding_; - std::map<int32_t, std::string> rows_; -}; - -class DatabaseImpl : public db::mojom::Database { - public: - explicit DatabaseImpl(db::mojom::DatabaseRequest request) - : binding_(this, std::move(request)) {} - ~DatabaseImpl() override {} - - // db::mojom::Database: - void AddTable(db::mojom::TableRequest table) { - tables_.emplace_back(base::MakeUnique<TableImpl>(std::move(table))); - } - - private: - mojo::Binding<db::mojom::Database> binding_; - std::vector<std::unique_ptr<TableImpl>> tables_; -}; -``` - -Pretty straightforward. The `Table&` Mojom paramter to `AddTable` translates to -a C++ `db::mojom::TableRequest`, aliased from -`mojo::InterfaceRequest<db::mojom::Table>`, which we know is just a -strongly-typed message pipe handle. When `DatabaseImpl` gets an `AddTable` call, -it constructs a new `TableImpl` and binds it to the received `TableRequest`. - -Let's see how this can be used. - -``` cpp -db::mojom::DatabasePtr database; -DatabaseImpl db_impl(mojo::MakeRequest(&database)); - -db::mojom::TablePtr table1, table2; -database->AddTable(mojo::MakeRequest(&table1)); -database->AddTable(mojo::MakeRequest(&table2)); - -table1->AddRow(1, "hiiiiiiii"); -table2->AddRow(2, "heyyyyyy"); -``` - -Notice that we can again start using the new `Table` pipes immediately, even -while their `TableRequest` endpoints are still in transit. - -#### Sending InterfacePtrs - -Of course we can also send `InterfacePtr`s: - -``` cpp -interface TableListener { - OnRowAdded(int32 key, string data); -}; - -interface Table { - AddRow(int32 key, string data); - - AddListener(TableListener listener); -}; -``` - -This would generate a `Table::AddListener` signature like so: - -``` cpp - virtual void AddListener(TableListenerPtr listener) = 0; -``` - -and this could be used like so: - -``` cpp -db::mojom::TableListenerPtr listener; -TableListenerImpl impl(mojo::MakeRequest(&listener)); -table->AddListener(std::move(listener)); -``` - -## Other Interface Binding Types - -The [Interfaces](#Interfaces) section above covers basic usage of the most -common bindings object types: `InterfacePtr`, `InterfaceRequest`, and `Binding`. -While these types are probably the most commonly used in practice, there are -several other ways of binding both client- and implementation-side interface -pipes. - -### Strong Bindings - -A **strong binding** exists as a standalone object which owns its interface -implementation and automatically cleans itself up when its bound interface -endpoint detects an error. The -[**`MakeStrongBinding`**](https://cs.chromim.org/chromium/src//mojo/public/cpp/bindings/strong_binding.h) -function is used to create such a binding. -. - -``` cpp -class LoggerImpl : public sample::mojom::Logger { - public: - LoggerImpl() {} - ~LoggerImpl() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - // NOTE: This doesn't own any Binding object! -}; - -db::mojom::LoggerPtr logger; -mojo::MakeStrongBinding(base::MakeUnique<DatabaseImpl>(), - mojo::MakeRequest(&logger)); - -logger->Log("NOM NOM NOM MESSAGES"); -``` - -Now as long as `logger` remains open somewhere in the system, the bound -`DatabaseImpl` on the other end will remain alive. - -### Binding Sets - -Sometimes it's useful to share a single implementation instance with multiple -clients. [**`BindingSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/binding_set.h) -makes this easy. Consider the Mojom: - -``` cpp -module system.mojom; - -interface Logger { - Log(string message); -}; - -interface LoggerProvider { - GetLogger(Logger& logger); -}; -``` - -We can use `BindingSet` to bind multiple `Logger` requests to a single -implementation instance: - -``` cpp -class LogManager : public system::mojom::LoggerProvider, - public system::mojom::Logger { - public: - explicit LogManager(system::mojom::LoggerProviderRequest request) - : provider_binding_(this, std::move(request)) {} - ~LogManager() {} - - // system::mojom::LoggerProvider: - void GetLogger(LoggerRequest request) override { - logger_bindings_.AddBinding(this, std::move(request)); - } - - // system::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - mojo::Binding<system::mojom::LoggerProvider> provider_binding_; - mojo::BindingSet<system::mojom::Logger> logger_bindings_; -}; - -``` - - -### InterfacePtr Sets - -Similar to the `BindingSet` above, sometimes it's useful to maintain a set of -`InterfacePtr`s for *e.g.* a set of clients observing some event. -[**`InterfacePtrSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_ptr_set.h) -is here to help. Take the Mojom: - -``` cpp -module db.mojom; - -interface TableListener { - OnRowAdded(int32 key, string data); -}; - -interface Table { - AddRow(int32 key, string data); - AddListener(TableListener listener); -}; -``` - -An implementation of `Table` might look something like like this: - -``` cpp -class TableImpl : public db::mojom::Table { - public: - TableImpl() {} - ~TableImpl() override {} - - // db::mojom::Table: - void AddRow(int32_t key, const std::string& data) override { - rows_.insert({key, data}); - listeners_.ForEach([key, &data](db::mojom::TableListener* listener) { - listener->OnRowAdded(key, data); - }); - } - - void AddListener(db::mojom::TableListenerPtr listener) { - listeners_.AddPtr(std::move(listener)); - } - - private: - mojo::InterfacePtrSet<db::mojom::Table> listeners_; - std::map<int32_t, std::string> rows_; -}; -``` - -## Associated Interfaces - -See [this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces). - -TODO: Move the above doc into the repository markdown docs. - -## Synchronous Calls - -See [this document](https://www.chromium.org/developers/design-documents/mojo/synchronous-calls) - -TODO: Move the above doc into the repository markdown docs. - -## Type Mapping - -In many instances you might prefer that your generated C++ bindings use a more -natural type to represent certain Mojom types in your interface methods. For one -example consider a Mojom struct such as the `Rect` below: - -``` cpp -module gfx.mojom; - -struct Rect { - int32 x; - int32 y; - int32 width; - int32 height; -}; - -interface Canvas { - void FillRect(Rect rect); -}; -``` - -The `Canvas` Mojom interface would normally generate a C++ interface like: - -``` cpp -class Canvas { - public: - virtual void FillRect(RectPtr rect) = 0; -}; -``` - -However, the Chromium tree already defines a native -[`gfx::Rect`](https://cs.chromium.org/chromium/src/ui/gfx/geometry/rect.h) which -is equivalent in meaning but which also has useful helper methods. Instead of -manually converting between a `gfx::Rect` and the Mojom-generated `RectPtr` at -every message boundary, wouldn't it be nice if the Mojom bindings generator -could instead generate: - -``` cpp -class Canvas { - public: - virtual void FillRect(const gfx::Rect& rect) = 0; -} -``` - -The correct answer is, "Yes! That would be nice!" And fortunately, it can! - -### Global Configuration - -While this feature is quite powerful, it introduces some unavoidable complexity -into build system. This stems from the fact that type-mapping is an inherently -viral concept: if `gfx::mojom::Rect` is mapped to `gfx::Rect` anywhere, the -mapping needs to apply *everywhere*. - -For this reason we have a few global typemap configurations defined in -[chromium_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni) -and -[blink_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni). These configure the two supported [variants](#Variants) of Mojom generated -bindings in the repository. Read more on this in the sections that follow. - -For now, let's take a look at how to express the mapping from `gfx::mojom::Rect` -to `gfx::Rect`. - -### Defining `StructTraits` - -In order to teach generated bindings code how to serialize an arbitrary native -type `T` as an arbitrary Mojom type `mojom::U`, we need to define an appropriate -specialization of the -[`mojo::StructTraits`](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/struct_traits.h) -template. - -A valid specialization of `StructTraits` MUST define the following static -methods: - -* A single static accessor for every field of the Mojom struct, with the exact - same name as the struct field. These accessors must all take a const ref to - an object of the native type, and must return a value compatible with the - Mojom struct field's type. This is used to safely and consistently extract - data from the native type during message serialization without incurring extra - copying costs. - -* A single static `Read` method which initializes an instance of the the native - type given a serialized representation of the Mojom struct. The `Read` method - must return a `bool` to indicate whether the incoming data is accepted - (`true`) or rejected (`false`). - -There are other methods a `StructTraits` specialization may define to satisfy -some less common requirements. See -[Advanced StructTraits Usage](#Advanced-StructTraits-Usage) for details. - -In order to define the mapping for `gfx::Rect`, we want the following -`StructTraits` specialization, which we'll define in -`//ui/gfx/geometry/mojo/geometry_struct_traits.h`: - -``` cpp -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/mojo/geometry.mojom.h" - -namespace mojo { - -template <> -class StructTraits<gfx::mojom::RectDataView, gfx::Rect> { - public: - static int32_t x(const gfx::Rect& r) { return r.x(); } - static int32_t y(const gfx::Rect& r) { return r.y(); } - static int32_t width(const gfx::Rect& r) { return r.width(); } - static int32_t height(const gfx::Rect& r) { return r.height(); } - - static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out_rect); -}; - -} // namespace mojo -``` - -And in `//ui/gfx/geometry/mojo/geometry_struct_traits.cc`: - -``` cpp -#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" - -namespace mojo { - -// static -template <> -bool StructTraits<gfx::mojom::RectDataView, gfx::Rect>::Read( - gfx::mojom::RectDataView data, - gfx::Rect* out_rect) { - if (data.width() < 0 || data.height() < 0) - return false; - - out_rect->SetRect(data.x(), data.y(), data.width(), data.height()); - return true; -}; - -} // namespace mojo -``` - -Note that the `Read()` method returns `false` if either the incoming `width` or -`height` fields are negative. This acts as a validation step during -deserialization: if a client sends a `gfx::Rect` with a negative width or -height, its message will be rejected and the pipe will be closed. In this way, -type mapping can serve to enable custom validation logic in addition to making -callsites and interface implemention more convenient. - -### Enabling a New Type Mapping - -We've defined the `StructTraits` necessary, but we still need to teach the -bindings generator (and hence the build system) about the mapping. To do this we -must create a **typemap** file, which uses familiar GN syntax to describe the -new type mapping. - -Let's place this `geometry.typemap` file alongside our Mojom file: - -``` -mojom = "//ui/gfx/geometry/mojo/geometry.mojom" -public_headers = [ "//ui/gfx/geometry/rect.h" ] -traits_headers = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.h" ] -sources = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.cc" ] -public_deps = [ "//ui/gfx/geometry" ] -type_mappings = [ - "gfx.mojom.Rect=gfx::Rect", -] -``` - -Let's look at each of the variables above: - -* `mojom`: Specifies the `mojom` file to which the typemap applies. Many - typemaps may apply to the same `mojom` file, but any given typemap may only - apply to a single `mojom` file. -* `public_headers`: Additional headers required by any code which would depend - on the Mojom definition of `gfx.mojom.Rect` now that the typemap is applied. - Any headers required for the native target type definition should be listed - here. -* `traits_headers`: Headers which contain the relevant `StructTraits` - specialization(s) for any type mappings described by this file. -* `sources`: Any private implementation sources needed for the `StructTraits` - definition. -* `public_deps`: Target dependencies exposed by the `public_headers` and - `traits_headers`. -* `deps`: Target dependencies exposed by `sources` but not already covered by - `public_deps`. -* `type_mappings`: A list of type mappings to be applied for this typemap. The - strings in this list are of the format `"MojomType=CppType"`, where - `MojomType` must be a fully qualified Mojom typename and `CppType` must be a - fully qualified C++ typename. Additional attributes may be specified in square - brackets following the `CppType`: - * `move_only`: The `CppType` is move-only and should be passed by value - in any generated method signatures. Note that `move_only` is transitive, - so containers of `MojomType` will translate to containers of `CppType` - also passed by value. - * `copyable_pass_by_value`: Forces values of type `CppType` to be passed by - value without moving them. Unlike `move_only`, this is not transitive. - * `nullable_is_same_type`: By default a non-nullable `MojomType` will be - mapped to `CppType` while a nullable `MojomType?` will be mapped to - `base::Optional<CppType>`. If this attribute is set, the `base::Optional` - wrapper is omitted for nullable `MojomType?` values, but the - `StructTraits` definition for this type mapping must define additional - `IsNull` and `SetToNull` methods. See - [Specializing Nullability](#Specializing-Nullability) below. - - -Now that we have the typemap file we need to add it to a local list of typemaps -that can be added to the global configuration. We create a new -`//ui/gfx/typemaps.gni` file with the following contents: - -``` -typemaps = [ - "//ui/gfx/geometry/mojo/geometry.typemap", -] -``` - -And finally we can reference this file in the global default (Chromium) bindings -configuration by adding it to `_typemap_imports` in -[chromium_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni): - -``` -_typemap_imports = [ - ..., - "//ui/gfx/typemaps.gni", - ..., -] -``` - -### StructTraits Reference - -Each of a `StructTraits` specialization's static getter methods -- one per -struct field -- must return a type which can be used as a data source for the -field during serialization. This is a quick reference mapping Mojom field type -to valid getter return types: - -| Mojom Field Type | C++ Getter Return Type | -|------------------------------|------------------------| -| `bool` | `bool` -| `int8` | `int8_t` -| `uint8` | `uint8_t` -| `int16` | `int16_t` -| `uint16` | `uint16_t` -| `int32` | `int32_t` -| `uint32` | `uint32_t` -| `int64` | `int64_t` -| `uint64` | `uint64_t` -| `float` | `float` -| `double` | `double` -| `handle` | `mojo::ScopedHandle` -| `handle<message_pipe>` | `mojo::ScopedMessagePipeHandle` -| `handle<data_pipe_consumer>` | `mojo::ScopedDataPipeConsumerHandle` -| `handle<data_pipe_producer>` | `mojo::ScopedDataPipeProducerHandle` -| `handle<shared_buffer>` | `mojo::ScopedSharedBufferHandle` -| `FooInterface` | `FooInterfacePtr` -| `FooInterface&` | `FooInterfaceRequest` -| `associated FooInterface` | `FooAssociatedInterfacePtr` -| `associated FooInterface&` | `FooAssociatedInterfaceRequest` -| `string` | Value or reference to any type `T` that has a `mojo::StringTraits` specialization defined. By default this includes `std::string`, `base::StringPiece`, and `WTF::String` (Blink). -| `array<T>` | Value or reference to any type `T` that has a `mojo::ArrayTraits` specialization defined. By default this includes `std::vector<T>`, `mojo::CArray<T>`, and `WTF::Vector<T>` (Blink). -| `map<K, V>` | Value or reference to any type `T` that has a `mojo::MapTraits` specialization defined. By default this includes `std::map<T>`, `mojo::unordered_map<T>`, and `WTF::HashMap<T>` (Blink). -| `FooEnum` | Value of any type that has an appropriate `EnumTraits` specialization defined. By default this inlcudes only the generated `FooEnum` type. -| `FooStruct` | Value or reference to any type that has an appropriate `StructTraits` specialization defined. By default this includes only the generated `FooStructPtr` type. -| `FooUnion` | Value of reference to any type that has an appropriate `UnionTraits` specialization defined. By default this includes only the generated `FooUnionPtr` type. - -### Using Generated DataView Types - -Static `Read` methods on `StructTraits` specializations get a generated -`FooDataView` argument (such as the `RectDataView` in the example above) which -exposes a direct view of the serialized Mojom structure within an incoming -message's contents. In order to make this as easy to work with as possible, the -generated `FooDataView` types have a generated method corresponding to every -struct field: - -* For POD field types (*e.g.* bools, floats, integers) these are simple accessor - methods with names identical to the field name. Hence in the `Rect` example we - can access things like `data.x()` and `data.width()`. The return types - correspond exactly to the mappings listed in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -* For handle and interface types (*e.g* `handle` or `FooInterface&`) these - are named `TakeFieldName` (for a field named `field_name`) and they return an - appropriate move-only handle type by value. The return types correspond - exactly to the mappings listed in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -* For all other field types (*e.g.*, enums, strings, arrays, maps, structs) - these are named `ReadFieldName` (for a field named `field_name`) and they - return a `bool` (to indicate success or failure in reading). On success they - fill their output argument with the deserialized field value. The output - argument may be a pointer to any type with an appropriate `StructTraits` - specialization defined, as mentioned in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -An example would be useful here. Suppose we introduced a new Mojom struct: - -``` cpp -struct RectPair { - Rect left; - Rect right; -}; -``` - -and a corresponding C++ type: - -``` cpp -class RectPair { - public: - RectPair() {} - - const gfx::Rect& left() const { return left_; } - const gfx::Rect& right() const { return right_; } - - void Set(const gfx::Rect& left, const gfx::Rect& right) { - left_ = left; - right_ = right; - } - - // ... some other stuff - - private: - gfx::Rect left_; - gfx::Rect right_; -}; -``` - -Our traits to map `gfx::mojom::RectPair` to `gfx::RectPair` might look like -this: - -``` cpp -namespace mojo { - -template <> -class StructTraits - public: - static const gfx::Rect& left(const gfx::RectPair& pair) { - return pair.left(); - } - - static const gfx::Rect& right(const gfx::RectPair& pair) { - return pair.right(); - } - - static bool Read(gfx::mojom::RectPairDataView data, gfx::RectPair* out_pair) { - gfx::Rect left, right; - if (!data.ReadLeft(&left) || !data.ReadRight(&right)) - return false; - out_pair->Set(left, right); - return true; - } -} // namespace mojo -``` - -Generated `ReadFoo` methods always convert `multi_word_field_name` fields to -`ReadMultiWordFieldName` methods. - -### Variants - -By now you may have noticed that additional C++ sources are generated when a -Mojom is processed. These exist due to type mapping, and the source files we -refer to throughout this docuemnt (namely `foo.mojom.cc` and `foo.mojom.h`) are -really only one **variant** (the *default* or *chromium* variant) of the C++ -bindings for a given Mojom file. - -The only other variant currently defined in the tree is the *blink* variant, -which produces a few additional files: - -``` -out/gen/sample/db.mojom-blink.cc -out/gen/sample/db.mojom-blink.h -``` - -These files mirror the definitions in the default variant but with different -C++ types in place of certain builtin field and parameter types. For example, -Mojom strings are represented by `WTF::String` instead of `std::string`. To -avoid symbol collisions, the variant's symbols are nested in an extra inner -namespace, so Blink consumer of the interface might write something like: - -``` -#include "sample/db.mojom-blink.h" - -class TableImpl : public db::mojom::blink::Table { - public: - void AddRow(int32_t key, const WTF::String& data) override { - // ... - } -}; -``` - -In addition to using different C++ types for builtin strings, arrays, and maps, -the global typemap configuration for default and "blink" variants are completely -separate. To add a typemap for the Blink configuration, you can modify -[blink_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni). - -All variants share some definitions which are unaffected by differences in the -type mapping configuration (enums, for example). These definitions are generated -in *shared* sources: - -``` -out/gen/sample/db.mojom-shared.cc -out/gen/sample/db.mojom-shared.h -out/gen/sample/db.mojom-shared-internal.h -``` - -Including either variant's header (`db.mojom.h` or `db.mojom-blink.h`) -implicitly includes the shared header, but you have on some occasions wish to -include *only* the shared header in some instances. - -Finally, note that for `mojom` GN targets, there is implicitly a corresponding -`mojom_{variant}` target defined for any supported bindings configuration. So -for example if you've defined in `//sample/BUILD.gn`: - -``` -import("mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "db.mojom", - ] -} -``` - -Code in Blink which wishes to use the generated Blink-variant definitions must -depend on `"//sample:interfaces_blink"`. - -## Versioning Considerations - -For general documentation of versioning in the Mojom IDL see -[Versioning](/mojo/public/tools/bindings#Versioning). - -This section briefly discusses some C++-specific considerations relevant to -versioned Mojom types. - -### Querying Interface Versions - -`InterfacePtr` defines the following methods to query or assert remote interface -version: - -```cpp -void QueryVersion(const base::Callback<void(uint32_t)>& callback); -``` - -This queries the remote endpoint for the version number of its binding. When a -response is received `callback` is invoked with the remote version number. Note -that this value is cached by the `InterfacePtr` instance to avoid redundant -queries. - -```cpp -void RequireVersion(uint32_t version); -``` - -Informs the remote endpoint that a minimum version of `version` is required by -the client. If the remote endpoint cannot support that version, it will close -its end of the pipe immediately, preventing any other requests from being -received. - -### Versioned Enums - -For convenience, every extensible enum has a generated helper function to -determine whether a received enum value is known by the implementation's current -version of the enum definition. For example: - -```cpp -[Extensible] -enum Department { - SALES, - DEV, - RESEARCH, -}; -``` - -generates the function in the same namespace as the generated C++ enum type: - -```cpp -inline bool IsKnownEnumValue(Department value); -``` - -### Additional Documentation - -[Calling Mojo From Blink](https://www.chromium.org/developers/design-documents/mojo/calling-mojo-from-blink) -: A brief overview of what it looks like to use Mojom C++ bindings from - within Blink code. diff --git a/mojo/public/cpp/bindings/array_data_view.h b/mojo/public/cpp/bindings/array_data_view.h deleted file mode 100644 index d02a884..0000000 --- a/mojo/public/cpp/bindings/array_data_view.h +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ - -#include <type_traits> - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" - -namespace mojo { -namespace internal { - -template <typename T, typename EnableType = void> -class ArrayDataViewImpl; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, MojomTypeCategory::POD>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T operator[](size_t index) const { return data_->at(index); } - - const T* data() const { return data_->storage(); } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, MojomTypeCategory::BOOLEAN>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - bool operator[](size_t index) const { return data_->at(index); } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, MojomTypeCategory::ENUM>::value>::type> { - public: - static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size"); - - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T operator[](size_t index) const { return static_cast<T>(data_->at(index)); } - - const T* data() const { return reinterpret_cast<const T*>(data_->storage()); } - - template <typename U> - bool Read(size_t index, U* output) { - return Deserialize<T>(data_->at(index), output); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, - MojomTypeCategory::ASSOCIATED_INTERFACE | - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST | - MojomTypeCategory::INTERFACE | - MojomTypeCategory::INTERFACE_REQUEST>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - template <typename U> - U Take(size_t index) { - U result; - bool ret = Deserialize<T>(&data_->at(index), &result, context_); - DCHECK(ret); - return result; - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, MojomTypeCategory::HANDLE>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T Take(size_t index) { - T result; - bool ret = Deserialize<T>(&data_->at(index), &result, context_); - DCHECK(ret); - return result; - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl<T, - typename std::enable_if<BelongsTo< - T, - MojomTypeCategory::ARRAY | MojomTypeCategory::MAP | - MojomTypeCategory::STRING | - MojomTypeCategory::STRUCT>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - void GetDataView(size_t index, T* output) { - *output = T(data_->at(index).Get(), context_); - } - - template <typename U> - bool Read(size_t index, U* output) { - return Deserialize<T>(data_->at(index).Get(), output, context_); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template <typename T> -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo<T, MojomTypeCategory::UNION>::value>::type> { - public: - using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - void GetDataView(size_t index, T* output) { - *output = T(&data_->at(index), context_); - } - - template <typename U> - bool Read(size_t index, U* output) { - return Deserialize<T>(&data_->at(index), output, context_); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -} // namespace internal - -template <typename K, typename V> -class MapDataView; - -template <typename T> -class ArrayDataView : public internal::ArrayDataViewImpl<T> { - public: - using Element = T; - using Data_ = typename internal::ArrayDataViewImpl<T>::Data_; - - ArrayDataView() : internal::ArrayDataViewImpl<T>(nullptr, nullptr) {} - - ArrayDataView(Data_* data, internal::SerializationContext* context) - : internal::ArrayDataViewImpl<T>(data, context) {} - - bool is_null() const { return !this->data_; } - - size_t size() const { return this->data_->size(); } - - // Methods to access elements are different for different element types. They - // are inherited from internal::ArrayDataViewImpl: - - // POD types except boolean and enums: - // T operator[](size_t index) const; - // const T* data() const; - - // Boolean: - // bool operator[](size_t index) const; - - // Enums: - // T operator[](size_t index) const; - // const T* data() const; - // template <typename U> - // bool Read(size_t index, U* output); - - // Handles: - // T Take(size_t index); - - // Interfaces: - // template <typename U> - // U Take(size_t index); - - // Object types: - // void GetDataView(size_t index, T* output); - // template <typename U> - // bool Read(size_t index, U* output); - - private: - template <typename K, typename V> - friend class MapDataView; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/array_traits.h b/mojo/public/cpp/bindings/array_traits.h deleted file mode 100644 index 594b2e0..0000000 --- a/mojo/public/cpp/bindings/array_traits.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom array. -// -// Usually you would like to do a partial specialization for a container (e.g. -// vector) template. Imagine you want to specialize it for Container<>, you need -// to implement: -// -// template <typename T> -// struct ArrayTraits<Container<T>> { -// using Element = T; -// // These two statements are optional. Use them if you'd like to serialize -// // a container that supports iterators but does not support O(1) random -// // access and so GetAt(...) would be expensive. -// // using Iterator = T::iterator; -// // using ConstIterator = T::const_iterator; -// -// // These two methods are optional. Please see comments in struct_traits.h -// static bool IsNull(const Container<T>& input); -// static void SetToNull(Container<T>* output); -// -// static size_t GetSize(const Container<T>& input); -// -// // These two methods are optional. They are used to access the -// // underlying storage of the array to speed up copy of POD types. -// static T* GetData(Container<T>& input); -// static const T* GetData(const Container<T>& input); -// -// // The following six methods are optional if the GetAt(...) methods are -// // implemented. These methods specify how to read the elements of -// // Container in some sequential order specified by the iterator. -// // -// // Acquires an iterator positioned at the first element in the container. -// static ConstIterator GetBegin(const Container<T>& input); -// static Iterator GetBegin(Container<T>& input); -// -// // Advances |iterator| to the next position within the container. -// static void AdvanceIterator(ConstIterator& iterator); -// static void AdvanceIterator(Iterator& iterator); -// -// // Returns a reference to the value at the current position of -// // |iterator|. Optionally, the ConstIterator version of GetValue can -// // return by value instead of by reference if it makes sense for the -// // type. -// static const T& GetValue(ConstIterator& iterator); -// static T& GetValue(Iterator& iterator); -// -// // These two methods are optional if the iterator methods are -// // implemented. -// static T& GetAt(Container<T>& input, size_t index); -// static const T& GetAt(const Container<T>& input, size_t index); -// -// // Returning false results in deserialization failure and causes the -// // message pipe receiving it to be disconnected. -// static bool Resize(Container<T>& input, size_t size); -// }; -// -template <typename T> -struct ArrayTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/array_traits_carray.h b/mojo/public/cpp/bindings/array_traits_carray.h deleted file mode 100644 index 3ff694b..0000000 --- a/mojo/public/cpp/bindings/array_traits_carray.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ - -#include "mojo/public/cpp/bindings/array_traits.h" - -namespace mojo { - -template <typename T> -struct CArray { - CArray() : size(0), max_size(0), data(nullptr) {} - CArray(size_t size, size_t max_size, T* data) - : size(size), max_size(max_size), data(data) {} - size_t size; - const size_t max_size; - T* data; -}; - -template <typename T> -struct ConstCArray { - ConstCArray() : size(0), data(nullptr) {} - ConstCArray(size_t size, const T* data) : size(size), data(data) {} - size_t size; - const T* data; -}; - -template <typename T> -struct ArrayTraits<CArray<T>> { - using Element = T; - - static bool IsNull(const CArray<T>& input) { return !input.data; } - - static void SetToNull(CArray<T>* output) { output->data = nullptr; } - - static size_t GetSize(const CArray<T>& input) { return input.size; } - - static T* GetData(CArray<T>& input) { return input.data; } - - static const T* GetData(const CArray<T>& input) { return input.data; } - - static T& GetAt(CArray<T>& input, size_t index) { return input.data[index]; } - - static const T& GetAt(const CArray<T>& input, size_t index) { - return input.data[index]; - } - - static bool Resize(CArray<T>& input, size_t size) { - if (size > input.max_size) - return false; - - input.size = size; - return true; - } -}; - -template <typename T> -struct ArrayTraits<ConstCArray<T>> { - using Element = T; - - static bool IsNull(const ConstCArray<T>& input) { return !input.data; } - - static size_t GetSize(const ConstCArray<T>& input) { return input.size; } - - static const T* GetData(const ConstCArray<T>& input) { return input.data; } - - static const T& GetAt(const ConstCArray<T>& input, size_t index) { - return input.data[index]; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ diff --git a/mojo/public/cpp/bindings/array_traits_stl.h b/mojo/public/cpp/bindings/array_traits_stl.h deleted file mode 100644 index dec47bf..0000000 --- a/mojo/public/cpp/bindings/array_traits_stl.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ - -#include <map> -#include <set> -#include <vector> - -#include "mojo/public/cpp/bindings/array_traits.h" - -namespace mojo { - -template <typename T> -struct ArrayTraits<std::vector<T>> { - using Element = T; - - static bool IsNull(const std::vector<T>& input) { - // std::vector<> is always converted to non-null mojom array. - return false; - } - - static void SetToNull(std::vector<T>* output) { - // std::vector<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const std::vector<T>& input) { return input.size(); } - - static T* GetData(std::vector<T>& input) { return input.data(); } - - static const T* GetData(const std::vector<T>& input) { return input.data(); } - - static typename std::vector<T>::reference GetAt(std::vector<T>& input, - size_t index) { - return input[index]; - } - - static typename std::vector<T>::const_reference GetAt( - const std::vector<T>& input, - size_t index) { - return input[index]; - } - - static inline bool Resize(std::vector<T>& input, size_t size) { - // Instead of calling std::vector<T>::resize() directly, this is a hack to - // make compilers happy. Some compilers (e.g., Mac, Android, Linux MSan) - // currently don't allow resizing types like - // std::vector<std::vector<MoveOnlyType>>. - // Because the deserialization code doesn't care about the original contents - // of |input|, we discard them directly. - // - // The "inline" keyword of this method matters. Without it, we have observed - // significant perf regression with some tests on Mac. crbug.com/631415 - if (input.size() != size) { - std::vector<T> temp(size); - input.swap(temp); - } - - return true; - } -}; - -// This ArrayTraits specialization is used only for serialization. -template <typename T> -struct ArrayTraits<std::set<T>> { - using Element = T; - using ConstIterator = typename std::set<T>::const_iterator; - - static bool IsNull(const std::set<T>& input) { - // std::set<> is always converted to non-null mojom array. - return false; - } - - static size_t GetSize(const std::set<T>& input) { return input.size(); } - - static ConstIterator GetBegin(const std::set<T>& input) { - return input.begin(); - } - static void AdvanceIterator(ConstIterator& iterator) { - ++iterator; - } - static const T& GetValue(ConstIterator& iterator) { - return *iterator; - } -}; - -template <typename K, typename V> -struct MapValuesArrayView { - explicit MapValuesArrayView(const std::map<K, V>& map) : map(map) {} - const std::map<K, V>& map; -}; - -// Convenience function to create a MapValuesArrayView<> that infers the -// template arguments from its argument type. -template <typename K, typename V> -MapValuesArrayView<K, V> MapValuesToArray(const std::map<K, V>& map) { - return MapValuesArrayView<K, V>(map); -} - -// This ArrayTraits specialization is used only for serialization and converts -// a map<K, V> into an array<V>, discarding the keys. -template <typename K, typename V> -struct ArrayTraits<MapValuesArrayView<K, V>> { - using Element = V; - using ConstIterator = typename std::map<K, V>::const_iterator; - - static bool IsNull(const MapValuesArrayView<K, V>& input) { - // std::map<> is always converted to non-null mojom array. - return false; - } - - static size_t GetSize(const MapValuesArrayView<K, V>& input) { - return input.map.size(); - } - static ConstIterator GetBegin(const MapValuesArrayView<K, V>& input) { - return input.map.begin(); - } - static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } - static const V& GetValue(ConstIterator& iterator) { return iterator->second; } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ diff --git a/mojo/public/cpp/bindings/array_traits_wtf_vector.h b/mojo/public/cpp/bindings/array_traits_wtf_vector.h deleted file mode 100644 index 6e20735..0000000 --- a/mojo/public/cpp/bindings/array_traits_wtf_vector.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ - -#include "mojo/public/cpp/bindings/array_traits.h" -#include "third_party/WebKit/Source/wtf/Vector.h" - -namespace mojo { - -template <typename U> -struct ArrayTraits<WTF::Vector<U>> { - using Element = U; - - static bool IsNull(const WTF::Vector<U>& input) { - // WTF::Vector<> is always converted to non-null mojom array. - return false; - } - - static void SetToNull(WTF::Vector<U>* output) { - // WTF::Vector<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const WTF::Vector<U>& input) { return input.size(); } - - static U* GetData(WTF::Vector<U>& input) { return input.data(); } - - static const U* GetData(const WTF::Vector<U>& input) { return input.data(); } - - static U& GetAt(WTF::Vector<U>& input, size_t index) { return input[index]; } - - static const U& GetAt(const WTF::Vector<U>& input, size_t index) { - return input[index]; - } - - static bool Resize(WTF::Vector<U>& input, size_t size) { - input.resize(size); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ diff --git a/mojo/public/cpp/bindings/associated_binding.h b/mojo/public/cpp/bindings/associated_binding.h deleted file mode 100644 index 5941166..0000000 --- a/mojo/public/cpp/bindings/associated_binding.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ - -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class MessageReceiver; - -// Base class used to factor out code in AssociatedBinding<T> expansions, in -// particular for Bind(). -class MOJO_CPP_BINDINGS_EXPORT AssociatedBindingBase { - public: - AssociatedBindingBase(); - ~AssociatedBindingBase(); - - // Adds a message filter to be notified of each incoming message before - // dispatch. If a filter returns |false| from Accept(), the message is not - // dispatched and the pipe is closed. Filters cannot be removed. - void AddFilter(std::unique_ptr<MessageReceiver> filter); - - // Closes the associated interface. Puts this object into a state where it can - // be rebound. - void Close(); - - // Similar to the method above, but also specifies a disconnect reason. - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - // Sets an error handler that will be called if a connection error occurs. - // - // This method may only be called after this AssociatedBinding has been bound - // to a message pipe. The error handler will be reset when this - // AssociatedBinding is unbound or closed. - void set_connection_error_handler(const base::Closure& error_handler); - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler); - - // Indicates whether the associated binding has been completed. - bool is_bound() const { return !!endpoint_client_; } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting(); - - protected: - void BindImpl(ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr<MessageReceiver> payload_validator, - bool expect_sync_requests, - scoped_refptr<base::SingleThreadTaskRunner> runner, - uint32_t interface_version); - - std::unique_ptr<InterfaceEndpointClient> endpoint_client_; -}; - -// Represents the implementation side of an associated interface. It is similar -// to Binding, except that it doesn't own a message pipe handle. -// -// When you bind this class to a request, optionally you can specify a -// base::SingleThreadTaskRunner. This task runner must belong to the same -// thread. It will be used to dispatch incoming method calls and connection -// error notification. It is useful when you attach multiple task runners to a -// single thread for the purposes of task scheduling. Please note that incoming -// synchrounous method calls may not be run from this task runner, when they -// reenter outgoing synchrounous calls on the same thread. -template <typename Interface, - typename ImplRefTraits = RawPtrImplRefTraits<Interface>> -class AssociatedBinding : public AssociatedBindingBase { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - // Constructs an incomplete associated binding that will use the - // implementation |impl|. It may be completed with a subsequent call to the - // |Bind| method. Does not take ownership of |impl|, which must outlive this - // object. - explicit AssociatedBinding(ImplPointerType impl) { stub_.set_sink(impl); } - - // Constructs a completed associated binding of |impl|. The output |ptr_info| - // should be sent by another interface. |impl| must outlive this object. - AssociatedBinding(ImplPointerType impl, - AssociatedInterfacePtrInfo<Interface>* ptr_info, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) - : AssociatedBinding(std::move(impl)) { - Bind(ptr_info, std::move(runner)); - } - - // Constructs a completed associated binding of |impl|. |impl| must outlive - // the binding. - AssociatedBinding(ImplPointerType impl, - AssociatedInterfaceRequest<Interface> request, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) - : AssociatedBinding(std::move(impl)) { - Bind(std::move(request), std::move(runner)); - } - - ~AssociatedBinding() {} - - // Creates an associated inteface and sets up this object as the - // implementation side. The output |ptr_info| should be sent by another - // interface. - void Bind(AssociatedInterfacePtrInfo<Interface>* ptr_info, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - auto request = MakeRequest(ptr_info); - ptr_info->set_version(Interface::Version_); - Bind(std::move(request), std::move(runner)); - } - - // Sets up this object as the implementation side of an associated interface. - void Bind(AssociatedInterfaceRequest<Interface> request, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - BindImpl(request.PassHandle(), &stub_, - base::WrapUnique(new typename Interface::RequestValidator_()), - Interface::HasSyncMethods_, std::move(runner), - Interface::Version_); - } - - // Unbinds and returns the associated interface request so it can be - // used in another context, such as on another thread or with a different - // implementation. Puts this object into a state where it can be rebound. - AssociatedInterfaceRequest<Interface> Unbind() { - DCHECK(endpoint_client_); - - AssociatedInterfaceRequest<Interface> request; - request.Bind(endpoint_client_->PassHandle()); - - endpoint_client_.reset(); - - return request; - } - - // Returns the interface implementation that was previously specified. - Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); } - - private: - typename Interface::template Stub_<ImplRefTraits> stub_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedBinding); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ diff --git a/mojo/public/cpp/bindings/associated_binding_set.h b/mojo/public/cpp/bindings/associated_binding_set.h deleted file mode 100644 index 59600c6..0000000 --- a/mojo/public/cpp/bindings/associated_binding_set.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ - -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/binding_set.h" - -namespace mojo { - -template <typename Interface, typename ImplRefTraits> -struct BindingSetTraits<AssociatedBinding<Interface, ImplRefTraits>> { - using ProxyType = AssociatedInterfacePtr<Interface>; - using RequestType = AssociatedInterfaceRequest<Interface>; - using BindingType = AssociatedBinding<Interface, ImplRefTraits>; - using ImplPointerType = typename BindingType::ImplPointerType; -}; - -template <typename Interface, typename ContextType = void> -using AssociatedBindingSet = - BindingSetBase<Interface, AssociatedBinding<Interface>, ContextType>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ diff --git a/mojo/public/cpp/bindings/associated_group.h b/mojo/public/cpp/bindings/associated_group.h deleted file mode 100644 index 14e78ec..0000000 --- a/mojo/public/cpp/bindings/associated_group.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class AssociatedGroupController; - -// AssociatedGroup refers to all the interface endpoints running at one end of a -// message pipe. -// It is thread safe and cheap to make copies. -class MOJO_CPP_BINDINGS_EXPORT AssociatedGroup { - public: - AssociatedGroup(); - - explicit AssociatedGroup(scoped_refptr<AssociatedGroupController> controller); - - explicit AssociatedGroup(const ScopedInterfaceEndpointHandle& handle); - - AssociatedGroup(const AssociatedGroup& other); - - ~AssociatedGroup(); - - AssociatedGroup& operator=(const AssociatedGroup& other); - - // The return value of this getter if this object is initialized with a - // ScopedInterfaceEndpointHandle: - // - If the handle is invalid, the return value will always be null. - // - If the handle is valid and non-pending, the return value will be - // non-null and remain unchanged even if the handle is later reset. - // - If the handle is pending asssociation, the return value will initially - // be null, change to non-null when/if the handle is associated, and - // remain unchanged ever since. - AssociatedGroupController* GetController(); - - private: - base::Callback<AssociatedGroupController*()> controller_getter_; - scoped_refptr<AssociatedGroupController> controller_; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ diff --git a/mojo/public/cpp/bindings/associated_group_controller.h b/mojo/public/cpp/bindings/associated_group_controller.h deleted file mode 100644 index d33c277..0000000 --- a/mojo/public/cpp/bindings/associated_group_controller.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class InterfaceEndpointClient; -class InterfaceEndpointController; - -// An internal interface used to manage endpoints within an associated group, -// which corresponds to one end of a message pipe. -class MOJO_CPP_BINDINGS_EXPORT AssociatedGroupController - : public base::RefCountedThreadSafe<AssociatedGroupController> { - public: - // Associates an interface with this AssociatedGroupController's message pipe. - // It takes ownership of |handle_to_send| and returns an interface ID that - // could be sent by any endpoints within the same associated group. - // If |handle_to_send| is not in pending association state, it returns - // kInvalidInterfaceId. Otherwise, the peer handle of |handle_to_send| joins - // the associated group and is no longer pending. - virtual InterfaceId AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) = 0; - - // Creates an interface endpoint handle from a given interface ID. The handle - // joins this associated group. - // Typically, this method is used to (1) create an endpoint handle for the - // master interface; or (2) create an endpoint handle on receiving an - // interface ID from the message pipe. - // - // On failure, the method returns an invalid handle. Usually that is because - // the ID has already been used to create a handle. - virtual ScopedInterfaceEndpointHandle CreateLocalEndpointHandle( - InterfaceId id) = 0; - - // Closes an interface endpoint handle. - virtual void CloseEndpointHandle( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) = 0; - - // Attaches a client to the specified endpoint to send and receive messages. - // The returned object is still owned by the controller. It must only be used - // on the same thread as this call, and only before the client is detached - // using DetachEndpointClient(). - virtual InterfaceEndpointController* AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* endpoint_client, - scoped_refptr<base::SingleThreadTaskRunner> runner) = 0; - - // Detaches the client attached to the specified endpoint. It must be called - // on the same thread as the corresponding AttachEndpointClient() call. - virtual void DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) = 0; - - // Raises an error on the underlying message pipe. It disconnects the pipe - // and notifies all interfaces running on this pipe. - virtual void RaiseError() = 0; - - protected: - friend class base::RefCountedThreadSafe<AssociatedGroupController>; - - // Creates a new ScopedInterfaceEndpointHandle within this associated group. - ScopedInterfaceEndpointHandle CreateScopedInterfaceEndpointHandle( - InterfaceId id); - - // Notifies that the interface represented by |handle_to_send| and its peer - // has been associated with this AssociatedGroupController's message pipe, and - // |handle_to_send|'s peer has joined this associated group. (Note: it is the - // peer who has joined the associated group; |handle_to_send| will be sent to - // the remote side.) - // Returns false if |handle_to_send|'s peer has closed. - bool NotifyAssociation(ScopedInterfaceEndpointHandle* handle_to_send, - InterfaceId id); - - virtual ~AssociatedGroupController(); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h deleted file mode 100644 index 8806a3e..0000000 --- a/mojo/public/cpp/bindings/associated_interface_ptr.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ - -#include <stdint.h> - -#include <string> -#include <utility> - -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// Represents the client side of an associated interface. It is similar to -// InterfacePtr, except that it doesn't own a message pipe handle. -template <typename Interface> -class AssociatedInterfacePtr { - public: - using InterfaceType = Interface; - using PtrInfoType = AssociatedInterfacePtrInfo<Interface>; - - // Constructs an unbound AssociatedInterfacePtr. - AssociatedInterfacePtr() {} - AssociatedInterfacePtr(decltype(nullptr)) {} - - AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { - internal_state_.Swap(&other.internal_state_); - } - - AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { - reset(); - internal_state_.Swap(&other.internal_state_); - return *this; - } - - // Assigning nullptr to this class causes it to closes the associated - // interface (if any) and returns the pointer to the unbound state. - AssociatedInterfacePtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - ~AssociatedInterfacePtr() {} - - // Sets up this object as the client side of an associated interface. - // Calling with an invalid |info| has the same effect as reset(). In this - // case, the AssociatedInterfacePtr is not considered as bound. - // - // |runner| must belong to the same thread. It will be used to dispatch all - // callbacks and connection error notification. It is useful when you attach - // multiple task runners to a single thread for the purposes of task - // scheduling. - // - // NOTE: The corresponding AssociatedInterfaceRequest must be sent over - // another interface before using this object to make calls. Please see the - // comments of MakeRequest(AssociatedInterfacePtr<Interface>*) for more - // details. - void Bind(AssociatedInterfacePtrInfo<Interface> info, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - reset(); - - if (info.is_valid()) - internal_state_.Bind(std::move(info), std::move(runner)); - } - - bool is_bound() const { return internal_state_.is_bound(); } - - Interface* get() const { return internal_state_.instance(); } - - // Functions like a pointer to Interface. Must already be bound. - Interface* operator->() const { return get(); } - Interface& operator*() const { return *get(); } - - // Returns the version number of the interface that the remote side supports. - uint32_t version() const { return internal_state_.version(); } - - // Queries the max version that the remote side supports. On completion, the - // result will be returned as the input of |callback|. The version number of - // this object will also be updated. - void QueryVersion(const base::Callback<void(uint32_t)>& callback) { - internal_state_.QueryVersion(callback); - } - - // If the remote side doesn't support the specified version, it will close the - // associated interface asynchronously. This does nothing if it's already - // known that the remote side supports the specified version, i.e., if - // |version <= this->version()|. - // - // After calling RequireVersion() with a version not supported by the remote - // side, all subsequent calls to interface methods will be ignored. - void RequireVersion(uint32_t version) { - internal_state_.RequireVersion(version); - } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Closes the associated interface (if any) and returns the pointer to the - // unbound state. - void reset() { - State doomed; - internal_state_.Swap(&doomed); - } - - // Similar to the method above, but also specifies a disconnect reason. - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (internal_state_.is_bound()) - internal_state_.CloseWithReason(custom_reason, description); - reset(); - } - - // Indicates whether an error has been encountered. If true, method calls made - // on this interface will be dropped (and may already have been dropped). - bool encountered_error() const { return internal_state_.encountered_error(); } - - // Registers a handler to receive error notifications. - // - // This method may only be called after the AssociatedInterfacePtr has been - // bound. - void set_connection_error_handler(const base::Closure& error_handler) { - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Unbinds and returns the associated interface pointer information which - // could be used to setup an AssociatedInterfacePtr again. This method may be - // used to move the proxy to a different thread. - // - // It is an error to call PassInterface() while there are pending responses. - // TODO: fix this restriction, it's not always obvious when there is a - // pending response. - AssociatedInterfacePtrInfo<Interface> PassInterface() { - DCHECK(!internal_state_.has_pending_callbacks()); - State state; - internal_state_.Swap(&state); - - return state.PassInterface(); - } - - // DO NOT USE. Exposed only for internal use and for testing. - internal::AssociatedInterfacePtrState<Interface>* internal_state() { - return &internal_state_; - } - - // Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef internal::AssociatedInterfacePtrState<Interface> - AssociatedInterfacePtr::*Testable; - - public: - operator Testable() const { - return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_ - : nullptr; - } - - private: - // Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr - // will be converted to Testable to do == or != comparison. - template <typename T> - bool operator==(const AssociatedInterfacePtr<T>& other) const = delete; - template <typename T> - bool operator!=(const AssociatedInterfacePtr<T>& other) const = delete; - - typedef internal::AssociatedInterfacePtrState<Interface> State; - mutable State internal_state_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtr); -}; - -// Creates an associated interface. The returned request is supposed to be sent -// over another interface (either associated or non-associated). -// -// NOTE: |ptr| must NOT be used to make calls before the request is sent. -// Violating that will lead to crash. On the other hand, as soon as the request -// is sent, |ptr| is usable. There is no need to wait until the request is bound -// to an implementation at the remote side. -template <typename Interface> -AssociatedInterfaceRequest<Interface> MakeRequest( - AssociatedInterfacePtr<Interface>* ptr, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - AssociatedInterfacePtrInfo<Interface> ptr_info; - auto request = MakeRequest(&ptr_info); - ptr->Bind(std::move(ptr_info), std::move(runner)); - return request; -} - -// Creates an associated interface. One of the two endpoints is supposed to be -// sent over another interface (either associated or non-associated); while the -// other is used locally. -// -// NOTE: If |ptr_info| is used locally and bound to an AssociatedInterfacePtr, -// the interface pointer must NOT be used to make calls before the request is -// sent. Please see NOTE of the previous function for more details. -template <typename Interface> -AssociatedInterfaceRequest<Interface> MakeRequest( - AssociatedInterfacePtrInfo<Interface>* ptr_info) { - ScopedInterfaceEndpointHandle handle0; - ScopedInterfaceEndpointHandle handle1; - ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&handle0, - &handle1); - - ptr_info->set_handle(std::move(handle0)); - ptr_info->set_version(0); - - AssociatedInterfaceRequest<Interface> request; - request.Bind(std::move(handle1)); - return request; -} - -// Like MakeRequest() above, but it creates a dedicated message pipe. The -// returned request can be bound directly to an implementation, without being -// first passed through a message pipe endpoint. -// -// This function has two main uses: -// -// * In testing, where the returned request is bound to e.g. a mock and there -// are no other interfaces involved. -// -// * When discarding messages sent on an interface, which can be done by -// discarding the returned request. -template <typename Interface> -AssociatedInterfaceRequest<Interface> MakeIsolatedRequest( - AssociatedInterfacePtr<Interface>* ptr) { - MessagePipe pipe; - scoped_refptr<internal::MultiplexRouter> router0 = - new internal::MultiplexRouter(std::move(pipe.handle0), - internal::MultiplexRouter::MULTI_INTERFACE, - false, base::ThreadTaskRunnerHandle::Get()); - scoped_refptr<internal::MultiplexRouter> router1 = - new internal::MultiplexRouter(std::move(pipe.handle1), - internal::MultiplexRouter::MULTI_INTERFACE, - true, base::ThreadTaskRunnerHandle::Get()); - - ScopedInterfaceEndpointHandle endpoint0, endpoint1; - ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&endpoint0, - &endpoint1); - InterfaceId id = router1->AssociateInterface(std::move(endpoint0)); - endpoint0 = router0->CreateLocalEndpointHandle(id); - - ptr->Bind(AssociatedInterfacePtrInfo<Interface>(std::move(endpoint0), - Interface::Version_)); - - AssociatedInterfaceRequest<Interface> request; - request.Bind(std::move(endpoint1)); - return request; -} - -// |handle| is supposed to be the request of an associated interface. This -// method associates the interface with a dedicated, disconnected message pipe. -// That way, the corresponding associated interface pointer of |handle| can -// safely make calls (although those calls are silently dropped). -MOJO_CPP_BINDINGS_EXPORT void GetIsolatedInterface( - ScopedInterfaceEndpointHandle handle); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_ptr_info.h b/mojo/public/cpp/bindings/associated_interface_ptr_info.h deleted file mode 100644 index 3c6ca54..0000000 --- a/mojo/public/cpp/bindings/associated_interface_ptr_info.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ - -#include <stdint.h> -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -// AssociatedInterfacePtrInfo stores necessary information to construct an -// associated interface pointer. It is similar to InterfacePtrInfo except that -// it doesn't own a message pipe handle. -template <typename Interface> -class AssociatedInterfacePtrInfo { - public: - AssociatedInterfacePtrInfo() : version_(0u) {} - AssociatedInterfacePtrInfo(std::nullptr_t) : version_(0u) {} - - AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other) - : handle_(std::move(other.handle_)), version_(other.version_) { - other.version_ = 0u; - } - - AssociatedInterfacePtrInfo(ScopedInterfaceEndpointHandle handle, - uint32_t version) - : handle_(std::move(handle)), version_(version) {} - - ~AssociatedInterfacePtrInfo() {} - - AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) { - if (this != &other) { - handle_ = std::move(other.handle_); - version_ = other.version_; - other.version_ = 0u; - } - - return *this; - } - - bool is_valid() const { return handle_.is_valid(); } - - ScopedInterfaceEndpointHandle PassHandle() { - return std::move(handle_); - } - const ScopedInterfaceEndpointHandle& handle() const { return handle_; } - void set_handle(ScopedInterfaceEndpointHandle handle) { - handle_ = std::move(handle); - } - - uint32_t version() const { return version_; } - void set_version(uint32_t version) { version_ = version; } - - bool Equals(const AssociatedInterfacePtrInfo& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_valid() && !other.is_valid(); - } - - private: - ScopedInterfaceEndpointHandle handle_; - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrInfo); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_request.h b/mojo/public/cpp/bindings/associated_interface_request.h deleted file mode 100644 index c37636c..0000000 --- a/mojo/public/cpp/bindings/associated_interface_request.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ - -#include <string> -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -// AssociatedInterfaceRequest represents an associated interface request. It is -// similar to InterfaceRequest except that it doesn't own a message pipe handle. -template <typename Interface> -class AssociatedInterfaceRequest { - public: - // Constructs an empty AssociatedInterfaceRequest, representing that the - // client is not requesting an implementation of Interface. - AssociatedInterfaceRequest() {} - AssociatedInterfaceRequest(decltype(nullptr)) {} - - // Takes the interface endpoint handle from another - // AssociatedInterfaceRequest. - AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) { - handle_ = std::move(other.handle_); - } - AssociatedInterfaceRequest& operator=(AssociatedInterfaceRequest&& other) { - if (this != &other) - handle_ = std::move(other.handle_); - return *this; - } - - // Assigning to nullptr resets the AssociatedInterfaceRequest to an empty - // state, closing the interface endpoint handle currently bound to it (if - // any). - AssociatedInterfaceRequest& operator=(decltype(nullptr)) { - handle_.reset(); - return *this; - } - - // Indicates whether the request currently contains a valid interface endpoint - // handle. - bool is_pending() const { return handle_.is_valid(); } - - void Bind(ScopedInterfaceEndpointHandle handle) { - handle_ = std::move(handle); - } - - ScopedInterfaceEndpointHandle PassHandle() { - return std::move(handle_); - } - - const ScopedInterfaceEndpointHandle& handle() const { return handle_; } - - bool Equals(const AssociatedInterfaceRequest& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_pending() && !other.is_pending(); - } - - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - handle_.ResetWithReason(custom_reason, description); - } - - private: - ScopedInterfaceEndpointHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceRequest); -}; - -// Makes an AssociatedInterfaceRequest bound to the specified associated -// endpoint. -template <typename Interface> -AssociatedInterfaceRequest<Interface> MakeAssociatedRequest( - ScopedInterfaceEndpointHandle handle) { - AssociatedInterfaceRequest<Interface> request; - request.Bind(std::move(handle)); - return request; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ diff --git a/mojo/public/cpp/bindings/binding.h b/mojo/public/cpp/bindings/binding.h deleted file mode 100644 index 88d2f4b..0000000 --- a/mojo/public/cpp/bindings/binding.h +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ - -#include <string> -#include <utility> - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/binding_state.h" -#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -class MessageReceiver; - -// Represents the binding of an interface implementation to a message pipe. -// When the |Binding| object is destroyed, the binding between the message pipe -// and the interface is torn down and the message pipe is closed, leaving the -// interface implementation in an unbound state. -// -// Example: -// -// #include "foo.mojom.h" -// -// class FooImpl : public Foo { -// public: -// explicit FooImpl(InterfaceRequest<Foo> request) -// : binding_(this, std::move(request)) {} -// -// // Foo implementation here. -// -// private: -// Binding<Foo> binding_; -// }; -// -// class MyFooFactory : public InterfaceFactory<Foo> { -// public: -// void Create(..., InterfaceRequest<Foo> request) override { -// auto f = new FooImpl(std::move(request)); -// // Do something to manage the lifetime of |f|. Use StrongBinding<> to -// // delete FooImpl on connection errors. -// } -// }; -// -// This class is thread hostile while bound to a message pipe. All calls to this -// class must be from the thread that bound it. The interface implementation's -// methods will be called from the thread that bound this. If a Binding is not -// bound to a message pipe, it may be bound or destroyed on any thread. -// -// When you bind this class to a message pipe, optionally you can specify a -// base::SingleThreadTaskRunner. This task runner must belong to the same -// thread. It will be used to dispatch incoming method calls and connection -// error notification. It is useful when you attach multiple task runners to a -// single thread for the purposes of task scheduling. Please note that incoming -// synchrounous method calls may not be run from this task runner, when they -// reenter outgoing synchrounous calls on the same thread. -template <typename Interface, - typename ImplRefTraits = RawPtrImplRefTraits<Interface>> -class Binding { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - // Constructs an incomplete binding that will use the implementation |impl|. - // The binding may be completed with a subsequent call to the |Bind| method. - // Does not take ownership of |impl|, which must outlive the binding. - explicit Binding(ImplPointerType impl) : internal_state_(std::move(impl)) {} - - // Constructs a completed binding of message pipe |handle| to implementation - // |impl|. Does not take ownership of |impl|, which must outlive the binding. - Binding(ImplPointerType impl, - ScopedMessagePipeHandle handle, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(std::move(handle), std::move(runner)); - } - - // Constructs a completed binding of |impl| to a new message pipe, passing the - // client end to |ptr|, which takes ownership of it. The caller is expected to - // pass |ptr| on to the client of the service. Does not take ownership of any - // of the parameters. |impl| must outlive the binding. |ptr| only needs to - // last until the constructor returns. - Binding(ImplPointerType impl, - InterfacePtr<Interface>* ptr, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(ptr, std::move(runner)); - } - - // Constructs a completed binding of |impl| to the message pipe endpoint in - // |request|, taking ownership of the endpoint. Does not take ownership of - // |impl|, which must outlive the binding. - Binding(ImplPointerType impl, - InterfaceRequest<Interface> request, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(request.PassMessagePipe(), std::move(runner)); - } - - // Tears down the binding, closing the message pipe and leaving the interface - // implementation unbound. - ~Binding() {} - - // Returns an InterfacePtr bound to one end of a pipe whose other end is - // bound to |this|. - InterfacePtr<Interface> CreateInterfacePtrAndBind( - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - InterfacePtr<Interface> interface_ptr; - Bind(&interface_ptr, std::move(runner)); - return interface_ptr; - } - - // Completes a binding that was constructed with only an interface - // implementation. Takes ownership of |handle| and binds it to the previously - // specified implementation. - void Bind(ScopedMessagePipeHandle handle, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - internal_state_.Bind(std::move(handle), std::move(runner)); - } - - // Completes a binding that was constructed with only an interface - // implementation by creating a new message pipe, binding one end of it to the - // previously specified implementation, and passing the other to |ptr|, which - // takes ownership of it. The caller is expected to pass |ptr| on to the - // eventual client of the service. Does not take ownership of |ptr|. - void Bind(InterfacePtr<Interface>* ptr, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - MessagePipe pipe; - ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), - Interface::Version_), - runner); - Bind(std::move(pipe.handle1), std::move(runner)); - } - - // Completes a binding that was constructed with only an interface - // implementation by removing the message pipe endpoint from |request| and - // binding it to the previously specified implementation. - void Bind(InterfaceRequest<Interface> request, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - Bind(request.PassMessagePipe(), std::move(runner)); - } - - // Adds a message filter to be notified of each incoming message before - // dispatch. If a filter returns |false| from Accept(), the message is not - // dispatched and the pipe is closed. Filters cannot be removed. - void AddFilter(std::unique_ptr<MessageReceiver> filter) { - DCHECK(is_bound()); - internal_state_.AddFilter(std::move(filter)); - } - - // Whether there are any associated interfaces running on the pipe currently. - bool HasAssociatedInterfaces() const { - return internal_state_.HasAssociatedInterfaces(); - } - - // Stops processing incoming messages until - // ResumeIncomingMethodCallProcessing(), or WaitForIncomingMethodCall(). - // Outgoing messages are still sent. - // - // No errors are detected on the message pipe while paused. - // - // This method may only be called if the object has been bound to a message - // pipe and there are no associated interfaces running. - void PauseIncomingMethodCallProcessing() { - CHECK(!HasAssociatedInterfaces()); - internal_state_.PauseIncomingMethodCallProcessing(); - } - void ResumeIncomingMethodCallProcessing() { - internal_state_.ResumeIncomingMethodCallProcessing(); - } - - // Blocks the calling thread until either a call arrives on the previously - // bound message pipe, the deadline is exceeded, or an error occurs. Returns - // true if a method was successfully read and dispatched. - // - // This method may only be called if the object has been bound to a message - // pipe. This returns once a message is received either on the master - // interface or any associated interfaces. - bool WaitForIncomingMethodCall( - MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) { - return internal_state_.WaitForIncomingMethodCall(deadline); - } - - // Closes the message pipe that was previously bound. Put this object into a - // state where it can be rebound to a new pipe. - void Close() { internal_state_.Close(); } - - // Similar to the method above, but also specifies a disconnect reason. - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - internal_state_.CloseWithReason(custom_reason, description); - } - - // Unbinds the underlying pipe from this binding and returns it so it can be - // used in another context, such as on another thread or with a different - // implementation. Put this object into a state where it can be rebound to a - // new pipe. - // - // This method may only be called if the object has been bound to a message - // pipe and there are no associated interfaces running. - // - // TODO(yzshen): For now, users need to make sure there is no one holding - // on to associated interface endpoint handles at both sides of the - // message pipe in order to call this method. We need a way to forcefully - // invalidate associated interface endpoint handles. - InterfaceRequest<Interface> Unbind() { - CHECK(!HasAssociatedInterfaces()); - return internal_state_.Unbind(); - } - - // Sets an error handler that will be called if a connection error occurs on - // the bound message pipe. - // - // This method may only be called after this Binding has been bound to a - // message pipe. The error handler will be reset when this Binding is unbound - // or closed. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(is_bound()); - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Returns the interface implementation that was previously specified. Caller - // does not take ownership. - Interface* impl() { return internal_state_.impl(); } - - // Indicates whether the binding has been completed (i.e., whether a message - // pipe has been bound to the implementation). - bool is_bound() const { return internal_state_.is_bound(); } - - // Returns the value of the handle currently bound to this Binding which can - // be used to make explicit Wait/WaitMany calls. Requires that the Binding be - // bound. Ownership of the handle is retained by the Binding, it is not - // transferred to the caller. - MessagePipeHandle handle() const { return internal_state_.handle(); } - - // Sends a no-op message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Exposed for testing, should not generally be used. - void EnableTestingMode() { internal_state_.EnableTestingMode(); } - - private: - internal::BindingState<Interface, ImplRefTraits> internal_state_; - - DISALLOW_COPY_AND_ASSIGN(Binding); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h deleted file mode 100644 index 919f9c0..0000000 --- a/mojo/public/cpp/bindings/binding_set.h +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ - -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -template <typename BindingType> -struct BindingSetTraits; - -template <typename Interface, typename ImplRefTraits> -struct BindingSetTraits<Binding<Interface, ImplRefTraits>> { - using ProxyType = InterfacePtr<Interface>; - using RequestType = InterfaceRequest<Interface>; - using BindingType = Binding<Interface, ImplRefTraits>; - using ImplPointerType = typename BindingType::ImplPointerType; - - static RequestType MakeRequest(ProxyType* proxy) { - return mojo::MakeRequest(proxy); - } -}; - -using BindingId = size_t; - -template <typename ContextType> -struct BindingSetContextTraits { - using Type = ContextType; - - static constexpr bool SupportsContext() { return true; } -}; - -template <> -struct BindingSetContextTraits<void> { - // NOTE: This choice of Type only matters insofar as it affects the size of - // the |context_| field of a BindingSetBase::Entry with void context. The - // context value is never used in this case. - using Type = bool; - - static constexpr bool SupportsContext() { return false; } -}; - -// Generic definition used for BindingSet and AssociatedBindingSet to own a -// collection of bindings which point to the same implementation. -// -// If |ContextType| is non-void, then every added binding must include a context -// value of that type, and |dispatch_context()| will return that value during -// the extent of any message dispatch targeting that specific binding. -template <typename Interface, typename BindingType, typename ContextType> -class BindingSetBase { - public: - using ContextTraits = BindingSetContextTraits<ContextType>; - using Context = typename ContextTraits::Type; - using PreDispatchCallback = base::Callback<void(const Context&)>; - using Traits = BindingSetTraits<BindingType>; - using ProxyType = typename Traits::ProxyType; - using RequestType = typename Traits::RequestType; - using ImplPointerType = typename Traits::ImplPointerType; - - BindingSetBase() {} - - void set_connection_error_handler(const base::Closure& error_handler) { - error_handler_ = error_handler; - error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - error_with_reason_handler_ = error_handler; - error_handler_.Reset(); - } - - // Sets a callback to be invoked immediately before dispatching any message or - // error received by any of the bindings in the set. This may only be used - // with a non-void |ContextType|. - void set_pre_dispatch_handler(const PreDispatchCallback& handler) { - static_assert(ContextTraits::SupportsContext(), - "Pre-dispatch handler usage requires non-void context type."); - pre_dispatch_handler_ = handler; - } - - // Adds a new binding to the set which binds |request| to |impl| with no - // additional context. - BindingId AddBinding(ImplPointerType impl, RequestType request) { - static_assert(!ContextTraits::SupportsContext(), - "Context value required for non-void context type."); - return AddBindingImpl(std::move(impl), std::move(request), false); - } - - // Adds a new binding associated with |context|. - BindingId AddBinding(ImplPointerType impl, - RequestType request, - Context context) { - static_assert(ContextTraits::SupportsContext(), - "Context value unsupported for void context type."); - return AddBindingImpl(std::move(impl), std::move(request), - std::move(context)); - } - - // Removes a binding from the set. Note that this is safe to call even if the - // binding corresponding to |id| has already been removed. - // - // Returns |true| if the binding was removed and |false| if it didn't exist. - bool RemoveBinding(BindingId id) { - auto it = bindings_.find(id); - if (it == bindings_.end()) - return false; - bindings_.erase(it); - return true; - } - - // Returns a proxy bound to one end of a pipe whose other end is bound to - // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID - // of the added binding. - ProxyType CreateInterfacePtrAndBind(ImplPointerType impl, - BindingId* id_storage = nullptr) { - ProxyType proxy; - BindingId id = AddBinding(std::move(impl), Traits::MakeRequest(&proxy)); - if (id_storage) - *id_storage = id; - return proxy; - } - - void CloseAllBindings() { bindings_.clear(); } - - bool empty() const { return bindings_.empty(); } - - // Implementations may call this when processing a dispatched message or - // error. During the extent of message or error dispatch, this will return the - // context associated with the specific binding which received the message or - // error. Use AddBinding() to associated a context with a specific binding. - const Context& dispatch_context() const { - static_assert(ContextTraits::SupportsContext(), - "dispatch_context() requires non-void context type."); - DCHECK(dispatch_context_); - return *dispatch_context_; - } - - void FlushForTesting() { - for (auto& binding : bindings_) - binding.second->FlushForTesting(); - } - - private: - friend class Entry; - - class Entry { - public: - Entry(ImplPointerType impl, - RequestType request, - BindingSetBase* binding_set, - BindingId binding_id, - Context context) - : binding_(std::move(impl), std::move(request)), - binding_set_(binding_set), - binding_id_(binding_id), - context_(std::move(context)) { - if (ContextTraits::SupportsContext()) - binding_.AddFilter(base::MakeUnique<DispatchFilter>(this)); - binding_.set_connection_error_with_reason_handler( - base::Bind(&Entry::OnConnectionError, base::Unretained(this))); - } - - void FlushForTesting() { binding_.FlushForTesting(); } - - private: - class DispatchFilter : public MessageReceiver { - public: - explicit DispatchFilter(Entry* entry) : entry_(entry) {} - ~DispatchFilter() override {} - - private: - // MessageReceiver: - bool Accept(Message* message) override { - entry_->WillDispatch(); - return true; - } - - Entry* entry_; - - DISALLOW_COPY_AND_ASSIGN(DispatchFilter); - }; - - void WillDispatch() { - DCHECK(ContextTraits::SupportsContext()); - binding_set_->SetDispatchContext(&context_); - } - - void OnConnectionError(uint32_t custom_reason, - const std::string& description) { - if (ContextTraits::SupportsContext()) - WillDispatch(); - binding_set_->OnConnectionError(binding_id_, custom_reason, description); - } - - BindingType binding_; - BindingSetBase* const binding_set_; - const BindingId binding_id_; - Context const context_; - - DISALLOW_COPY_AND_ASSIGN(Entry); - }; - - void SetDispatchContext(const Context* context) { - DCHECK(ContextTraits::SupportsContext()); - dispatch_context_ = context; - if (!pre_dispatch_handler_.is_null()) - pre_dispatch_handler_.Run(*context); - } - - BindingId AddBindingImpl(ImplPointerType impl, - RequestType request, - Context context) { - BindingId id = next_binding_id_++; - DCHECK_GE(next_binding_id_, 0u); - auto entry = base::MakeUnique<Entry>(std::move(impl), std::move(request), - this, id, std::move(context)); - bindings_.insert(std::make_pair(id, std::move(entry))); - return id; - } - - void OnConnectionError(BindingId id, - uint32_t custom_reason, - const std::string& description) { - auto it = bindings_.find(id); - DCHECK(it != bindings_.end()); - - // We keep the Entry alive throughout error dispatch. - std::unique_ptr<Entry> entry = std::move(it->second); - bindings_.erase(it); - - if (!error_handler_.is_null()) - error_handler_.Run(); - else if (!error_with_reason_handler_.is_null()) - error_with_reason_handler_.Run(custom_reason, description); - } - - base::Closure error_handler_; - ConnectionErrorWithReasonCallback error_with_reason_handler_; - PreDispatchCallback pre_dispatch_handler_; - BindingId next_binding_id_ = 0; - std::map<BindingId, std::unique_ptr<Entry>> bindings_; - const Context* dispatch_context_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(BindingSetBase); -}; - -template <typename Interface, typename ContextType = void> -using BindingSet = BindingSetBase<Interface, Binding<Interface>, ContextType>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ diff --git a/mojo/public/cpp/bindings/bindings_export.h b/mojo/public/cpp/bindings/bindings_export.h deleted file mode 100644 index 9fd7a27..0000000 --- a/mojo/public/cpp/bindings/bindings_export.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION) -#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllexport) -#else -#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION) -#define MOJO_CPP_BINDINGS_EXPORT __attribute((visibility("default"))) -#else -#define MOJO_CPP_BINDINGS_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) - -#define MOJO_CPP_BINDINGS_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ diff --git a/mojo/public/cpp/bindings/clone_traits.h b/mojo/public/cpp/bindings/clone_traits.h deleted file mode 100644 index 203ab34..0000000 --- a/mojo/public/cpp/bindings/clone_traits.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ - -#include <type_traits> -#include <unordered_map> -#include <vector> - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { - -template <typename T> -struct HasCloneMethod { - template <typename U> - static char Test(decltype(&U::Clone)); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - internal::EnsureTypeIsComplete<T> check_t_; -}; - -template <typename T, bool has_clone_method = HasCloneMethod<T>::value> -struct CloneTraits; - -template <typename T> -T Clone(const T& input); - -template <typename T> -struct CloneTraits<T, true> { - static T Clone(const T& input) { return input.Clone(); } -}; - -template <typename T> -struct CloneTraits<T, false> { - static T Clone(const T& input) { return input; } -}; - -template <typename T> -struct CloneTraits<base::Optional<T>, false> { - static base::Optional<T> Clone(const base::Optional<T>& input) { - if (!input) - return base::nullopt; - - return base::Optional<T>(mojo::Clone(*input)); - } -}; - -template <typename T> -struct CloneTraits<std::vector<T>, false> { - static std::vector<T> Clone(const std::vector<T>& input) { - std::vector<T> result; - result.reserve(input.size()); - for (const auto& element : input) - result.push_back(mojo::Clone(element)); - - return result; - } -}; - -template <typename K, typename V> -struct CloneTraits<std::unordered_map<K, V>, false> { - static std::unordered_map<K, V> Clone(const std::unordered_map<K, V>& input) { - std::unordered_map<K, V> result; - for (const auto& element : input) { - result.insert(std::make_pair(mojo::Clone(element.first), - mojo::Clone(element.second))); - } - return result; - } -}; - -template <typename T> -T Clone(const T& input) { - return CloneTraits<T>::Clone(input); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/connection_error_callback.h b/mojo/public/cpp/bindings/connection_error_callback.h deleted file mode 100644 index 306e99e..0000000 --- a/mojo/public/cpp/bindings/connection_error_callback.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ - -#include "base/callback.h" - -namespace mojo { - -// This callback type accepts user-defined disconnect reason and description. If -// the other side specifies a reason on closing the connection, it will be -// passed to the error handler. -using ConnectionErrorWithReasonCallback = - base::Callback<void(uint32_t /* custom_reason */, - const std::string& /* description */)>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h deleted file mode 100644 index cb065c1..0000000 --- a/mojo/public/cpp/bindings/connector.h +++ /dev/null @@ -1,241 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/simple_watcher.h" - -namespace base { -class Lock; -} - -namespace mojo { - -// The Connector class is responsible for performing read/write operations on a -// MessagePipe. It writes messages it receives through the MessageReceiver -// interface that it subclasses, and it forwards messages it reads through the -// MessageReceiver interface assigned as its incoming receiver. -// -// NOTE: -// - MessagePipe I/O is non-blocking. -// - Sending messages can be configured to be thread safe (please see comments -// of the constructor). Other than that, the object should only be accessed -// on the creating thread. -class MOJO_CPP_BINDINGS_EXPORT Connector - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - enum ConnectorConfig { - // Connector::Accept() is only called from a single thread. - SINGLE_THREADED_SEND, - // Connector::Accept() is allowed to be called from multiple threads. - MULTI_THREADED_SEND - }; - - // The Connector takes ownership of |message_pipe|. - Connector(ScopedMessagePipeHandle message_pipe, - ConnectorConfig config, - scoped_refptr<base::SingleThreadTaskRunner> runner); - ~Connector() override; - - // Sets the receiver to handle messages read from the message pipe. The - // Connector will read messages from the pipe regardless of whether or not an - // incoming receiver has been set. - void set_incoming_receiver(MessageReceiver* receiver) { - DCHECK(thread_checker_.CalledOnValidThread()); - incoming_receiver_ = receiver; - } - - // Errors from incoming receivers will force the connector into an error - // state, where no more messages will be processed. This method is used - // during testing to prevent that from happening. - void set_enforce_errors_from_incoming_receiver(bool enforce) { - DCHECK(thread_checker_.CalledOnValidThread()); - enforce_errors_from_incoming_receiver_ = enforce; - } - - // Sets the error handler to receive notifications when an error is - // encountered while reading from the pipe or waiting to read from the pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - connection_error_handler_ = error_handler; - } - - // Returns true if an error was encountered while reading from the pipe or - // waiting to read from the pipe. - bool encountered_error() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return error_; - } - - // Closes the pipe. The connector is put into a quiescent state. - // - // Please note that this method shouldn't be called unless it results from an - // explicit request of the user of bindings (e.g., the user sets an - // InterfacePtr to null or closes a Binding). - void CloseMessagePipe(); - - // Releases the pipe. Connector is put into a quiescent state. - ScopedMessagePipeHandle PassMessagePipe(); - - // Enters the error state. The upper layer may do this for unrecoverable - // issues such as invalid messages are received. If a connection error handler - // has been set, it will be called asynchronously. - // - // It is a no-op if the connector is already in the error state or there isn't - // a bound message pipe. Otherwise, it closes the message pipe, which notifies - // the other end and also prevents potential danger (say, the caller raises - // an error because it believes the other end is malicious). In order to - // appear to the user that the connector still binds to a message pipe, it - // creates a new message pipe, closes one end and binds to the other. - void RaiseError(); - - // Is the connector bound to a MessagePipe handle? - bool is_valid() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return message_pipe_.is_valid(); - } - - // Waits for the next message on the pipe, blocking until one arrives, - // |deadline| elapses, or an error happens. Returns |true| if a message has - // been delivered, |false| otherwise. - bool WaitForIncomingMessage(MojoDeadline deadline); - - // See Binding for details of pause/resume. - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - MessagePipeHandle handle() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return message_pipe_.get(); - } - - // Allows |message_pipe_| to be watched while others perform sync handle - // watching on the same thread. Please see comments of - // SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread(). - void AllowWokenUpBySyncWatchOnSameThread(); - - // Watches |message_pipe_| (as well as other handles registered to be watched - // together) synchronously. - // This method: - // - returns true when |should_stop| is set to true; - // - return false when any error occurs, including |message_pipe_| being - // closed. - bool SyncWatch(const bool* should_stop); - - // Whether currently the control flow is inside the sync handle watcher - // callback. - // It always returns false after CloseMessagePipe()/PassMessagePipe(). - bool during_sync_handle_watcher_callback() const { - return sync_handle_watcher_callback_count_ > 0; - } - - base::SingleThreadTaskRunner* task_runner() const { - return task_runner_.get(); - } - - // Sets the tag used by the heap profiler. - // |tag| must be a const string literal. - void SetWatcherHeapProfilerTag(const char* tag); - - private: - class ActiveDispatchTracker; - class MessageLoopNestingObserver; - - // Callback of mojo::SimpleWatcher. - void OnWatcherHandleReady(MojoResult result); - // Callback of SyncHandleWatcher. - void OnSyncHandleWatcherHandleReady(MojoResult result); - void OnHandleReadyInternal(MojoResult result); - - void WaitToReadMore(); - - // Returns false if it is impossible to receive more messages in the future. - // |this| may have been destroyed in that case. - WARN_UNUSED_RESULT bool ReadSingleMessage(MojoResult* read_result); - - // |this| can be destroyed during message dispatch. - void ReadAllAvailableMessages(); - - // If |force_pipe_reset| is true, this method replaces the existing - // |message_pipe_| with a dummy message pipe handle (whose peer is closed). - // If |force_async_handler| is true, |connection_error_handler_| is called - // asynchronously. - void HandleError(bool force_pipe_reset, bool force_async_handler); - - // Cancels any calls made to |waiter_|. - void CancelWait(); - - void EnsureSyncWatcherExists(); - - base::Closure connection_error_handler_; - - ScopedMessagePipeHandle message_pipe_; - MessageReceiver* incoming_receiver_ = nullptr; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - std::unique_ptr<SimpleWatcher> handle_watcher_; - - bool error_ = false; - bool drop_writes_ = false; - bool enforce_errors_from_incoming_receiver_ = true; - - bool paused_ = false; - - // If sending messages is allowed from multiple threads, |lock_| is used to - // protect modifications to |message_pipe_| and |drop_writes_|. - base::Optional<base::Lock> lock_; - - std::unique_ptr<SyncHandleWatcher> sync_watcher_; - bool allow_woken_up_by_others_ = false; - // If non-zero, currently the control flow is inside the sync handle watcher - // callback. - size_t sync_handle_watcher_callback_count_ = 0; - - base::ThreadChecker thread_checker_; - - base::Lock connected_lock_; - bool connected_ = true; - - // The tag used to track heap allocations that originated from a Watcher - // notification. - const char* heap_profiler_tag_ = nullptr; - - // A cached pointer to the MessageLoopNestingObserver for the MessageLoop on - // which this Connector was created. - MessageLoopNestingObserver* const nesting_observer_; - - // |true| iff the Connector is currently dispatching a message. Used to detect - // nested dispatch operations. - bool is_dispatching_ = false; - - // Create a single weak ptr and use it everywhere, to avoid the malloc/free - // cost of creating a new weak ptr whenever it is needed. - // NOTE: This weak pointer is invalidated when the message pipe is closed or - // transferred (i.e., when |connected_| is set to false). - base::WeakPtr<Connector> weak_self_; - base::WeakPtrFactory<Connector> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Connector); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ diff --git a/mojo/public/cpp/bindings/disconnect_reason.h b/mojo/public/cpp/bindings/disconnect_reason.h deleted file mode 100644 index c04e8ad..0000000 --- a/mojo/public/cpp/bindings/disconnect_reason.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ - -#include <stdint.h> - -#include <string> - -namespace mojo { - -struct DisconnectReason { - public: - DisconnectReason(uint32_t in_custom_reason, const std::string& in_description) - : custom_reason(in_custom_reason), description(in_description) {} - - uint32_t custom_reason; - std::string description; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ diff --git a/mojo/public/cpp/bindings/enum_traits.h b/mojo/public/cpp/bindings/enum_traits.h deleted file mode 100644 index 2c528f3..0000000 --- a/mojo/public/cpp/bindings/enum_traits.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as a -// mojom enum |MojomType|. Each specialization needs to implement: -// -// template <> -// struct EnumTraits<MojomType, T> { -// static MojomType ToMojom(T input); -// -// // Returning false results in deserialization failure and causes the -// // message pipe receiving it to be disconnected. -// static bool FromMojom(MojomType input, T* output); -// }; -// -template <typename MojomType, typename T> -struct EnumTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/filter_chain.h b/mojo/public/cpp/bindings/filter_chain.h deleted file mode 100644 index 1262f39..0000000 --- a/mojo/public/cpp/bindings/filter_chain.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ - -#include <utility> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class MOJO_CPP_BINDINGS_EXPORT FilterChain - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - explicit FilterChain(MessageReceiver* sink = nullptr); - - FilterChain(FilterChain&& other); - FilterChain& operator=(FilterChain&& other); - ~FilterChain() override; - - template <typename FilterType, typename... Args> - inline void Append(Args&&... args); - - void Append(std::unique_ptr<MessageReceiver> filter); - - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - void SetSink(MessageReceiver* sink); - - // MessageReceiver: - bool Accept(Message* message) override; - - private: - std::vector<std::unique_ptr<MessageReceiver>> filters_; - - MessageReceiver* sink_; - - DISALLOW_COPY_AND_ASSIGN(FilterChain); -}; - -template <typename FilterType, typename... Args> -inline void FilterChain::Append(Args&&... args) { - Append(base::MakeUnique<FilterType>(std::forward<Args>(args)...)); -} - -template <> -inline void FilterChain::Append<PassThroughFilter>() { -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ diff --git a/mojo/public/cpp/bindings/interface_data_view.h b/mojo/public/cpp/bindings/interface_data_view.h deleted file mode 100644 index ef12254..0000000 --- a/mojo/public/cpp/bindings/interface_data_view.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ - -namespace mojo { - -// They are used for type identification purpose only. -template <typename Interface> -class AssociatedInterfacePtrInfoDataView {}; - -template <typename Interface> -class AssociatedInterfaceRequestDataView {}; - -template <typename Interface> -class InterfacePtrDataView {}; - -template <typename Interface> -class InterfaceRequestDataView {}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h deleted file mode 100644 index b519fe9..0000000 --- a/mojo/public/cpp/bindings/interface_endpoint_client.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ - -#include <stdint.h> - -#include <map> -#include <memory> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/lib/control_message_handler.h" -#include "mojo/public/cpp/bindings/lib/control_message_proxy.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class AssociatedGroup; -class InterfaceEndpointController; - -// InterfaceEndpointClient handles message sending and receiving of an interface -// endpoint, either the implementation side or the client side. -// It should only be accessed and destructed on the creating thread. -class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient - : NON_EXPORTED_BASE(public MessageReceiverWithResponder) { - public: - // |receiver| is okay to be null. If it is not null, it must outlive this - // object. - InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr<MessageReceiver> payload_validator, - bool expect_sync_requests, - scoped_refptr<base::SingleThreadTaskRunner> runner, - uint32_t interface_version); - ~InterfaceEndpointClient() override; - - // Sets the error handler to receive notifications when an error is - // encountered. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - error_handler_ = error_handler; - error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - error_with_reason_handler_ = error_handler; - error_handler_.Reset(); - } - - // Returns true if an error was encountered. - bool encountered_error() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return encountered_error_; - } - - // Returns true if this endpoint has any pending callbacks. - bool has_pending_responders() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return !async_responders_.empty() || !sync_responses_.empty(); - } - - AssociatedGroup* associated_group(); - - // Adds a MessageReceiver which can filter a message after validation but - // before dispatch. - void AddFilter(std::unique_ptr<MessageReceiver> filter); - - // After this call the object is in an invalid state and shouldn't be reused. - ScopedInterfaceEndpointHandle PassHandle(); - - // Raises an error on the underlying message pipe. It disconnects the pipe - // and notifies all interfaces running on this pipe. - void RaiseError(); - - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - // MessageReceiverWithResponder implementation: - // They must only be called when the handle is not in pending association - // state. - bool Accept(Message* message) override; - bool AcceptWithResponder(Message* message, - std::unique_ptr<MessageReceiver> responder) override; - - // The following methods are called by the router. They must be called - // outside of the router's lock. - - // NOTE: |message| must have passed message header validation. - bool HandleIncomingMessage(Message* message); - void NotifyError(const base::Optional<DisconnectReason>& reason); - - // The following methods send interface control messages. - // They must only be called when the handle is not in pending association - // state. - void QueryVersion(const base::Callback<void(uint32_t)>& callback); - void RequireVersion(uint32_t version); - void FlushForTesting(); - - private: - // Maps from the id of a response to the MessageReceiver that handles the - // response. - using AsyncResponderMap = - std::map<uint64_t, std::unique_ptr<MessageReceiver>>; - - struct SyncResponseInfo { - public: - explicit SyncResponseInfo(bool* in_response_received); - ~SyncResponseInfo(); - - Message response; - - // Points to a stack-allocated variable. - bool* response_received; - - private: - DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo); - }; - - using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>; - - // Used as the sink for |payload_validator_| and forwards messages to - // HandleValidatedMessage(). - class HandleIncomingMessageThunk : public MessageReceiver { - public: - explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner); - ~HandleIncomingMessageThunk() override; - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - private: - InterfaceEndpointClient* const owner_; - - DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk); - }; - - void InitControllerIfNecessary(); - - void OnAssociationEvent( - ScopedInterfaceEndpointHandle::AssociationEvent event); - - bool HandleValidatedMessage(Message* message); - - const bool expect_sync_requests_ = false; - - ScopedInterfaceEndpointHandle handle_; - std::unique_ptr<AssociatedGroup> associated_group_; - InterfaceEndpointController* controller_ = nullptr; - - MessageReceiverWithResponderStatus* const incoming_receiver_ = nullptr; - HandleIncomingMessageThunk thunk_; - FilterChain filters_; - - AsyncResponderMap async_responders_; - SyncResponseMap sync_responses_; - - uint64_t next_request_id_ = 1; - - base::Closure error_handler_; - ConnectionErrorWithReasonCallback error_with_reason_handler_; - bool encountered_error_ = false; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - internal::ControlMessageProxy control_message_proxy_; - internal::ControlMessageHandler control_message_handler_; - - base::ThreadChecker thread_checker_; - - base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ diff --git a/mojo/public/cpp/bindings/interface_endpoint_controller.h b/mojo/public/cpp/bindings/interface_endpoint_controller.h deleted file mode 100644 index 8d99d4a..0000000 --- a/mojo/public/cpp/bindings/interface_endpoint_controller.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ - -namespace mojo { - -class Message; - -// A control interface exposed by AssociatedGroupController for interface -// endpoints. -class InterfaceEndpointController { - public: - virtual ~InterfaceEndpointController() {} - - virtual bool SendMessage(Message* message) = 0; - - // Allows the interface endpoint to watch for incoming sync messages while - // others perform sync handle watching on the same thread. Please see comments - // of SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread(). - virtual void AllowWokenUpBySyncWatchOnSameThread() = 0; - - // Watches the interface endpoint for incoming sync messages. (It also watches - // other other handles registered to be watched together.) - // This method: - // - returns true when |should_stop| is set to true; - // - return false otherwise, including - // MultiplexRouter::DetachEndpointClient() being called for the same - // interface endpoint. - virtual bool SyncWatch(const bool* should_stop) = 0; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ diff --git a/mojo/public/cpp/bindings/interface_id.h b/mojo/public/cpp/bindings/interface_id.h deleted file mode 100644 index 53475d6..0000000 --- a/mojo/public/cpp/bindings/interface_id.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ - -#include <stdint.h> - -namespace mojo { - -// The size of the type matters because it is directly used in messages. -using InterfaceId = uint32_t; - -// IDs of associated interface can be generated at both sides of the message -// pipe. In order to avoid collision, the highest bit is used as namespace bit: -// at the side where the client-side of the master interface lives, IDs are -// generated with the namespace bit set to 1; at the opposite side IDs are -// generated with the namespace bit set to 0. -const uint32_t kInterfaceIdNamespaceMask = 0x80000000; - -const InterfaceId kMasterInterfaceId = 0x00000000; -const InterfaceId kInvalidInterfaceId = 0xFFFFFFFF; - -inline bool IsMasterInterfaceId(InterfaceId id) { - return id == kMasterInterfaceId; -} - -inline bool IsValidInterfaceId(InterfaceId id) { - return id != kInvalidInterfaceId; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h deleted file mode 100644 index e88be74..0000000 --- a/mojo/public/cpp/bindings/interface_ptr.h +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ - -#include <stdint.h> - -#include <string> -#include <utility> - -#include "base/callback_forward.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/lib/interface_ptr_state.h" - -namespace mojo { - -// A pointer to a local proxy of a remote Interface implementation. Uses a -// message pipe to communicate with the remote implementation, and automatically -// closes the pipe and deletes the proxy on destruction. The pointer must be -// bound to a message pipe before the interface methods can be called. -// -// This class is thread hostile, as is the local proxy it manages, while bound -// to a message pipe. All calls to this class or the proxy should be from the -// same thread that bound it. If you need to move the proxy to a different -// thread, extract the InterfacePtrInfo (containing just the message pipe and -// any version information) using PassInterface(), pass it to a different -// thread, and create and bind a new InterfacePtr from that thread. If an -// InterfacePtr is not bound to a message pipe, it may be bound or destroyed on -// any thread. -template <typename Interface> -class InterfacePtr { - public: - using InterfaceType = Interface; - using PtrInfoType = InterfacePtrInfo<Interface>; - - // Constructs an unbound InterfacePtr. - InterfacePtr() {} - InterfacePtr(decltype(nullptr)) {} - - // Takes over the binding of another InterfacePtr. - InterfacePtr(InterfacePtr&& other) { - internal_state_.Swap(&other.internal_state_); - } - - // Takes over the binding of another InterfacePtr, and closes any message pipe - // already bound to this pointer. - InterfacePtr& operator=(InterfacePtr&& other) { - reset(); - internal_state_.Swap(&other.internal_state_); - return *this; - } - - // Assigning nullptr to this class causes it to close the currently bound - // message pipe (if any) and returns the pointer to the unbound state. - InterfacePtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - // Closes the bound message pipe (if any) on destruction. - ~InterfacePtr() {} - - // Binds the InterfacePtr to a remote implementation of Interface. - // - // Calling with an invalid |info| (containing an invalid message pipe handle) - // has the same effect as reset(). In this case, the InterfacePtr is not - // considered as bound. - // - // |runner| must belong to the same thread. It will be used to dispatch all - // callbacks and connection error notification. It is useful when you attach - // multiple task runners to a single thread for the purposes of task - // scheduling. - void Bind(InterfacePtrInfo<Interface> info, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - reset(); - if (info.is_valid()) - internal_state_.Bind(std::move(info), std::move(runner)); - } - - // Returns whether or not this InterfacePtr is bound to a message pipe. - bool is_bound() const { return internal_state_.is_bound(); } - - // Returns a raw pointer to the local proxy. Caller does not take ownership. - // Note that the local proxy is thread hostile, as stated above. - Interface* get() const { return internal_state_.instance(); } - - // Functions like a pointer to Interface. Must already be bound. - Interface* operator->() const { return get(); } - Interface& operator*() const { return *get(); } - - // Returns the version number of the interface that the remote side supports. - uint32_t version() const { return internal_state_.version(); } - - // Queries the max version that the remote side supports. On completion, the - // result will be returned as the input of |callback|. The version number of - // this interface pointer will also be updated. - void QueryVersion(const base::Callback<void(uint32_t)>& callback) { - internal_state_.QueryVersion(callback); - } - - // If the remote side doesn't support the specified version, it will close its - // end of the message pipe asynchronously. This does nothing if it's already - // known that the remote side supports the specified version, i.e., if - // |version <= this->version()|. - // - // After calling RequireVersion() with a version not supported by the remote - // side, all subsequent calls to interface methods will be ignored. - void RequireVersion(uint32_t version) { - internal_state_.RequireVersion(version); - } - - // Sends a no-op message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Closes the bound message pipe (if any) and returns the pointer to the - // unbound state. - void reset() { - State doomed; - internal_state_.Swap(&doomed); - } - - // Similar to the method above, but also specifies a disconnect reason. - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (internal_state_.is_bound()) - internal_state_.CloseWithReason(custom_reason, description); - reset(); - } - - // Whether there are any associated interfaces running on the pipe currently. - bool HasAssociatedInterfaces() const { - return internal_state_.HasAssociatedInterfaces(); - } - - // Indicates whether the message pipe has encountered an error. If true, - // method calls made on this interface will be dropped (and may already have - // been dropped). - bool encountered_error() const { return internal_state_.encountered_error(); } - - // Registers a handler to receive error notifications. The handler will be - // called from the thread that owns this InterfacePtr. - // - // This method may only be called after the InterfacePtr has been bound to a - // message pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Unbinds the InterfacePtr and returns the information which could be used - // to setup an InterfacePtr again. This method may be used to move the proxy - // to a different thread (see class comments for details). - // - // It is an error to call PassInterface() while: - // - there are pending responses; or - // TODO: fix this restriction, it's not always obvious when there is a - // pending response. - // - there are associated interfaces running. - // TODO(yzshen): For now, users need to make sure there is no one holding - // on to associated interface endpoint handles at both sides of the - // message pipe in order to call this method. We need a way to forcefully - // invalidate associated interface endpoint handles. - InterfacePtrInfo<Interface> PassInterface() { - CHECK(!HasAssociatedInterfaces()); - CHECK(!internal_state_.has_pending_callbacks()); - State state; - internal_state_.Swap(&state); - - return state.PassInterface(); - } - - bool Equals(const InterfacePtr& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both null. - return !(*this) && !other; - } - - // DO NOT USE. Exposed only for internal use and for testing. - internal::InterfacePtrState<Interface>* internal_state() { - return &internal_state_; - } - - // Allow InterfacePtr<> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef internal::InterfacePtrState<Interface> InterfacePtr::*Testable; - - public: - operator Testable() const { - return internal_state_.is_bound() ? &InterfacePtr::internal_state_ - : nullptr; - } - - private: - // Forbid the == and != operators explicitly, otherwise InterfacePtr will be - // converted to Testable to do == or != comparison. - template <typename T> - bool operator==(const InterfacePtr<T>& other) const = delete; - template <typename T> - bool operator!=(const InterfacePtr<T>& other) const = delete; - - typedef internal::InterfacePtrState<Interface> State; - mutable State internal_state_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtr); -}; - -// If |info| is valid (containing a valid message pipe handle), returns an -// InterfacePtr bound to it. Otherwise, returns an unbound InterfacePtr. -template <typename Interface> -InterfacePtr<Interface> MakeProxy( - InterfacePtrInfo<Interface> info, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - InterfacePtr<Interface> ptr; - if (info.is_valid()) - ptr.Bind(std::move(info), std::move(runner)); - return std::move(ptr); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr_info.h b/mojo/public/cpp/bindings/interface_ptr_info.h deleted file mode 100644 index 0b2d808..0000000 --- a/mojo/public/cpp/bindings/interface_ptr_info.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ - -#include <stdint.h> -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// InterfacePtrInfo stores necessary information to communicate with a remote -// interface implementation, which could be used to construct an InterfacePtr. -template <typename Interface> -class InterfacePtrInfo { - public: - InterfacePtrInfo() : version_(0u) {} - - InterfacePtrInfo(ScopedMessagePipeHandle handle, uint32_t version) - : handle_(std::move(handle)), version_(version) {} - - InterfacePtrInfo(InterfacePtrInfo&& other) - : handle_(std::move(other.handle_)), version_(other.version_) { - other.version_ = 0u; - } - - ~InterfacePtrInfo() {} - - InterfacePtrInfo& operator=(InterfacePtrInfo&& other) { - if (this != &other) { - handle_ = std::move(other.handle_); - version_ = other.version_; - other.version_ = 0u; - } - - return *this; - } - - bool is_valid() const { return handle_.is_valid(); } - - ScopedMessagePipeHandle PassHandle() { return std::move(handle_); } - const ScopedMessagePipeHandle& handle() const { return handle_; } - void set_handle(ScopedMessagePipeHandle handle) { - handle_ = std::move(handle); - } - - uint32_t version() const { return version_; } - void set_version(uint32_t version) { version_ = version; } - - private: - ScopedMessagePipeHandle handle_; - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtrInfo); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr_set.h b/mojo/public/cpp/bindings/interface_ptr_set.h deleted file mode 100644 index 09a2682..0000000 --- a/mojo/public/cpp/bindings/interface_ptr_set.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ - -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" - -namespace mojo { -namespace internal { - -// TODO(blundell): This class should be rewritten to be structured -// similarly to BindingSet if possible, with PtrSet owning its -// Elements and those Elements calling back into PtrSet on connection -// error. -template <typename Interface, template <typename> class Ptr> -class PtrSet { - public: - PtrSet() {} - ~PtrSet() { CloseAll(); } - - void AddPtr(Ptr<Interface> ptr) { - auto weak_interface_ptr = new Element(std::move(ptr)); - ptrs_.push_back(weak_interface_ptr->GetWeakPtr()); - ClearNullPtrs(); - } - - template <typename FunctionType> - void ForAllPtrs(FunctionType function) { - for (const auto& it : ptrs_) { - if (it) - function(it->get()); - } - ClearNullPtrs(); - } - - void CloseAll() { - for (const auto& it : ptrs_) { - if (it) - it->Close(); - } - ptrs_.clear(); - } - - private: - class Element { - public: - explicit Element(Ptr<Interface> ptr) - : ptr_(std::move(ptr)), weak_ptr_factory_(this) { - ptr_.set_connection_error_handler(base::Bind(&DeleteElement, this)); - } - - ~Element() {} - - void Close() { - ptr_.reset(); - - // Resetting the interface ptr means that it won't call this object back - // on connection error anymore, so this object must delete itself now. - DeleteElement(this); - } - - Interface* get() { return ptr_.get(); } - - base::WeakPtr<Element> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - static void DeleteElement(Element* element) { delete element; } - - Ptr<Interface> ptr_; - base::WeakPtrFactory<Element> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(Element); - }; - - void ClearNullPtrs() { - ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(), - [](const base::WeakPtr<Element>& p) { - return p.get() == nullptr; - }), - ptrs_.end()); - } - - std::vector<base::WeakPtr<Element>> ptrs_; -}; - -} // namespace internal - -template <typename Interface> -using InterfacePtrSet = internal::PtrSet<Interface, InterfacePtr>; - -template <typename Interface> -using AssociatedInterfacePtrSet = - internal::PtrSet<Interface, AssociatedInterfacePtr>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ diff --git a/mojo/public/cpp/bindings/interface_request.h b/mojo/public/cpp/bindings/interface_request.h deleted file mode 100644 index 29d8836..0000000 --- a/mojo/public/cpp/bindings/interface_request.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ - -#include <string> -#include <utility> - -#include "base/macros.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// Represents a request from a remote client for an implementation of Interface -// over a specified message pipe. The implementor of the interface should -// remove the message pipe by calling PassMessagePipe() and bind it to the -// implementation. If this is not done, the InterfaceRequest will automatically -// close the pipe on destruction. Can also represent the absence of a request -// if the client did not provide a message pipe. -template <typename Interface> -class InterfaceRequest { - public: - // Constructs an empty InterfaceRequest, representing that the client is not - // requesting an implementation of Interface. - InterfaceRequest() {} - InterfaceRequest(decltype(nullptr)) {} - - // Creates a new message pipe over which Interface is to be served, binding - // the specified InterfacePtr to one end of the message pipe and this - // InterfaceRequest to the other. For example usage, see comments on - // MakeRequest(InterfacePtr*) below. - explicit InterfaceRequest(InterfacePtr<Interface>* ptr, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - MessagePipe pipe; - ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u), - std::move(runner)); - Bind(std::move(pipe.handle1)); - } - - // Takes the message pipe from another InterfaceRequest. - InterfaceRequest(InterfaceRequest&& other) { - handle_ = std::move(other.handle_); - } - InterfaceRequest& operator=(InterfaceRequest&& other) { - handle_ = std::move(other.handle_); - return *this; - } - - // Assigning to nullptr resets the InterfaceRequest to an empty state, - // closing the message pipe currently bound to it (if any). - InterfaceRequest& operator=(decltype(nullptr)) { - handle_.reset(); - return *this; - } - - // Binds the request to a message pipe over which Interface is to be - // requested. If the request is already bound to a message pipe, the current - // message pipe will be closed. - void Bind(ScopedMessagePipeHandle handle) { handle_ = std::move(handle); } - - // Indicates whether the request currently contains a valid message pipe. - bool is_pending() const { return handle_.is_valid(); } - - // Removes the message pipe from the request and returns it. - ScopedMessagePipeHandle PassMessagePipe() { return std::move(handle_); } - - bool Equals(const InterfaceRequest& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_pending() && !other.is_pending(); - } - - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (!handle_.is_valid()) - return; - - Message message = - PipeControlMessageProxy::ConstructPeerEndpointClosedMessage( - kMasterInterfaceId, DisconnectReason(custom_reason, description)); - MojoResult result = WriteMessageNew( - handle_.get(), message.TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE); - DCHECK_EQ(MOJO_RESULT_OK, result); - - handle_.reset(); - } - - private: - ScopedMessagePipeHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceRequest); -}; - -// Makes an InterfaceRequest bound to the specified message pipe. If |handle| -// is empty or invalid, the resulting InterfaceRequest will represent the -// absence of a request. -template <typename Interface> -InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) { - InterfaceRequest<Interface> request; - request.Bind(std::move(handle)); - return std::move(request); -} - -// Creates a new message pipe over which Interface is to be served. Binds the -// specified InterfacePtr to one end of the message pipe, and returns an -// InterfaceRequest bound to the other. The InterfacePtr should be passed to -// the client, and the InterfaceRequest should be passed to whatever will -// provide the implementation. The implementation should typically be bound to -// the InterfaceRequest using the Binding or StrongBinding classes. The client -// may begin to issue calls even before an implementation has been bound, since -// messages sent over the pipe will just queue up until they are consumed by -// the implementation. -// -// Example #1: Requesting a remote implementation of an interface. -// =============================================================== -// -// Given the following interface: -// -// interface Database { -// OpenTable(Table& table); -// } -// -// The client would have code similar to the following: -// -// DatabasePtr database = ...; // Connect to database. -// TablePtr table; -// database->OpenTable(MakeRequest(&table)); -// -// Upon return from MakeRequest, |table| is ready to have methods called on it. -// -// Example #2: Registering a local implementation with a remote service. -// ===================================================================== -// -// Given the following interface -// interface Collector { -// RegisterSource(Source source); -// } -// -// The client would have code similar to the following: -// -// CollectorPtr collector = ...; // Connect to Collector. -// SourcePtr source; -// InterfaceRequest<Source> source_request(&source); -// collector->RegisterSource(std::move(source)); -// CreateSource(std::move(source_request)); // Create implementation locally. -// -template <typename Interface> -InterfaceRequest<Interface> MakeRequest( - InterfacePtr<Interface>* ptr, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()) { - return InterfaceRequest<Interface>(ptr, runner); -} - -// Fuses an InterfaceRequest<T> endpoint with an InterfacePtrInfo<T> endpoint. -// Returns |true| on success or |false| on failure. -template <typename Interface> -bool FuseInterface(InterfaceRequest<Interface> request, - InterfacePtrInfo<Interface> proxy_info) { - MojoResult result = FuseMessagePipes(request.PassMessagePipe(), - proxy_info.PassHandle()); - return result == MOJO_RESULT_OK; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ diff --git a/mojo/public/cpp/bindings/lib/array_internal.cc b/mojo/public/cpp/bindings/lib/array_internal.cc deleted file mode 100644 index dd24eac..0000000 --- a/mojo/public/cpp/bindings/lib/array_internal.cc +++ /dev/null @@ -1,59 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/lib/array_internal.h" - -#include <stddef.h> -#include <stdint.h> - -#include <sstream> - -namespace mojo { -namespace internal { - -std::string MakeMessageWithArrayIndex(const char* message, - size_t size, - size_t index) { - std::ostringstream stream; - stream << message << ": array size - " << size << "; index - " << index; - return stream.str(); -} - -std::string MakeMessageWithExpectedArraySize(const char* message, - size_t size, - size_t expected_size) { - std::ostringstream stream; - stream << message << ": array size - " << size << "; expected size - " - << expected_size; - return stream.str(); -} - -ArrayDataTraits<bool>::BitRef::~BitRef() { -} - -ArrayDataTraits<bool>::BitRef::BitRef(uint8_t* storage, uint8_t mask) - : storage_(storage), mask_(mask) { -} - -ArrayDataTraits<bool>::BitRef& ArrayDataTraits<bool>::BitRef::operator=( - bool value) { - if (value) { - *storage_ |= mask_; - } else { - *storage_ &= ~mask_; - } - return *this; -} - -ArrayDataTraits<bool>::BitRef& ArrayDataTraits<bool>::BitRef::operator=( - const BitRef& value) { - return (*this) = static_cast<bool>(value); -} - -ArrayDataTraits<bool>::BitRef::operator bool() const { - return (*storage_ & mask_) != 0; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h deleted file mode 100644 index eecfcfb..0000000 --- a/mojo/public/cpp/bindings/lib/array_internal.h +++ /dev/null @@ -1,368 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <new> - -#include "base/logging.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace internal { - -template <typename K, typename V> -class Map_Data; - -MOJO_CPP_BINDINGS_EXPORT std::string -MakeMessageWithArrayIndex(const char* message, size_t size, size_t index); - -MOJO_CPP_BINDINGS_EXPORT std::string MakeMessageWithExpectedArraySize( - const char* message, - size_t size, - size_t expected_size); - -template <typename T> -struct ArrayDataTraits { - using StorageType = T; - using Ref = T&; - using ConstRef = const T&; - - static const uint32_t kMaxNumElements = - (std::numeric_limits<uint32_t>::max() - sizeof(ArrayHeader)) / - sizeof(StorageType); - - static uint32_t GetStorageSize(uint32_t num_elements) { - DCHECK(num_elements <= kMaxNumElements); - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; - } - static Ref ToRef(StorageType* storage, size_t offset) { - return storage[offset]; - } - static ConstRef ToConstRef(const StorageType* storage, size_t offset) { - return storage[offset]; - } -}; - -// Specialization of Arrays for bools, optimized for space. It has the -// following differences from a generalized Array: -// * Each element takes up a single bit of memory. -// * Accessing a non-const single element uses a helper class |BitRef|, which -// emulates a reference to a bool. -template <> -struct ArrayDataTraits<bool> { - // Helper class to emulate a reference to a bool, used for direct element - // access. - class MOJO_CPP_BINDINGS_EXPORT BitRef { - public: - ~BitRef(); - BitRef& operator=(bool value); - BitRef& operator=(const BitRef& value); - operator bool() const; - - private: - friend struct ArrayDataTraits<bool>; - BitRef(uint8_t* storage, uint8_t mask); - BitRef(); - uint8_t* storage_; - uint8_t mask_; - }; - - // Because each element consumes only 1/8 byte. - static const uint32_t kMaxNumElements = std::numeric_limits<uint32_t>::max(); - - using StorageType = uint8_t; - using Ref = BitRef; - using ConstRef = bool; - - static uint32_t GetStorageSize(uint32_t num_elements) { - return sizeof(ArrayHeader) + ((num_elements + 7) / 8); - } - static BitRef ToRef(StorageType* storage, size_t offset) { - return BitRef(&storage[offset / 8], 1 << (offset % 8)); - } - static bool ToConstRef(const StorageType* storage, size_t offset) { - return (storage[offset / 8] & (1 << (offset % 8))) != 0; - } -}; - -// What follows is code to support the serialization/validation of -// Array_Data<T>. There are four interesting cases: arrays of primitives, -// arrays of handles/interfaces, arrays of objects and arrays of unions. -// Arrays of objects are represented as arrays of pointers to objects. Arrays -// of unions are inlined so they are not pointers, but comparing with primitives -// they require more work for serialization/validation. -// -// TODO(yzshen): Validation code should be organzied in a way similar to -// Serializer<>, or merged into it. It should be templatized with the mojo -// data view type instead of the data type, that way we can use MojomTypeTraits -// to determine the categories. - -template <typename T, bool is_union, bool is_handle_or_interface> -struct ArraySerializationHelper; - -template <typename T> -struct ArraySerializationHelper<T, false, false> { - using ElementType = typename ArrayDataTraits<T>::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - if (!validate_params->validate_enum_func) - return true; - - // Enum validation. - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->validate_enum_func(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template <typename T> -struct ArraySerializationHelper<T, false, true> { - using ElementType = typename ArrayDataTraits<T>::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params->element_validate_params) - << "Handle or interface type should not have array validate params"; - - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && - !IsHandleOrInterfaceValid(elements[i])) { - static const ValidationError kError = - std::is_same<T, Interface_Data>::value || - std::is_same<T, Handle_Data>::value - ? VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE - : VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID; - ReportValidationError( - validation_context, kError, - MakeMessageWithArrayIndex( - "invalid handle or interface ID in array expecting valid " - "handles or interface IDs", - header->num_elements, i) - .c_str()); - return false; - } - if (!ValidateHandleOrInterface(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template <typename T> -struct ArraySerializationHelper<Pointer<T>, false, false> { - using ElementType = typename ArrayDataTraits<Pointer<T>>::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && !elements[i].offset) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid pointers", - header->num_elements, - i).c_str()); - return false; - } - if (!ValidateCaller<T>::Run(elements[i], validation_context, - validate_params->element_validate_params)) { - return false; - } - } - return true; - } - - private: - template <typename U, - bool is_array_or_map = IsSpecializationOf<Array_Data, U>::value || - IsSpecializationOf<Map_Data, U>::value> - struct ValidateCaller { - static bool Run(const Pointer<U>& data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params) - << "Struct type should not have array validate params"; - - return ValidateStruct(data, validation_context); - } - }; - - template <typename U> - struct ValidateCaller<U, true> { - static bool Run(const Pointer<U>& data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - return ValidateContainer(data, validation_context, validate_params); - } - }; -}; - -template <typename U> -struct ArraySerializationHelper<U, true, false> { - using ElementType = typename ArrayDataTraits<U>::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && elements[i].is_null()) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid unions", - header->num_elements, i) - .c_str()); - return false; - } - if (!ValidateInlinedUnion(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template <typename T> -class Array_Data { - public: - using Traits = ArrayDataTraits<T>; - using StorageType = typename Traits::StorageType; - using Ref = typename Traits::Ref; - using ConstRef = typename Traits::ConstRef; - using Helper = ArraySerializationHelper< - T, - IsUnionDataType<T>::value, - std::is_same<T, AssociatedInterface_Data>::value || - std::is_same<T, AssociatedEndpointHandle_Data>::value || - std::is_same<T, Interface_Data>::value || - std::is_same<T, Handle_Data>::value>; - using Element = T; - - // Returns null if |num_elements| or the corresponding storage size cannot be - // stored in uint32_t. - static Array_Data<T>* New(size_t num_elements, Buffer* buf) { - if (num_elements > Traits::kMaxNumElements) - return nullptr; - - uint32_t num_bytes = - Traits::GetStorageSize(static_cast<uint32_t>(num_elements)); - return new (buf->Allocate(num_bytes)) - Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements)); - } - - static bool Validate(const void* data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!data) - return true; - if (!IsAligned(data)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MISALIGNED_OBJECT); - return false; - } - if (!validation_context->IsValidRange(data, sizeof(ArrayHeader))) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - const ArrayHeader* header = static_cast<const ArrayHeader*>(data); - if (header->num_elements > Traits::kMaxNumElements || - header->num_bytes < Traits::GetStorageSize(header->num_elements)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); - return false; - } - if (validate_params->expected_num_elements != 0 && - header->num_elements != validate_params->expected_num_elements) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", - header->num_elements, - validate_params->expected_num_elements).c_str()); - return false; - } - if (!validation_context->ClaimMemory(data, header->num_bytes)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); - return Helper::ValidateElements(&object->header_, object->storage(), - validation_context, validate_params); - } - - size_t size() const { return header_.num_elements; } - - Ref at(size_t offset) { - DCHECK(offset < static_cast<size_t>(header_.num_elements)); - return Traits::ToRef(storage(), offset); - } - - ConstRef at(size_t offset) const { - DCHECK(offset < static_cast<size_t>(header_.num_elements)); - return Traits::ToConstRef(storage(), offset); - } - - StorageType* storage() { - return reinterpret_cast<StorageType*>(reinterpret_cast<char*>(this) + - sizeof(*this)); - } - - const StorageType* storage() const { - return reinterpret_cast<const StorageType*>( - reinterpret_cast<const char*>(this) + sizeof(*this)); - } - - private: - Array_Data(uint32_t num_bytes, uint32_t num_elements) { - header_.num_bytes = num_bytes; - header_.num_elements = num_elements; - } - ~Array_Data() = delete; - - internal::ArrayHeader header_; - - // Elements of type internal::ArrayDataTraits<T>::StorageType follow. -}; -static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)"); - -// UTF-8 encoded -using String_Data = Array_Data<char>; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h deleted file mode 100644 index d2f8ecf..0000000 --- a/mojo/public/cpp/bindings/lib/array_serialization.h +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ - -#include <stddef.h> -#include <string.h> // For |memcpy()|. - -#include <limits> -#include <type_traits> -#include <utility> -#include <vector> - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/array_data_view.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" - -namespace mojo { -namespace internal { - -template <typename Traits, - typename MaybeConstUserType, - bool HasGetBegin = - HasGetBeginMethod<Traits, MaybeConstUserType>::value> -class ArrayIterator {}; - -// Used as the UserTypeIterator template parameter of ArraySerializer. -template <typename Traits, typename MaybeConstUserType> -class ArrayIterator<Traits, MaybeConstUserType, true> { - public: - using IteratorType = decltype( - CallGetBeginIfExists<Traits>(std::declval<MaybeConstUserType&>())); - - explicit ArrayIterator(MaybeConstUserType& input) - : input_(input), iter_(CallGetBeginIfExists<Traits>(input)) {} - ~ArrayIterator() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - using GetNextResult = - decltype(Traits::GetValue(std::declval<IteratorType&>())); - GetNextResult GetNext() { - GetNextResult value = Traits::GetValue(iter_); - Traits::AdvanceIterator(iter_); - return value; - } - - using GetDataIfExistsResult = decltype( - CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>())); - GetDataIfExistsResult GetDataIfExists() { - return CallGetDataIfExists<Traits>(input_); - } - - private: - MaybeConstUserType& input_; - IteratorType iter_; -}; - -// Used as the UserTypeIterator template parameter of ArraySerializer. -template <typename Traits, typename MaybeConstUserType> -class ArrayIterator<Traits, MaybeConstUserType, false> { - public: - explicit ArrayIterator(MaybeConstUserType& input) : input_(input), iter_(0) {} - ~ArrayIterator() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - using GetNextResult = - decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0)); - GetNextResult GetNext() { - DCHECK_LT(iter_, Traits::GetSize(input_)); - return Traits::GetAt(input_, iter_++); - } - - using GetDataIfExistsResult = decltype( - CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>())); - GetDataIfExistsResult GetDataIfExists() { - return CallGetDataIfExists<Traits>(input_); - } - - private: - MaybeConstUserType& input_; - size_t iter_; -}; - -// ArraySerializer is also used to serialize map keys and values. Therefore, it -// has a UserTypeIterator parameter which is an adaptor for reading to hide the -// difference between ArrayTraits and MapTraits. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator, - typename EnableType = void> -struct ArraySerializer; - -// Handles serialization and deserialization of arrays of pod types. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if<BelongsTo<typename MojomType::Element, - MojomTypeCategory::POD>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Data = typename MojomTypeTraits<MojomType>::Data; - using DataElement = typename Data::Element; - using Element = typename MojomType::Element; - using Traits = ArrayTraits<UserType>; - - static_assert(std::is_same<Element, DataElement>::value, - "Incorrect array serializer"); - static_assert(std::is_same<Element, typename Traits::Element>::value, - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - if (size == 0) - return; - - auto data = input->GetDataIfExists(); - if (data) { - memcpy(output->storage(), data, size * sizeof(DataElement)); - } else { - for (size_t i = 0; i < size; ++i) - output->at(i) = input->GetNext(); - } - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - if (input->size()) { - auto data = iterator.GetDataIfExists(); - if (data) { - memcpy(data, input->storage(), input->size() * sizeof(DataElement)); - } else { - for (size_t i = 0; i < input->size(); ++i) - iterator.GetNext() = input->at(i); - } - } - return true; - } -}; - -// Handles serialization and deserialization of arrays of enum types. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if<BelongsTo<typename MojomType::Element, - MojomTypeCategory::ENUM>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Data = typename MojomTypeTraits<MojomType>::Data; - using DataElement = typename Data::Element; - using Element = typename MojomType::Element; - using Traits = ArrayTraits<UserType>; - - static_assert(sizeof(Element) == sizeof(DataElement), - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) - Serialize<Element>(input->GetNext(), output->storage() + i); - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize<Element>(input->at(i), &iterator.GetNext())) - return false; - } - return true; - } -}; - -// Serializes and deserializes arrays of bools. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer<MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if<BelongsTo< - typename MojomType::Element, - MojomTypeCategory::BOOLEAN>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = ArrayTraits<UserType>; - using Data = typename MojomTypeTraits<MojomType>::Data; - - static_assert(std::is_same<bool, typename Traits::Element>::value, - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align((input->GetSize() + 7) / 8); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) - output->at(i) = input->GetNext(); - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - for (size_t i = 0; i < input->size(); ++i) - iterator.GetNext() = input->at(i); - return true; - } -}; - -// Serializes and deserializes arrays of handles or interfaces. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if< - BelongsTo<typename MojomType::Element, - MojomTypeCategory::ASSOCIATED_INTERFACE | - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST | - MojomTypeCategory::HANDLE | - MojomTypeCategory::INTERFACE | - MojomTypeCategory::INTERFACE_REQUEST>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Data = typename MojomTypeTraits<MojomType>::Data; - using Element = typename MojomType::Element; - using Traits = ArrayTraits<UserType>; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - if (BelongsTo<Element, - MojomTypeCategory::ASSOCIATED_INTERFACE | - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST>::value) { - for (size_t i = 0; i < element_count; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size_t size = PrepareToSerialize<Element>(next, context); - DCHECK_EQ(size, 0u); - } - } - return sizeof(Data) + Align(element_count * sizeof(typename Data::Element)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_validate_params) - << "Handle or interface type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - Serialize<Element>(next, &output->at(i), context); - - static const ValidationError kError = - BelongsTo<Element, - MojomTypeCategory::ASSOCIATED_INTERFACE | - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST>::value - ? VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID - : VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE; - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && - !IsHandleOrInterfaceValid(output->at(i)), - kError, - MakeMessageWithArrayIndex("invalid handle or interface ID in array " - "expecting valid handles or interface IDs", - size, i)); - } - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - bool result = - Deserialize<Element>(&input->at(i), &iterator.GetNext(), context); - DCHECK(result); - } - return true; - } -}; - -// This template must only apply to pointer mojo entity (strings, structs, -// arrays and maps). -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer<MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if<BelongsTo< - typename MojomType::Element, - MojomTypeCategory::ARRAY | MojomTypeCategory::MAP | - MojomTypeCategory::STRING | - MojomTypeCategory::STRUCT>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Data = typename MojomTypeTraits<MojomType>::Data; - using Element = typename MojomType::Element; - using DataElementPtr = typename MojomTypeTraits<Element>::Data*; - using Traits = ArrayTraits<UserType>; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - size_t size = sizeof(Data) + element_count * sizeof(typename Data::Element); - for (size_t i = 0; i < element_count; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size += PrepareToSerialize<Element>(next, context); - } - return size; - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - DataElementPtr data_ptr; - typename UserTypeIterator::GetNextResult next = input->GetNext(); - SerializeCaller<Element>::Run(next, buf, &data_ptr, - validate_params->element_validate_params, - context); - output->at(i).Set(data_ptr); - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && !data_ptr, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid pointers", - size, i)); - } - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize<Element>(input->at(i).Get(), &iterator.GetNext(), - context)) - return false; - } - return true; - } - - private: - template <typename T, - bool is_array_or_map = BelongsTo<T, - MojomTypeCategory::ARRAY | - MojomTypeCategory::MAP>::value> - struct SerializeCaller { - template <typename InputElementType> - static void Run(InputElementType&& input, - Buffer* buf, - DataElementPtr* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - Serialize<T>(std::forward<InputElementType>(input), buf, output, context); - } - }; - - template <typename T> - struct SerializeCaller<T, true> { - template <typename InputElementType> - static void Run(InputElementType&& input, - Buffer* buf, - DataElementPtr* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - Serialize<T>(std::forward<InputElementType>(input), buf, output, - validate_params, context); - } - }; -}; - -// Handles serialization and deserialization of arrays of unions. -template <typename MojomType, - typename MaybeConstUserType, - typename UserTypeIterator> -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if<BelongsTo<typename MojomType::Element, - MojomTypeCategory::UNION>::value>::type> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Data = typename MojomTypeTraits<MojomType>::Data; - using Element = typename MojomType::Element; - using Traits = ArrayTraits<UserType>; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - size_t size = sizeof(Data); - for (size_t i = 0; i < element_count; ++i) { - // Call with |inlined| set to false, so that it will account for both the - // data in the union and the space in the array used to hold the union. - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size += PrepareToSerialize<Element>(next, false, context); - } - return size; - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - typename Data::Element* result = output->storage() + i; - typename UserTypeIterator::GetNextResult next = input->GetNext(); - Serialize<Element>(next, buf, &result, true, context); - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && output->at(i).is_null(), - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid unions", - size, i)); - } - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator<Traits, UserType> iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize<Element>(&input->at(i), &iterator.GetNext(), context)) - return false; - } - return true; - } -}; - -template <typename Element, typename MaybeConstUserType> -struct Serializer<ArrayDataView<Element>, MaybeConstUserType> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = ArrayTraits<UserType>; - using Impl = ArraySerializer<ArrayDataView<Element>, - MaybeConstUserType, - ArrayIterator<Traits, MaybeConstUserType>>; - using Data = typename MojomTypeTraits<ArrayDataView<Element>>::Data; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists<Traits>(input)) - return 0; - ArrayIterator<Traits, MaybeConstUserType> iterator(input); - return Impl::GetSerializedSize(&iterator, context); - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buf, - Data** output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - if (!CallIsNullIfExists<Traits>(input)) { - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - validate_params->expected_num_elements != 0 && - Traits::GetSize(input) != validate_params->expected_num_elements, - internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - internal::MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", - Traits::GetSize(input), validate_params->expected_num_elements)); - Data* result = Data::New(Traits::GetSize(input), buf); - if (result) { - ArrayIterator<Traits, MaybeConstUserType> iterator(input); - Impl::SerializeElements(&iterator, buf, result, validate_params, - context); - } - *output = result; - } else { - *output = nullptr; - } - } - - static bool Deserialize(Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists<Traits>(output); - return Impl::DeserializeElements(input, output, context); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/associated_binding.cc b/mojo/public/cpp/bindings/lib/associated_binding.cc deleted file mode 100644 index 6788e68..0000000 --- a/mojo/public/cpp/bindings/lib/associated_binding.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_binding.h" - -namespace mojo { - -AssociatedBindingBase::AssociatedBindingBase() {} - -AssociatedBindingBase::~AssociatedBindingBase() {} - -void AssociatedBindingBase::AddFilter(std::unique_ptr<MessageReceiver> filter) { - DCHECK(endpoint_client_); - endpoint_client_->AddFilter(std::move(filter)); -} - -void AssociatedBindingBase::Close() { - endpoint_client_.reset(); -} - -void AssociatedBindingBase::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - if (endpoint_client_) - endpoint_client_->CloseWithReason(custom_reason, description); - Close(); -} - -void AssociatedBindingBase::set_connection_error_handler( - const base::Closure& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_handler(error_handler); -} - -void AssociatedBindingBase::set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); -} - -void AssociatedBindingBase::FlushForTesting() { - endpoint_client_->FlushForTesting(); -} - -void AssociatedBindingBase::BindImpl( - ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr<MessageReceiver> payload_validator, - bool expect_sync_requests, - scoped_refptr<base::SingleThreadTaskRunner> runner, - uint32_t interface_version) { - if (!handle.is_valid()) { - endpoint_client_.reset(); - return; - } - - endpoint_client_.reset(new InterfaceEndpointClient( - std::move(handle), receiver, std::move(payload_validator), - expect_sync_requests, std::move(runner), interface_version)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_group.cc b/mojo/public/cpp/bindings/lib/associated_group.cc deleted file mode 100644 index 3e95eeb..0000000 --- a/mojo/public/cpp/bindings/lib/associated_group.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_group.h" - -#include "mojo/public/cpp/bindings/associated_group_controller.h" - -namespace mojo { - -AssociatedGroup::AssociatedGroup() = default; - -AssociatedGroup::AssociatedGroup( - scoped_refptr<AssociatedGroupController> controller) - : controller_(std::move(controller)) {} - -AssociatedGroup::AssociatedGroup(const ScopedInterfaceEndpointHandle& handle) - : controller_getter_(handle.CreateGroupControllerGetter()) {} - -AssociatedGroup::AssociatedGroup(const AssociatedGroup& other) = default; - -AssociatedGroup::~AssociatedGroup() = default; - -AssociatedGroup& AssociatedGroup::operator=(const AssociatedGroup& other) = - default; - -AssociatedGroupController* AssociatedGroup::GetController() { - if (controller_) - return controller_.get(); - - return controller_getter_.Run(); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_group_controller.cc b/mojo/public/cpp/bindings/lib/associated_group_controller.cc deleted file mode 100644 index f4a9aa2..0000000 --- a/mojo/public/cpp/bindings/lib/associated_group_controller.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_group_controller.h" - -#include "mojo/public/cpp/bindings/associated_group.h" - -namespace mojo { - -AssociatedGroupController::~AssociatedGroupController() {} - -ScopedInterfaceEndpointHandle -AssociatedGroupController::CreateScopedInterfaceEndpointHandle(InterfaceId id) { - return ScopedInterfaceEndpointHandle(id, this); -} - -bool AssociatedGroupController::NotifyAssociation( - ScopedInterfaceEndpointHandle* handle_to_send, - InterfaceId id) { - return handle_to_send->NotifyAssociation(id, this); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc b/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc deleted file mode 100644 index 78281ed..0000000 --- a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" - -namespace mojo { - -void GetIsolatedInterface(ScopedInterfaceEndpointHandle handle) { - MessagePipe pipe; - scoped_refptr<internal::MultiplexRouter> router = - new internal::MultiplexRouter(std::move(pipe.handle0), - internal::MultiplexRouter::MULTI_INTERFACE, - false, base::ThreadTaskRunnerHandle::Get()); - router->AssociateInterface(std::move(handle)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h deleted file mode 100644 index a4b5188..0000000 --- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ - -#include <stdint.h> - -#include <algorithm> // For |std::swap()|. -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { -namespace internal { - -template <typename Interface> -class AssociatedInterfacePtrState { - public: - AssociatedInterfacePtrState() : version_(0u) {} - - ~AssociatedInterfacePtrState() { - endpoint_client_.reset(); - proxy_.reset(); - } - - Interface* instance() { - // This will be null if the object is not bound. - return proxy_.get(); - } - - uint32_t version() const { return version_; } - - void QueryVersion(const base::Callback<void(uint32_t)>& callback) { - // It is safe to capture |this| because the callback won't be run after this - // object goes away. - endpoint_client_->QueryVersion( - base::Bind(&AssociatedInterfacePtrState::OnQueryVersion, - base::Unretained(this), callback)); - } - - void RequireVersion(uint32_t version) { - if (version <= version_) - return; - - version_ = version; - endpoint_client_->RequireVersion(version); - } - - void FlushForTesting() { endpoint_client_->FlushForTesting(); } - - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - endpoint_client_->CloseWithReason(custom_reason, description); - } - - void Swap(AssociatedInterfacePtrState* other) { - using std::swap; - swap(other->endpoint_client_, endpoint_client_); - swap(other->proxy_, proxy_); - swap(other->version_, version_); - } - - void Bind(AssociatedInterfacePtrInfo<Interface> info, - scoped_refptr<base::SingleThreadTaskRunner> runner) { - DCHECK(!endpoint_client_); - DCHECK(!proxy_); - DCHECK_EQ(0u, version_); - DCHECK(info.is_valid()); - - version_ = info.version(); - // The version is only queried from the client so the value passed here - // will not be used. - endpoint_client_.reset(new InterfaceEndpointClient( - info.PassHandle(), nullptr, - base::WrapUnique(new typename Interface::ResponseValidator_()), false, - std::move(runner), 0u)); - proxy_.reset(new Proxy(endpoint_client_.get())); - } - - // After this method is called, the object is in an invalid state and - // shouldn't be reused. - AssociatedInterfacePtrInfo<Interface> PassInterface() { - ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); - endpoint_client_.reset(); - proxy_.reset(); - return AssociatedInterfacePtrInfo<Interface>(std::move(handle), version_); - } - - bool is_bound() const { return !!endpoint_client_; } - - bool encountered_error() const { - return endpoint_client_ ? endpoint_client_->encountered_error() : false; - } - - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - // Returns true if bound and awaiting a response to a message. - bool has_pending_callbacks() const { - return endpoint_client_ && endpoint_client_->has_pending_responders(); - } - - AssociatedGroup* associated_group() { - return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; - } - - void ForwardMessage(Message message) { endpoint_client_->Accept(&message); } - - void ForwardMessageWithResponder(Message message, - std::unique_ptr<MessageReceiver> responder) { - endpoint_client_->AcceptWithResponder(&message, std::move(responder)); - } - - private: - using Proxy = typename Interface::Proxy_; - - void OnQueryVersion(const base::Callback<void(uint32_t)>& callback, - uint32_t version) { - version_ = version; - callback.Run(version); - } - - std::unique_ptr<InterfaceEndpointClient> endpoint_client_; - std::unique_ptr<Proxy> proxy_; - - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc deleted file mode 100644 index b34cb47..0000000 --- a/mojo/public/cpp/bindings/lib/binding_state.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/binding_state.h" - -namespace mojo { -namespace internal { - -BindingStateBase::BindingStateBase() = default; - -BindingStateBase::~BindingStateBase() = default; - -void BindingStateBase::AddFilter(std::unique_ptr<MessageReceiver> filter) { - DCHECK(endpoint_client_); - endpoint_client_->AddFilter(std::move(filter)); -} - -bool BindingStateBase::HasAssociatedInterfaces() const { - return router_ ? router_->HasAssociatedEndpoints() : false; -} - -void BindingStateBase::PauseIncomingMethodCallProcessing() { - DCHECK(router_); - router_->PauseIncomingMethodCallProcessing(); -} -void BindingStateBase::ResumeIncomingMethodCallProcessing() { - DCHECK(router_); - router_->ResumeIncomingMethodCallProcessing(); -} - -bool BindingStateBase::WaitForIncomingMethodCall(MojoDeadline deadline) { - DCHECK(router_); - return router_->WaitForIncomingMessage(deadline); -} - -void BindingStateBase::Close() { - if (!router_) - return; - - endpoint_client_.reset(); - router_->CloseMessagePipe(); - router_ = nullptr; -} - -void BindingStateBase::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - if (endpoint_client_) - endpoint_client_->CloseWithReason(custom_reason, description); - - Close(); -} - -void BindingStateBase::FlushForTesting() { - endpoint_client_->FlushForTesting(); -} - -void BindingStateBase::EnableTestingMode() { - DCHECK(is_bound()); - router_->EnableTestingMode(); -} - -void BindingStateBase::BindInternal( - ScopedMessagePipeHandle handle, - scoped_refptr<base::SingleThreadTaskRunner> runner, - const char* interface_name, - std::unique_ptr<MessageReceiver> request_validator, - bool passes_associated_kinds, - bool has_sync_methods, - MessageReceiverWithResponderStatus* stub, - uint32_t interface_version) { - DCHECK(!router_); - - MultiplexRouter::Config config = - passes_associated_kinds - ? MultiplexRouter::MULTI_INTERFACE - : (has_sync_methods - ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS - : MultiplexRouter::SINGLE_INTERFACE); - router_ = new MultiplexRouter(std::move(handle), config, false, runner); - router_->SetMasterInterfaceName(interface_name); - - endpoint_client_.reset(new InterfaceEndpointClient( - router_->CreateLocalEndpointHandle(kMasterInterfaceId), stub, - std::move(request_validator), has_sync_methods, std::move(runner), - interface_version)); -} - -} // namesapce internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h deleted file mode 100644 index 0b0dbee..0000000 --- a/mojo/public/cpp/bindings/lib/binding_state.h +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ - -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace internal { - -class MOJO_CPP_BINDINGS_EXPORT BindingStateBase { - public: - BindingStateBase(); - ~BindingStateBase(); - - void AddFilter(std::unique_ptr<MessageReceiver> filter); - - bool HasAssociatedInterfaces() const; - - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - bool WaitForIncomingMethodCall( - MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE); - - void Close(); - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - bool is_bound() const { return !!router_; } - - MessagePipeHandle handle() const { - DCHECK(is_bound()); - return router_->handle(); - } - - void FlushForTesting(); - - void EnableTestingMode(); - - protected: - void BindInternal(ScopedMessagePipeHandle handle, - scoped_refptr<base::SingleThreadTaskRunner> runner, - const char* interface_name, - std::unique_ptr<MessageReceiver> request_validator, - bool passes_associated_kinds, - bool has_sync_methods, - MessageReceiverWithResponderStatus* stub, - uint32_t interface_version); - - scoped_refptr<internal::MultiplexRouter> router_; - std::unique_ptr<InterfaceEndpointClient> endpoint_client_; -}; - -template <typename Interface, typename ImplRefTraits> -class BindingState : public BindingStateBase { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - explicit BindingState(ImplPointerType impl) { - stub_.set_sink(std::move(impl)); - } - - ~BindingState() { Close(); } - - void Bind(ScopedMessagePipeHandle handle, - scoped_refptr<base::SingleThreadTaskRunner> runner) { - BindingStateBase::BindInternal( - std::move(handle), runner, Interface::Name_, - base::MakeUnique<typename Interface::RequestValidator_>(), - Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_, &stub_, - Interface::Version_); - } - - InterfaceRequest<Interface> Unbind() { - endpoint_client_.reset(); - InterfaceRequest<Interface> request = - MakeRequest<Interface>(router_->PassMessagePipe()); - router_ = nullptr; - return request; - } - - Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); } - - private: - typename Interface::template Stub_<ImplRefTraits> stub_; - - DISALLOW_COPY_AND_ASSIGN(BindingState); -}; - -} // namesapce internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h deleted file mode 100644 index 631daec..0000000 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ /dev/null @@ -1,336 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ - -#include <stdint.h> - -#include <functional> - -#include "base/template_util.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -template <typename T> -class ArrayDataView; - -template <typename T> -class AssociatedInterfacePtrInfoDataView; - -template <typename T> -class AssociatedInterfaceRequestDataView; - -template <typename T> -class InterfacePtrDataView; - -template <typename T> -class InterfaceRequestDataView; - -template <typename K, typename V> -class MapDataView; - -class NativeStructDataView; - -class StringDataView; - -namespace internal { - -// Please note that this is a different value than |mojo::kInvalidHandleValue|, -// which is the "decoded" invalid handle. -const uint32_t kEncodedInvalidHandleValue = static_cast<uint32_t>(-1); - -// A serialized union always takes 16 bytes: -// 4-byte size + 4-byte tag + 8-byte payload. -const uint32_t kUnionDataSize = 16; - -template <typename T> -class Array_Data; - -template <typename K, typename V> -class Map_Data; - -class NativeStruct_Data; - -using String_Data = Array_Data<char>; - -inline size_t Align(size_t size) { - return (size + 7) & ~0x7; -} - -inline bool IsAligned(const void* ptr) { - return !(reinterpret_cast<uintptr_t>(ptr) & 0x7); -} - -// Pointers are encoded as relative offsets. The offsets are relative to the -// address of where the offset value is stored, such that the pointer may be -// recovered with the expression: -// -// ptr = reinterpret_cast<char*>(offset) + *offset -// -// A null pointer is encoded as an offset value of 0. -// -inline void EncodePointer(const void* ptr, uint64_t* offset) { - if (!ptr) { - *offset = 0; - return; - } - - const char* p_obj = reinterpret_cast<const char*>(ptr); - const char* p_slot = reinterpret_cast<const char*>(offset); - DCHECK(p_obj > p_slot); - - *offset = static_cast<uint64_t>(p_obj - p_slot); -} - -// Note: This function doesn't validate the encoded pointer value. -inline const void* DecodePointer(const uint64_t* offset) { - if (!*offset) - return nullptr; - return reinterpret_cast<const char*>(offset) + *offset; -} - -#pragma pack(push, 1) - -struct StructHeader { - uint32_t num_bytes; - uint32_t version; -}; -static_assert(sizeof(StructHeader) == 8, "Bad sizeof(StructHeader)"); - -struct ArrayHeader { - uint32_t num_bytes; - uint32_t num_elements; -}; -static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)"); - -template <typename T> -struct Pointer { - using BaseType = T; - - void Set(T* ptr) { EncodePointer(ptr, &offset); } - const T* Get() const { return static_cast<const T*>(DecodePointer(&offset)); } - T* Get() { - return static_cast<T*>(const_cast<void*>(DecodePointer(&offset))); - } - - bool is_null() const { return offset == 0; } - - uint64_t offset; -}; -static_assert(sizeof(Pointer<char>) == 8, "Bad_sizeof(Pointer)"); - -using GenericPointer = Pointer<void>; - -struct Handle_Data { - Handle_Data() = default; - explicit Handle_Data(uint32_t value) : value(value) {} - - bool is_valid() const { return value != kEncodedInvalidHandleValue; } - - uint32_t value; -}; -static_assert(sizeof(Handle_Data) == 4, "Bad_sizeof(Handle_Data)"); - -struct Interface_Data { - Handle_Data handle; - uint32_t version; -}; -static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)"); - -struct AssociatedEndpointHandle_Data { - AssociatedEndpointHandle_Data() = default; - explicit AssociatedEndpointHandle_Data(uint32_t value) : value(value) {} - - bool is_valid() const { return value != kEncodedInvalidHandleValue; } - - uint32_t value; -}; -static_assert(sizeof(AssociatedEndpointHandle_Data) == 4, - "Bad_sizeof(AssociatedEndpointHandle_Data)"); - -struct AssociatedInterface_Data { - AssociatedEndpointHandle_Data handle; - uint32_t version; -}; -static_assert(sizeof(AssociatedInterface_Data) == 8, - "Bad_sizeof(AssociatedInterface_Data)"); - -#pragma pack(pop) - -template <typename T> -T FetchAndReset(T* ptr) { - T temp = *ptr; - *ptr = T(); - return temp; -} - -template <typename T> -struct IsUnionDataType { - private: - template <typename U> - static YesType Test(const typename U::MojomUnionDataType*); - - template <typename U> - static NoType Test(...); - - EnsureTypeIsComplete<T> check_t_; - - public: - static const bool value = - sizeof(Test<T>(0)) == sizeof(YesType) && !IsConst<T>::value; -}; - -enum class MojomTypeCategory : uint32_t { - ARRAY = 1 << 0, - ASSOCIATED_INTERFACE = 1 << 1, - ASSOCIATED_INTERFACE_REQUEST = 1 << 2, - BOOLEAN = 1 << 3, - ENUM = 1 << 4, - HANDLE = 1 << 5, - INTERFACE = 1 << 6, - INTERFACE_REQUEST = 1 << 7, - MAP = 1 << 8, - // POD except boolean and enum. - POD = 1 << 9, - STRING = 1 << 10, - STRUCT = 1 << 11, - UNION = 1 << 12 -}; - -inline constexpr MojomTypeCategory operator&(MojomTypeCategory x, - MojomTypeCategory y) { - return static_cast<MojomTypeCategory>(static_cast<uint32_t>(x) & - static_cast<uint32_t>(y)); -} - -inline constexpr MojomTypeCategory operator|(MojomTypeCategory x, - MojomTypeCategory y) { - return static_cast<MojomTypeCategory>(static_cast<uint32_t>(x) | - static_cast<uint32_t>(y)); -} - -template <typename T, bool is_enum = std::is_enum<T>::value> -struct MojomTypeTraits { - using Data = T; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::POD; -}; - -template <typename T> -struct MojomTypeTraits<ArrayDataView<T>, false> { - using Data = Array_Data<typename MojomTypeTraits<T>::DataAsArrayElement>; - using DataAsArrayElement = Pointer<Data>; - - static const MojomTypeCategory category = MojomTypeCategory::ARRAY; -}; - -template <typename T> -struct MojomTypeTraits<AssociatedInterfacePtrInfoDataView<T>, false> { - using Data = AssociatedInterface_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::ASSOCIATED_INTERFACE; -}; - -template <typename T> -struct MojomTypeTraits<AssociatedInterfaceRequestDataView<T>, false> { - using Data = AssociatedEndpointHandle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST; -}; - -template <> -struct MojomTypeTraits<bool, false> { - using Data = bool; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::BOOLEAN; -}; - -template <typename T> -struct MojomTypeTraits<T, true> { - using Data = int32_t; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::ENUM; -}; - -template <typename T> -struct MojomTypeTraits<ScopedHandleBase<T>, false> { - using Data = Handle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::HANDLE; -}; - -template <typename T> -struct MojomTypeTraits<InterfacePtrDataView<T>, false> { - using Data = Interface_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::INTERFACE; -}; - -template <typename T> -struct MojomTypeTraits<InterfaceRequestDataView<T>, false> { - using Data = Handle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::INTERFACE_REQUEST; -}; - -template <typename K, typename V> -struct MojomTypeTraits<MapDataView<K, V>, false> { - using Data = Map_Data<typename MojomTypeTraits<K>::DataAsArrayElement, - typename MojomTypeTraits<V>::DataAsArrayElement>; - using DataAsArrayElement = Pointer<Data>; - - static const MojomTypeCategory category = MojomTypeCategory::MAP; -}; - -template <> -struct MojomTypeTraits<NativeStructDataView, false> { - using Data = internal::NativeStruct_Data; - using DataAsArrayElement = Pointer<Data>; - - static const MojomTypeCategory category = MojomTypeCategory::STRUCT; -}; - -template <> -struct MojomTypeTraits<StringDataView, false> { - using Data = String_Data; - using DataAsArrayElement = Pointer<Data>; - - static const MojomTypeCategory category = MojomTypeCategory::STRING; -}; - -template <typename T, MojomTypeCategory categories> -struct BelongsTo { - static const bool value = - static_cast<uint32_t>(MojomTypeTraits<T>::category & categories) != 0; -}; - -template <typename T> -struct EnumHashImpl { - static_assert(std::is_enum<T>::value, "Incorrect hash function."); - - size_t operator()(T input) const { - using UnderlyingType = typename base::underlying_type<T>::type; - return std::hash<UnderlyingType>()(static_cast<UnderlyingType>(input)); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h deleted file mode 100644 index 213a445..0000000 --- a/mojo/public/cpp/bindings/lib/buffer.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" - -namespace mojo { -namespace internal { - -// Buffer provides an interface to allocate memory blocks which are 8-byte -// aligned and zero-initialized. It doesn't own the underlying memory. Users -// must ensure that the memory stays valid while using the allocated blocks from -// Buffer. -class Buffer { - public: - Buffer() {} - - // The memory must have been zero-initialized. |data| must be 8-byte - // aligned. - void Initialize(void* data, size_t size) { - DCHECK(IsAligned(data)); - - data_ = data; - size_ = size; - cursor_ = reinterpret_cast<uintptr_t>(data); - data_end_ = cursor_ + size; - } - - size_t size() const { return size_; } - - void* data() const { return data_; } - - // Allocates |num_bytes| from the buffer and returns a pointer to the start of - // the allocated block. - // The resulting address is 8-byte aligned, and the content of the memory is - // zero-filled. - void* Allocate(size_t num_bytes) { - num_bytes = Align(num_bytes); - uintptr_t result = cursor_; - cursor_ += num_bytes; - if (cursor_ > data_end_ || cursor_ < result) { - NOTREACHED(); - cursor_ -= num_bytes; - return nullptr; - } - - return reinterpret_cast<void*>(result); - } - - private: - void* data_ = nullptr; - size_t size_ = 0; - - uintptr_t cursor_ = 0; - uintptr_t data_end_ = 0; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc deleted file mode 100644 index d93e45e..0000000 --- a/mojo/public/cpp/bindings/lib/connector.cc +++ /dev/null @@ -1,493 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/connector.h" - -#include <stdint.h> -#include <utility> - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_local.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" -#include "mojo/public/cpp/system/wait.h" - -namespace mojo { - -namespace { - -// The NestingObserver for each thread. Note that this is always a -// Connector::MessageLoopNestingObserver; we use the base type here because that -// subclass is private to Connector. -base::LazyInstance< - base::ThreadLocalPointer<base::MessageLoop::NestingObserver>>::Leaky - g_tls_nesting_observer = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// Used to efficiently maintain a doubly-linked list of all Connectors -// currently dispatching on any given thread. -class Connector::ActiveDispatchTracker { - public: - explicit ActiveDispatchTracker(const base::WeakPtr<Connector>& connector); - ~ActiveDispatchTracker(); - - void NotifyBeginNesting(); - - private: - const base::WeakPtr<Connector> connector_; - MessageLoopNestingObserver* const nesting_observer_; - ActiveDispatchTracker* outer_tracker_ = nullptr; - ActiveDispatchTracker* inner_tracker_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(ActiveDispatchTracker); -}; - -// Watches the MessageLoop on the current thread. Notifies the current chain of -// ActiveDispatchTrackers when a nested message loop is started. -class Connector::MessageLoopNestingObserver - : public base::MessageLoop::NestingObserver, - public base::MessageLoop::DestructionObserver { - public: - MessageLoopNestingObserver() { - base::MessageLoop::current()->AddNestingObserver(this); - base::MessageLoop::current()->AddDestructionObserver(this); - } - - ~MessageLoopNestingObserver() override {} - - // base::MessageLoop::NestingObserver: - void OnBeginNestedMessageLoop() override { - if (top_tracker_) - top_tracker_->NotifyBeginNesting(); - } - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - base::MessageLoop::current()->RemoveNestingObserver(this); - base::MessageLoop::current()->RemoveDestructionObserver(this); - DCHECK_EQ(this, g_tls_nesting_observer.Get().Get()); - g_tls_nesting_observer.Get().Set(nullptr); - delete this; - } - - static MessageLoopNestingObserver* GetForThread() { - if (!base::MessageLoop::current() || - !base::MessageLoop::current()->nesting_allowed()) - return nullptr; - auto* observer = static_cast<MessageLoopNestingObserver*>( - g_tls_nesting_observer.Get().Get()); - if (!observer) { - observer = new MessageLoopNestingObserver; - g_tls_nesting_observer.Get().Set(observer); - } - return observer; - } - - private: - friend class ActiveDispatchTracker; - - ActiveDispatchTracker* top_tracker_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(MessageLoopNestingObserver); -}; - -Connector::ActiveDispatchTracker::ActiveDispatchTracker( - const base::WeakPtr<Connector>& connector) - : connector_(connector), nesting_observer_(connector_->nesting_observer_) { - DCHECK(nesting_observer_); - if (nesting_observer_->top_tracker_) { - outer_tracker_ = nesting_observer_->top_tracker_; - outer_tracker_->inner_tracker_ = this; - } - nesting_observer_->top_tracker_ = this; -} - -Connector::ActiveDispatchTracker::~ActiveDispatchTracker() { - if (nesting_observer_->top_tracker_ == this) - nesting_observer_->top_tracker_ = outer_tracker_; - else if (inner_tracker_) - inner_tracker_->outer_tracker_ = outer_tracker_; - if (outer_tracker_) - outer_tracker_->inner_tracker_ = inner_tracker_; -} - -void Connector::ActiveDispatchTracker::NotifyBeginNesting() { - if (connector_ && connector_->handle_watcher_) - connector_->handle_watcher_->ArmOrNotify(); - if (outer_tracker_) - outer_tracker_->NotifyBeginNesting(); -} - -Connector::Connector(ScopedMessagePipeHandle message_pipe, - ConnectorConfig config, - scoped_refptr<base::SingleThreadTaskRunner> runner) - : message_pipe_(std::move(message_pipe)), - task_runner_(std::move(runner)), - nesting_observer_(MessageLoopNestingObserver::GetForThread()), - weak_factory_(this) { - if (config == MULTI_THREADED_SEND) - lock_.emplace(); - - weak_self_ = weak_factory_.GetWeakPtr(); - // Even though we don't have an incoming receiver, we still want to monitor - // the message pipe to know if is closed or encounters an error. - WaitToReadMore(); -} - -Connector::~Connector() { - { - // Allow for quick destruction on any thread if the pipe is already closed. - base::AutoLock lock(connected_lock_); - if (!connected_) - return; - } - - DCHECK(thread_checker_.CalledOnValidThread()); - CancelWait(); -} - -void Connector::CloseMessagePipe() { - // Throw away the returned message pipe. - PassMessagePipe(); -} - -ScopedMessagePipeHandle Connector::PassMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - - CancelWait(); - internal::MayAutoLock locker(&lock_); - ScopedMessagePipeHandle message_pipe = std::move(message_pipe_); - weak_factory_.InvalidateWeakPtrs(); - sync_handle_watcher_callback_count_ = 0; - - base::AutoLock lock(connected_lock_); - connected_ = false; - return message_pipe; -} - -void Connector::RaiseError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - HandleError(true, true); -} - -bool Connector::WaitForIncomingMessage(MojoDeadline deadline) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (error_) - return false; - - ResumeIncomingMethodCallProcessing(); - - // TODO(rockot): Use a timed Wait here. Nobody uses anything but 0 or - // INDEFINITE deadlines at present, so we only support those. - DCHECK(deadline == 0 || deadline == MOJO_DEADLINE_INDEFINITE); - - MojoResult rv = MOJO_RESULT_UNKNOWN; - if (deadline == 0 && !message_pipe_->QuerySignalsState().readable()) - return false; - - if (deadline == MOJO_DEADLINE_INDEFINITE) { - rv = Wait(message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE); - if (rv != MOJO_RESULT_OK) { - // Users that call WaitForIncomingMessage() should expect their code to be - // re-entered, so we call the error handler synchronously. - HandleError(rv != MOJO_RESULT_FAILED_PRECONDITION, false); - return false; - } - } - - ignore_result(ReadSingleMessage(&rv)); - return (rv == MOJO_RESULT_OK); -} - -void Connector::PauseIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (paused_) - return; - - paused_ = true; - CancelWait(); -} - -void Connector::ResumeIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!paused_) - return; - - paused_ = false; - WaitToReadMore(); -} - -bool Connector::Accept(Message* message) { - DCHECK(lock_ || thread_checker_.CalledOnValidThread()); - - // It shouldn't hurt even if |error_| may be changed by a different thread at - // the same time. The outcome is that we may write into |message_pipe_| after - // encountering an error, which should be fine. - if (error_) - return false; - - internal::MayAutoLock locker(&lock_); - - if (!message_pipe_.is_valid() || drop_writes_) - return true; - - MojoResult rv = - WriteMessageNew(message_pipe_.get(), message->TakeMojoMessage(), - MOJO_WRITE_MESSAGE_FLAG_NONE); - - switch (rv) { - case MOJO_RESULT_OK: - break; - case MOJO_RESULT_FAILED_PRECONDITION: - // There's no point in continuing to write to this pipe since the other - // end is gone. Avoid writing any future messages. Hide write failures - // from the caller since we'd like them to continue consuming any backlog - // of incoming messages before regarding the message pipe as closed. - drop_writes_ = true; - break; - case MOJO_RESULT_BUSY: - // We'd get a "busy" result if one of the message's handles is: - // - |message_pipe_|'s own handle; - // - simultaneously being used on another thread; or - // - in a "busy" state that prohibits it from being transferred (e.g., - // a data pipe handle in the middle of a two-phase read/write, - // regardless of which thread that two-phase read/write is happening - // on). - // TODO(vtl): I wonder if this should be a |DCHECK()|. (But, until - // crbug.com/389666, etc. are resolved, this will make tests fail quickly - // rather than hanging.) - CHECK(false) << "Race condition or other bug detected"; - return false; - default: - // This particular write was rejected, presumably because of bad input. - // The pipe is not necessarily in a bad state. - return false; - } - return true; -} - -void Connector::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - - allow_woken_up_by_others_ = true; - - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); -} - -bool Connector::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (error_) - return false; - - ResumeIncomingMethodCallProcessing(); - - EnsureSyncWatcherExists(); - return sync_watcher_->SyncWatch(should_stop); -} - -void Connector::SetWatcherHeapProfilerTag(const char* tag) { - heap_profiler_tag_ = tag; - if (handle_watcher_) { - handle_watcher_->set_heap_profiler_tag(tag); - } -} - -void Connector::OnWatcherHandleReady(MojoResult result) { - OnHandleReadyInternal(result); -} - -void Connector::OnSyncHandleWatcherHandleReady(MojoResult result) { - base::WeakPtr<Connector> weak_self(weak_self_); - - sync_handle_watcher_callback_count_++; - OnHandleReadyInternal(result); - // At this point, this object might have been deleted. - if (weak_self) { - DCHECK_LT(0u, sync_handle_watcher_callback_count_); - sync_handle_watcher_callback_count_--; - } -} - -void Connector::OnHandleReadyInternal(MojoResult result) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (result != MOJO_RESULT_OK) { - HandleError(result != MOJO_RESULT_FAILED_PRECONDITION, false); - return; - } - - ReadAllAvailableMessages(); - // At this point, this object might have been deleted. Return. -} - -void Connector::WaitToReadMore() { - CHECK(!paused_); - DCHECK(!handle_watcher_); - - handle_watcher_.reset(new SimpleWatcher( - FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL, task_runner_)); - if (heap_profiler_tag_) - handle_watcher_->set_heap_profiler_tag(heap_profiler_tag_); - MojoResult rv = handle_watcher_->Watch( - message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&Connector::OnWatcherHandleReady, base::Unretained(this))); - - if (rv != MOJO_RESULT_OK) { - // If the watch failed because the handle is invalid or its conditions can - // no longer be met, we signal the error asynchronously to avoid reentry. - task_runner_->PostTask( - FROM_HERE, - base::Bind(&Connector::OnWatcherHandleReady, weak_self_, rv)); - } else { - handle_watcher_->ArmOrNotify(); - } - - if (allow_woken_up_by_others_) { - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); - } -} - -bool Connector::ReadSingleMessage(MojoResult* read_result) { - CHECK(!paused_); - - bool receiver_result = false; - - // Detect if |this| was destroyed or the message pipe was closed/transferred - // during message dispatch. - base::WeakPtr<Connector> weak_self = weak_self_; - - Message message; - const MojoResult rv = ReadMessage(message_pipe_.get(), &message); - *read_result = rv; - - if (rv == MOJO_RESULT_OK) { - base::Optional<ActiveDispatchTracker> dispatch_tracker; - if (!is_dispatching_ && nesting_observer_) { - is_dispatching_ = true; - dispatch_tracker.emplace(weak_self); - } - - receiver_result = - incoming_receiver_ && incoming_receiver_->Accept(&message); - - if (!weak_self) - return false; - - if (dispatch_tracker) { - is_dispatching_ = false; - dispatch_tracker.reset(); - } - } else if (rv == MOJO_RESULT_SHOULD_WAIT) { - return true; - } else { - HandleError(rv != MOJO_RESULT_FAILED_PRECONDITION, false); - return false; - } - - if (enforce_errors_from_incoming_receiver_ && !receiver_result) { - HandleError(true, false); - return false; - } - return true; -} - -void Connector::ReadAllAvailableMessages() { - while (!error_) { - base::WeakPtr<Connector> weak_self = weak_self_; - MojoResult rv; - - // May delete |this.| - if (!ReadSingleMessage(&rv)) - return; - - if (!weak_self || paused_) - return; - - DCHECK(rv == MOJO_RESULT_OK || rv == MOJO_RESULT_SHOULD_WAIT); - - if (rv == MOJO_RESULT_SHOULD_WAIT) { - // Attempt to re-arm the Watcher. - MojoResult ready_result; - MojoResult arm_result = handle_watcher_->Arm(&ready_result); - if (arm_result == MOJO_RESULT_OK) - return; - - // The watcher is already ready to notify again. - DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, arm_result); - - if (ready_result == MOJO_RESULT_FAILED_PRECONDITION) { - HandleError(false, false); - return; - } - - // There's more to read now, so we'll just keep looping. - DCHECK_EQ(MOJO_RESULT_OK, ready_result); - } - } -} - -void Connector::CancelWait() { - handle_watcher_.reset(); - sync_watcher_.reset(); -} - -void Connector::HandleError(bool force_pipe_reset, bool force_async_handler) { - if (error_ || !message_pipe_.is_valid()) - return; - - if (paused_) { - // Enforce calling the error handler asynchronously if the user has paused - // receiving messages. We need to wait until the user starts receiving - // messages again. - force_async_handler = true; - } - - if (!force_pipe_reset && force_async_handler) - force_pipe_reset = true; - - if (force_pipe_reset) { - CancelWait(); - internal::MayAutoLock locker(&lock_); - message_pipe_.reset(); - MessagePipe dummy_pipe; - message_pipe_ = std::move(dummy_pipe.handle0); - } else { - CancelWait(); - } - - if (force_async_handler) { - if (!paused_) - WaitToReadMore(); - } else { - error_ = true; - if (!connection_error_handler_.is_null()) - connection_error_handler_.Run(); - } -} - -void Connector::EnsureSyncWatcherExists() { - if (sync_watcher_) - return; - sync_watcher_.reset(new SyncHandleWatcher( - message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&Connector::OnSyncHandleWatcherHandleReady, - base::Unretained(this)))); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc deleted file mode 100644 index 1b7bb78..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/control_message_handler.h" - -#include <stddef.h> -#include <stdint.h> -#include <utility> - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" - -namespace mojo { -namespace internal { -namespace { - -bool ValidateControlRequestWithResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlRequestValidator"); - if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunMessageId: - return ValidateMessagePayload< - interface_control::internal::RunMessageParams_Data>( - message, &validation_context); - } - return false; -} - -bool ValidateControlRequestWithoutResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlRequestValidator"); - if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunOrClosePipeMessageId: - return ValidateMessageIsRequestWithoutResponse(message, - &validation_context) && - ValidateMessagePayload< - interface_control::internal::RunOrClosePipeMessageParams_Data>( - message, &validation_context); - } - return false; -} - -} // namespace - -// static -bool ControlMessageHandler::IsControlMessage(const Message* message) { - return message->header()->name == interface_control::kRunMessageId || - message->header()->name == interface_control::kRunOrClosePipeMessageId; -} - -ControlMessageHandler::ControlMessageHandler(uint32_t interface_version) - : interface_version_(interface_version) { -} - -ControlMessageHandler::~ControlMessageHandler() { -} - -bool ControlMessageHandler::Accept(Message* message) { - if (!ValidateControlRequestWithoutResponse(message)) - return false; - - if (message->header()->name == interface_control::kRunOrClosePipeMessageId) - return RunOrClosePipe(message); - - NOTREACHED(); - return false; -} - -bool ControlMessageHandler::AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) { - if (!ValidateControlRequestWithResponse(message)) - return false; - - if (message->header()->name == interface_control::kRunMessageId) - return Run(message, std::move(responder)); - - NOTREACHED(); - return false; -} - -bool ControlMessageHandler::Run( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) { - interface_control::internal::RunMessageParams_Data* params = - reinterpret_cast<interface_control::internal::RunMessageParams_Data*>( - message->mutable_payload()); - interface_control::RunMessageParamsPtr params_ptr; - Deserialize<interface_control::RunMessageParamsDataView>(params, ¶ms_ptr, - &context_); - auto& input = *params_ptr->input; - interface_control::RunOutputPtr output = interface_control::RunOutput::New(); - if (input.is_query_version()) { - output->set_query_version_result( - interface_control::QueryVersionResult::New()); - output->get_query_version_result()->version = interface_version_; - } else if (input.is_flush_for_testing()) { - output.reset(); - } else { - output.reset(); - } - - auto response_params_ptr = interface_control::RunResponseMessageParams::New(); - response_params_ptr->output = std::move(output); - size_t size = - PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>( - response_params_ptr, &context_); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagIsResponse, size, 0); - builder.message()->set_request_id(message->request_id()); - - interface_control::internal::RunResponseMessageParams_Data* response_params = - nullptr; - Serialize<interface_control::RunResponseMessageParamsDataView>( - response_params_ptr, builder.buffer(), &response_params, &context_); - ignore_result(responder->Accept(builder.message())); - - return true; -} - -bool ControlMessageHandler::RunOrClosePipe(Message* message) { - interface_control::internal::RunOrClosePipeMessageParams_Data* params = - reinterpret_cast< - interface_control::internal::RunOrClosePipeMessageParams_Data*>( - message->mutable_payload()); - interface_control::RunOrClosePipeMessageParamsPtr params_ptr; - Deserialize<interface_control::RunOrClosePipeMessageParamsDataView>( - params, ¶ms_ptr, &context_); - auto& input = *params_ptr->input; - if (input.is_require_version()) - return interface_version_ >= input.get_require_version()->version; - - return false; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.h b/mojo/public/cpp/bindings/lib/control_message_handler.h deleted file mode 100644 index 5d1f716..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_handler.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace internal { - -// Handlers for request messages defined in interface_control_messages.mojom. -class MOJO_CPP_BINDINGS_EXPORT ControlMessageHandler - : NON_EXPORTED_BASE(public MessageReceiverWithResponderStatus) { - public: - static bool IsControlMessage(const Message* message); - - explicit ControlMessageHandler(uint32_t interface_version); - ~ControlMessageHandler() override; - - // Call the following methods only if IsControlMessage() returned true. - bool Accept(Message* message) override; - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) override; - - private: - bool Run(Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder); - bool RunOrClosePipe(Message* message); - - uint32_t interface_version_; - SerializationContext context_; - - DISALLOW_COPY_AND_ASSIGN(ControlMessageHandler); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc deleted file mode 100644 index d082b49..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/control_message_proxy.h" - -#include <stddef.h> -#include <stdint.h> -#include <utility> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" - -namespace mojo { -namespace internal { - -namespace { - -bool ValidateControlResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlResponseValidator"); - if (!ValidateMessageIsResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunMessageId: - return ValidateMessagePayload< - interface_control::internal::RunResponseMessageParams_Data>( - message, &validation_context); - } - return false; -} - -using RunCallback = - base::Callback<void(interface_control::RunResponseMessageParamsPtr)>; - -class RunResponseForwardToCallback : public MessageReceiver { - public: - explicit RunResponseForwardToCallback(const RunCallback& callback) - : callback_(callback) {} - bool Accept(Message* message) override; - - private: - RunCallback callback_; - DISALLOW_COPY_AND_ASSIGN(RunResponseForwardToCallback); -}; - -bool RunResponseForwardToCallback::Accept(Message* message) { - if (!ValidateControlResponse(message)) - return false; - - interface_control::internal::RunResponseMessageParams_Data* params = - reinterpret_cast< - interface_control::internal::RunResponseMessageParams_Data*>( - message->mutable_payload()); - interface_control::RunResponseMessageParamsPtr params_ptr; - SerializationContext context; - Deserialize<interface_control::RunResponseMessageParamsDataView>( - params, ¶ms_ptr, &context); - - callback_.Run(std::move(params_ptr)); - return true; -} - -void SendRunMessage(MessageReceiverWithResponder* receiver, - interface_control::RunInputPtr input_ptr, - const RunCallback& callback) { - SerializationContext context; - - auto params_ptr = interface_control::RunMessageParams::New(); - params_ptr->input = std::move(input_ptr); - size_t size = PrepareToSerialize<interface_control::RunMessageParamsDataView>( - params_ptr, &context); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagExpectsResponse, size, 0); - - interface_control::internal::RunMessageParams_Data* params = nullptr; - Serialize<interface_control::RunMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); - std::unique_ptr<MessageReceiver> responder = - base::MakeUnique<RunResponseForwardToCallback>(callback); - ignore_result( - receiver->AcceptWithResponder(builder.message(), std::move(responder))); -} - -Message ConstructRunOrClosePipeMessage( - interface_control::RunOrClosePipeInputPtr input_ptr) { - SerializationContext context; - - auto params_ptr = interface_control::RunOrClosePipeMessageParams::New(); - params_ptr->input = std::move(input_ptr); - - size_t size = PrepareToSerialize< - interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr, - &context); - MessageBuilder builder(interface_control::kRunOrClosePipeMessageId, 0, size, - 0); - - interface_control::internal::RunOrClosePipeMessageParams_Data* params = - nullptr; - Serialize<interface_control::RunOrClosePipeMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); - return std::move(*builder.message()); -} - -void SendRunOrClosePipeMessage( - MessageReceiverWithResponder* receiver, - interface_control::RunOrClosePipeInputPtr input_ptr) { - Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr))); - - ignore_result(receiver->Accept(&message)); -} - -void RunVersionCallback( - const base::Callback<void(uint32_t)>& callback, - interface_control::RunResponseMessageParamsPtr run_response) { - uint32_t version = 0u; - if (run_response->output && run_response->output->is_query_version_result()) - version = run_response->output->get_query_version_result()->version; - callback.Run(version); -} - -void RunClosure(const base::Closure& callback, - interface_control::RunResponseMessageParamsPtr run_response) { - callback.Run(); -} - -} // namespace - -ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver) - : receiver_(receiver) { -} - -ControlMessageProxy::~ControlMessageProxy() = default; - -void ControlMessageProxy::QueryVersion( - const base::Callback<void(uint32_t)>& callback) { - auto input_ptr = interface_control::RunInput::New(); - input_ptr->set_query_version(interface_control::QueryVersion::New()); - SendRunMessage(receiver_, std::move(input_ptr), - base::Bind(&RunVersionCallback, callback)); -} - -void ControlMessageProxy::RequireVersion(uint32_t version) { - auto require_version = interface_control::RequireVersion::New(); - require_version->version = version; - auto input_ptr = interface_control::RunOrClosePipeInput::New(); - input_ptr->set_require_version(std::move(require_version)); - SendRunOrClosePipeMessage(receiver_, std::move(input_ptr)); -} - -void ControlMessageProxy::FlushForTesting() { - if (encountered_error_) - return; - - auto input_ptr = interface_control::RunInput::New(); - input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New()); - base::RunLoop run_loop; - run_loop_quit_closure_ = run_loop.QuitClosure(); - SendRunMessage( - receiver_, std::move(input_ptr), - base::Bind(&RunClosure, - base::Bind(&ControlMessageProxy::RunFlushForTestingClosure, - base::Unretained(this)))); - run_loop.Run(); -} - -void ControlMessageProxy::RunFlushForTestingClosure() { - DCHECK(!run_loop_quit_closure_.is_null()); - base::ResetAndReturn(&run_loop_quit_closure_).Run(); -} - -void ControlMessageProxy::OnConnectionError() { - encountered_error_ = true; - if (!run_loop_quit_closure_.is_null()) - RunFlushForTestingClosure(); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.h b/mojo/public/cpp/bindings/lib/control_message_proxy.h deleted file mode 100644 index 2f9314e..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ - -#include <stdint.h> - -#include "base/callback.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { - -class MessageReceiverWithResponder; - -namespace internal { - -// Proxy for request messages defined in interface_control_messages.mojom. -class MOJO_CPP_BINDINGS_EXPORT ControlMessageProxy { - public: - // Doesn't take ownership of |receiver|. It must outlive this object. - explicit ControlMessageProxy(MessageReceiverWithResponder* receiver); - ~ControlMessageProxy(); - - void QueryVersion(const base::Callback<void(uint32_t)>& callback); - void RequireVersion(uint32_t version); - - void FlushForTesting(); - void OnConnectionError(); - - private: - void RunFlushForTestingClosure(); - - // Not owned. - MessageReceiverWithResponder* receiver_; - bool encountered_error_ = false; - - base::Closure run_loop_quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ diff --git a/mojo/public/cpp/bindings/lib/equals_traits.h b/mojo/public/cpp/bindings/lib/equals_traits.h deleted file mode 100644 index 53c7dce..0000000 --- a/mojo/public/cpp/bindings/lib/equals_traits.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ - -#include <type_traits> -#include <unordered_map> -#include <vector> - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { -namespace internal { - -template <typename T> -struct HasEqualsMethod { - template <typename U> - static char Test(decltype(&U::Equals)); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename T, bool has_equals_method = HasEqualsMethod<T>::value> -struct EqualsTraits; - -template <typename T> -bool Equals(const T& a, const T& b); - -template <typename T> -struct EqualsTraits<T, true> { - static bool Equals(const T& a, const T& b) { return a.Equals(b); } -}; - -template <typename T> -struct EqualsTraits<T, false> { - static bool Equals(const T& a, const T& b) { return a == b; } -}; - -template <typename T> -struct EqualsTraits<base::Optional<T>, false> { - static bool Equals(const base::Optional<T>& a, const base::Optional<T>& b) { - if (!a && !b) - return true; - if (!a || !b) - return false; - - return internal::Equals(*a, *b); - } -}; - -template <typename T> -struct EqualsTraits<std::vector<T>, false> { - static bool Equals(const std::vector<T>& a, const std::vector<T>& b) { - if (a.size() != b.size()) - return false; - for (size_t i = 0; i < a.size(); ++i) { - if (!internal::Equals(a[i], b[i])) - return false; - } - return true; - } -}; - -template <typename K, typename V> -struct EqualsTraits<std::unordered_map<K, V>, false> { - static bool Equals(const std::unordered_map<K, V>& a, - const std::unordered_map<K, V>& b) { - if (a.size() != b.size()) - return false; - for (const auto& element : a) { - auto iter = b.find(element.first); - if (iter == b.end() || !internal::Equals(element.second, iter->second)) - return false; - } - return true; - } -}; - -template <typename T> -bool Equals(const T& a, const T& b) { - return EqualsTraits<T>::Equals(a, b); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/lib/filter_chain.cc b/mojo/public/cpp/bindings/lib/filter_chain.cc deleted file mode 100644 index 5d919fe..0000000 --- a/mojo/public/cpp/bindings/lib/filter_chain.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/filter_chain.h" - -#include <algorithm> - -#include "base/logging.h" - -namespace mojo { - -FilterChain::FilterChain(MessageReceiver* sink) : sink_(sink) { -} - -FilterChain::FilterChain(FilterChain&& other) : sink_(other.sink_) { - other.sink_ = nullptr; - filters_.swap(other.filters_); -} - -FilterChain& FilterChain::operator=(FilterChain&& other) { - std::swap(sink_, other.sink_); - filters_.swap(other.filters_); - return *this; -} - -FilterChain::~FilterChain() { -} - -void FilterChain::SetSink(MessageReceiver* sink) { - DCHECK(!sink_); - sink_ = sink; -} - -bool FilterChain::Accept(Message* message) { - DCHECK(sink_); - for (auto& filter : filters_) - if (!filter->Accept(message)) - return false; - return sink_->Accept(message); -} - -void FilterChain::Append(std::unique_ptr<MessageReceiver> filter) { - filters_.emplace_back(std::move(filter)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc deleted file mode 100644 index 725a193..0000000 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" - -#include <stdlib.h> - -namespace mojo { -namespace internal { - -FixedBufferForTesting::FixedBufferForTesting(size_t size) { - size = internal::Align(size); - // Use calloc here to ensure all message memory is zero'd out. - void* ptr = calloc(size, 1); - Initialize(ptr, size); -} - -FixedBufferForTesting::~FixedBufferForTesting() { - free(data()); -} - -void* FixedBufferForTesting::Leak() { - void* ptr = data(); - Initialize(nullptr, 0); - return ptr; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h deleted file mode 100644 index 070b0c8..0000000 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ - -#include <stddef.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" - -namespace mojo { -namespace internal { - -// FixedBufferForTesting owns its buffer. The Leak method may be used to steal -// the underlying memory. -class MOJO_CPP_BINDINGS_EXPORT FixedBufferForTesting - : NON_EXPORTED_BASE(public Buffer) { - public: - explicit FixedBufferForTesting(size_t size); - ~FixedBufferForTesting(); - - // Returns the internal memory owned by the Buffer to the caller. The Buffer - // relinquishes its pointer, effectively resetting the state of the Buffer - // and leaving the caller responsible for freeing the returned memory address - // when no longer needed. - void* Leak(); - - private: - DISALLOW_COPY_AND_ASSIGN(FixedBufferForTesting); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h b/mojo/public/cpp/bindings/lib/handle_interface_serialization.h deleted file mode 100644 index 14ed21f..0000000 --- a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ - -#include <type_traits> - -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/interface_data_view.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -template <typename Base, typename T> -struct Serializer<AssociatedInterfacePtrInfoDataView<Base>, - AssociatedInterfacePtrInfo<T>> { - static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const AssociatedInterfacePtrInfo<T>& input, - SerializationContext* context) { - if (input.handle().is_valid()) - context->associated_endpoint_count++; - return 0; - } - - static void Serialize(AssociatedInterfacePtrInfo<T>& input, - AssociatedInterface_Data* output, - SerializationContext* context) { - DCHECK(!input.handle().is_valid() || input.handle().pending_association()); - if (input.handle().is_valid()) { - // Set to the index of the element pushed to the back of the vector. - output->handle.value = - static_cast<uint32_t>(context->associated_endpoint_handles.size()); - context->associated_endpoint_handles.push_back(input.PassHandle()); - } else { - output->handle.value = kEncodedInvalidHandleValue; - } - output->version = input.version(); - } - - static bool Deserialize(AssociatedInterface_Data* input, - AssociatedInterfacePtrInfo<T>* output, - SerializationContext* context) { - if (input->handle.is_valid()) { - DCHECK_LT(input->handle.value, - context->associated_endpoint_handles.size()); - output->set_handle( - std::move(context->associated_endpoint_handles[input->handle.value])); - } else { - output->set_handle(ScopedInterfaceEndpointHandle()); - } - output->set_version(input->version); - return true; - } -}; - -template <typename Base, typename T> -struct Serializer<AssociatedInterfaceRequestDataView<Base>, - AssociatedInterfaceRequest<T>> { - static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const AssociatedInterfaceRequest<T>& input, - SerializationContext* context) { - if (input.handle().is_valid()) - context->associated_endpoint_count++; - return 0; - } - - static void Serialize(AssociatedInterfaceRequest<T>& input, - AssociatedEndpointHandle_Data* output, - SerializationContext* context) { - DCHECK(!input.handle().is_valid() || input.handle().pending_association()); - if (input.handle().is_valid()) { - // Set to the index of the element pushed to the back of the vector. - output->value = - static_cast<uint32_t>(context->associated_endpoint_handles.size()); - context->associated_endpoint_handles.push_back(input.PassHandle()); - } else { - output->value = kEncodedInvalidHandleValue; - } - } - - static bool Deserialize(AssociatedEndpointHandle_Data* input, - AssociatedInterfaceRequest<T>* output, - SerializationContext* context) { - if (input->is_valid()) { - DCHECK_LT(input->value, context->associated_endpoint_handles.size()); - output->Bind( - std::move(context->associated_endpoint_handles[input->value])); - } else { - output->Bind(ScopedInterfaceEndpointHandle()); - } - return true; - } -}; - -template <typename Base, typename T> -struct Serializer<InterfacePtrDataView<Base>, InterfacePtr<T>> { - static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const InterfacePtr<T>& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(InterfacePtr<T>& input, - Interface_Data* output, - SerializationContext* context) { - InterfacePtrInfo<T> info = input.PassInterface(); - output->handle = context->handles.AddHandle(info.PassHandle().release()); - output->version = info.version(); - } - - static bool Deserialize(Interface_Data* input, - InterfacePtr<T>* output, - SerializationContext* context) { - output->Bind(InterfacePtrInfo<T>( - context->handles.TakeHandleAs<mojo::MessagePipeHandle>(input->handle), - input->version)); - return true; - } -}; - -template <typename Base, typename T> -struct Serializer<InterfaceRequestDataView<Base>, InterfaceRequest<T>> { - static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const InterfaceRequest<T>& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(InterfaceRequest<T>& input, - Handle_Data* output, - SerializationContext* context) { - *output = context->handles.AddHandle(input.PassMessagePipe().release()); - } - - static bool Deserialize(Handle_Data* input, - InterfaceRequest<T>* output, - SerializationContext* context) { - output->Bind(context->handles.TakeHandleAs<MessagePipeHandle>(*input)); - return true; - } -}; - -template <typename T> -struct Serializer<ScopedHandleBase<T>, ScopedHandleBase<T>> { - static size_t PrepareToSerialize(const ScopedHandleBase<T>& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(ScopedHandleBase<T>& input, - Handle_Data* output, - SerializationContext* context) { - *output = context->handles.AddHandle(input.release()); - } - - static bool Deserialize(Handle_Data* input, - ScopedHandleBase<T>* output, - SerializationContext* context) { - *output = context->handles.TakeHandleAs<T>(*input); - return true; - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/hash_util.h b/mojo/public/cpp/bindings/lib/hash_util.h deleted file mode 100644 index 93280d6..0000000 --- a/mojo/public/cpp/bindings/lib/hash_util.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ - -#include <cstring> -#include <functional> -#include <type_traits> -#include <vector> - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { -namespace internal { - -template <typename T> -size_t HashCombine(size_t seed, const T& value) { - // Based on proposal in: - // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf - return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2)); -} - -template <typename T> -struct HasHashMethod { - template <typename U> - static char Test(decltype(&U::Hash)); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename T, bool has_hash_method = HasHashMethod<T>::value> -struct HashTraits; - -template <typename T> -size_t Hash(size_t seed, const T& value); - -template <typename T> -struct HashTraits<T, true> { - static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } -}; - -template <typename T> -struct HashTraits<T, false> { - static size_t Hash(size_t seed, const T& value) { - return HashCombine(seed, value); - } -}; - -template <typename T> -struct HashTraits<std::vector<T>, false> { - static size_t Hash(size_t seed, const std::vector<T>& value) { - for (const auto& element : value) { - seed = HashCombine(seed, element); - } - return seed; - } -}; - -template <typename T> -struct HashTraits<base::Optional<std::vector<T>>, false> { - static size_t Hash(size_t seed, const base::Optional<std::vector<T>>& value) { - if (!value) - return HashCombine(seed, 0); - - return Hash(seed, *value); - } -}; - -template <typename T> -size_t Hash(size_t seed, const T& value) { - return HashTraits<T>::Hash(seed, value); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc deleted file mode 100644 index 4682e72..0000000 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" - -namespace mojo { - -// ---------------------------------------------------------------------------- - -namespace { - -void DCheckIfInvalid(const base::WeakPtr<InterfaceEndpointClient>& client, - const std::string& message) { - bool is_valid = client && !client->encountered_error(); - DCHECK(!is_valid) << message; -} - -// When receiving an incoming message which expects a repsonse, -// InterfaceEndpointClient creates a ResponderThunk object and passes it to the -// incoming message receiver. When the receiver finishes processing the message, -// it can provide a response using this object. -class ResponderThunk : public MessageReceiverWithStatus { - public: - explicit ResponderThunk( - const base::WeakPtr<InterfaceEndpointClient>& endpoint_client, - scoped_refptr<base::SingleThreadTaskRunner> runner) - : endpoint_client_(endpoint_client), - accept_was_invoked_(false), - task_runner_(std::move(runner)) {} - ~ResponderThunk() override { - if (!accept_was_invoked_) { - // The Service handled a message that was expecting a response - // but did not send a response. - // We raise an error to signal the calling application that an error - // condition occurred. Without this the calling application would have no - // way of knowing it should stop waiting for a response. - if (task_runner_->RunsTasksOnCurrentThread()) { - // Please note that even if this code is run from a different task - // runner on the same thread as |task_runner_|, it is okay to directly - // call InterfaceEndpointClient::RaiseError(), because it will raise - // error from the correct task runner asynchronously. - if (endpoint_client_) { - endpoint_client_->RaiseError(); - } - } else { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&InterfaceEndpointClient::RaiseError, endpoint_client_)); - } - } - } - - // MessageReceiver implementation: - bool Accept(Message* message) override { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - accept_was_invoked_ = true; - DCHECK(message->has_flag(Message::kFlagIsResponse)); - - bool result = false; - - if (endpoint_client_) - result = endpoint_client_->Accept(message); - - return result; - } - - // MessageReceiverWithStatus implementation: - bool IsValid() override { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - return endpoint_client_ && !endpoint_client_->encountered_error(); - } - - void DCheckInvalid(const std::string& message) override { - if (task_runner_->RunsTasksOnCurrentThread()) { - DCheckIfInvalid(endpoint_client_, message); - } else { - task_runner_->PostTask( - FROM_HERE, base::Bind(&DCheckIfInvalid, endpoint_client_, message)); - } - } - - private: - base::WeakPtr<InterfaceEndpointClient> endpoint_client_; - bool accept_was_invoked_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(ResponderThunk); -}; - -} // namespace - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::SyncResponseInfo::SyncResponseInfo( - bool* in_response_received) - : response_received(in_response_received) {} - -InterfaceEndpointClient::SyncResponseInfo::~SyncResponseInfo() {} - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::HandleIncomingMessageThunk::HandleIncomingMessageThunk( - InterfaceEndpointClient* owner) - : owner_(owner) {} - -InterfaceEndpointClient::HandleIncomingMessageThunk:: - ~HandleIncomingMessageThunk() {} - -bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept( - Message* message) { - return owner_->HandleValidatedMessage(message); -} - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::InterfaceEndpointClient( - ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr<MessageReceiver> payload_validator, - bool expect_sync_requests, - scoped_refptr<base::SingleThreadTaskRunner> runner, - uint32_t interface_version) - : expect_sync_requests_(expect_sync_requests), - handle_(std::move(handle)), - incoming_receiver_(receiver), - thunk_(this), - filters_(&thunk_), - task_runner_(std::move(runner)), - control_message_proxy_(this), - control_message_handler_(interface_version), - weak_ptr_factory_(this) { - DCHECK(handle_.is_valid()); - - // TODO(yzshen): the way to use validator (or message filter in general) - // directly is a little awkward. - if (payload_validator) - filters_.Append(std::move(payload_validator)); - - if (handle_.pending_association()) { - handle_.SetAssociationEventHandler(base::Bind( - &InterfaceEndpointClient::OnAssociationEvent, base::Unretained(this))); - } else { - InitControllerIfNecessary(); - } -} - -InterfaceEndpointClient::~InterfaceEndpointClient() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (controller_) - handle_.group_controller()->DetachEndpointClient(handle_); -} - -AssociatedGroup* InterfaceEndpointClient::associated_group() { - if (!associated_group_) - associated_group_ = base::MakeUnique<AssociatedGroup>(handle_); - return associated_group_.get(); -} - -ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!has_pending_responders()); - - if (!handle_.is_valid()) - return ScopedInterfaceEndpointHandle(); - - handle_.SetAssociationEventHandler( - ScopedInterfaceEndpointHandle::AssociationEventCallback()); - - if (controller_) { - controller_ = nullptr; - handle_.group_controller()->DetachEndpointClient(handle_); - } - - return std::move(handle_); -} - -void InterfaceEndpointClient::AddFilter( - std::unique_ptr<MessageReceiver> filter) { - filters_.Append(std::move(filter)); -} - -void InterfaceEndpointClient::RaiseError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!handle_.pending_association()) - handle_.group_controller()->RaiseError(); -} - -void InterfaceEndpointClient::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - DCHECK(thread_checker_.CalledOnValidThread()); - - auto handle = PassHandle(); - handle.ResetWithReason(custom_reason, description); -} - -bool InterfaceEndpointClient::Accept(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!message->has_flag(Message::kFlagExpectsResponse)); - DCHECK(!handle_.pending_association()); - - // This has to been done even if connection error has occurred. For example, - // the message contains a pending associated request. The user may try to use - // the corresponding associated interface pointer after sending this message. - // That associated interface pointer has to join an associated group in order - // to work properly. - if (!message->associated_endpoint_handles()->empty()) - message->SerializeAssociatedEndpointHandles(handle_.group_controller()); - - if (encountered_error_) - return false; - - InitControllerIfNecessary(); - - return controller_->SendMessage(message); -} - -bool InterfaceEndpointClient::AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiver> responder) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(message->has_flag(Message::kFlagExpectsResponse)); - DCHECK(!handle_.pending_association()); - - // Please see comments in Accept(). - if (!message->associated_endpoint_handles()->empty()) - message->SerializeAssociatedEndpointHandles(handle_.group_controller()); - - if (encountered_error_) - return false; - - InitControllerIfNecessary(); - - // Reserve 0 in case we want it to convey special meaning in the future. - uint64_t request_id = next_request_id_++; - if (request_id == 0) - request_id = next_request_id_++; - - message->set_request_id(request_id); - - bool is_sync = message->has_flag(Message::kFlagIsSync); - if (!controller_->SendMessage(message)) - return false; - - if (!is_sync) { - async_responders_[request_id] = std::move(responder); - return true; - } - - SyncCallRestrictions::AssertSyncCallAllowed(); - - bool response_received = false; - sync_responses_.insert(std::make_pair( - request_id, base::MakeUnique<SyncResponseInfo>(&response_received))); - - base::WeakPtr<InterfaceEndpointClient> weak_self = - weak_ptr_factory_.GetWeakPtr(); - controller_->SyncWatch(&response_received); - // Make sure that this instance hasn't been destroyed. - if (weak_self) { - DCHECK(base::ContainsKey(sync_responses_, request_id)); - auto iter = sync_responses_.find(request_id); - DCHECK_EQ(&response_received, iter->second->response_received); - if (response_received) - ignore_result(responder->Accept(&iter->second->response)); - sync_responses_.erase(iter); - } - - return true; -} - -bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - return filters_.Accept(message); -} - -void InterfaceEndpointClient::NotifyError( - const base::Optional<DisconnectReason>& reason) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (encountered_error_) - return; - encountered_error_ = true; - - // Response callbacks may hold on to resource, and there's no need to keep - // them alive any longer. Note that it's allowed that a pending response - // callback may own this endpoint, so we simply move the responders onto the - // stack here and let them be destroyed when the stack unwinds. - AsyncResponderMap responders = std::move(async_responders_); - - control_message_proxy_.OnConnectionError(); - - if (!error_handler_.is_null()) { - base::Closure error_handler = std::move(error_handler_); - error_handler.Run(); - } else if (!error_with_reason_handler_.is_null()) { - ConnectionErrorWithReasonCallback error_with_reason_handler = - std::move(error_with_reason_handler_); - if (reason) { - error_with_reason_handler.Run(reason->custom_reason, reason->description); - } else { - error_with_reason_handler.Run(0, std::string()); - } - } -} - -void InterfaceEndpointClient::QueryVersion( - const base::Callback<void(uint32_t)>& callback) { - control_message_proxy_.QueryVersion(callback); -} - -void InterfaceEndpointClient::RequireVersion(uint32_t version) { - control_message_proxy_.RequireVersion(version); -} - -void InterfaceEndpointClient::FlushForTesting() { - control_message_proxy_.FlushForTesting(); -} - -void InterfaceEndpointClient::InitControllerIfNecessary() { - if (controller_ || handle_.pending_association()) - return; - - controller_ = handle_.group_controller()->AttachEndpointClient(handle_, this, - task_runner_); - if (expect_sync_requests_) - controller_->AllowWokenUpBySyncWatchOnSameThread(); -} - -void InterfaceEndpointClient::OnAssociationEvent( - ScopedInterfaceEndpointHandle::AssociationEvent event) { - if (event == ScopedInterfaceEndpointHandle::ASSOCIATED) { - InitControllerIfNecessary(); - } else if (event == - ScopedInterfaceEndpointHandle::PEER_CLOSED_BEFORE_ASSOCIATION) { - task_runner_->PostTask(FROM_HERE, - base::Bind(&InterfaceEndpointClient::NotifyError, - weak_ptr_factory_.GetWeakPtr(), - handle_.disconnect_reason())); - } -} - -bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) { - DCHECK_EQ(handle_.id(), message->interface_id()); - - if (encountered_error_) { - // This message is received after error has been encountered. For associated - // interfaces, this means the remote side sends a - // PeerAssociatedEndpointClosed event but continues to send more messages - // for the same interface. Close the pipe because this shouldn't happen. - DVLOG(1) << "A message is received for an interface after it has been " - << "disconnected. Closing the pipe."; - return false; - } - - if (message->has_flag(Message::kFlagExpectsResponse)) { - std::unique_ptr<MessageReceiverWithStatus> responder = - base::MakeUnique<ResponderThunk>(weak_ptr_factory_.GetWeakPtr(), - task_runner_); - if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) { - return control_message_handler_.AcceptWithResponder(message, - std::move(responder)); - } else { - return incoming_receiver_->AcceptWithResponder(message, - std::move(responder)); - } - } else if (message->has_flag(Message::kFlagIsResponse)) { - uint64_t request_id = message->request_id(); - - if (message->has_flag(Message::kFlagIsSync)) { - auto it = sync_responses_.find(request_id); - if (it == sync_responses_.end()) - return false; - it->second->response = std::move(*message); - *it->second->response_received = true; - return true; - } - - auto it = async_responders_.find(request_id); - if (it == async_responders_.end()) - return false; - std::unique_ptr<MessageReceiver> responder = std::move(it->second); - async_responders_.erase(it); - return responder->Accept(message); - } else { - if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) - return control_message_handler_.Accept(message); - - return incoming_receiver_->Accept(message); - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h deleted file mode 100644 index fa54979..0000000 --- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ - -#include <stdint.h> - -#include <algorithm> // For |std::swap()|. -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { -namespace internal { - -template <typename Interface> -class InterfacePtrState { - public: - InterfacePtrState() : version_(0u) {} - - ~InterfacePtrState() { - endpoint_client_.reset(); - proxy_.reset(); - if (router_) - router_->CloseMessagePipe(); - } - - Interface* instance() { - ConfigureProxyIfNecessary(); - - // This will be null if the object is not bound. - return proxy_.get(); - } - - uint32_t version() const { return version_; } - - void QueryVersion(const base::Callback<void(uint32_t)>& callback) { - ConfigureProxyIfNecessary(); - - // It is safe to capture |this| because the callback won't be run after this - // object goes away. - endpoint_client_->QueryVersion(base::Bind( - &InterfacePtrState::OnQueryVersion, base::Unretained(this), callback)); - } - - void RequireVersion(uint32_t version) { - ConfigureProxyIfNecessary(); - - if (version <= version_) - return; - - version_ = version; - endpoint_client_->RequireVersion(version); - } - - void FlushForTesting() { - ConfigureProxyIfNecessary(); - endpoint_client_->FlushForTesting(); - } - - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - ConfigureProxyIfNecessary(); - endpoint_client_->CloseWithReason(custom_reason, description); - } - - void Swap(InterfacePtrState* other) { - using std::swap; - swap(other->router_, router_); - swap(other->endpoint_client_, endpoint_client_); - swap(other->proxy_, proxy_); - handle_.swap(other->handle_); - runner_.swap(other->runner_); - swap(other->version_, version_); - } - - void Bind(InterfacePtrInfo<Interface> info, - scoped_refptr<base::SingleThreadTaskRunner> runner) { - DCHECK(!router_); - DCHECK(!endpoint_client_); - DCHECK(!proxy_); - DCHECK(!handle_.is_valid()); - DCHECK_EQ(0u, version_); - DCHECK(info.is_valid()); - - handle_ = info.PassHandle(); - version_ = info.version(); - runner_ = std::move(runner); - } - - bool HasAssociatedInterfaces() const { - return router_ ? router_->HasAssociatedEndpoints() : false; - } - - // After this method is called, the object is in an invalid state and - // shouldn't be reused. - InterfacePtrInfo<Interface> PassInterface() { - endpoint_client_.reset(); - proxy_.reset(); - return InterfacePtrInfo<Interface>( - router_ ? router_->PassMessagePipe() : std::move(handle_), version_); - } - - bool is_bound() const { return handle_.is_valid() || endpoint_client_; } - - bool encountered_error() const { - return endpoint_client_ ? endpoint_client_->encountered_error() : false; - } - - void set_connection_error_handler(const base::Closure& error_handler) { - ConfigureProxyIfNecessary(); - - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - ConfigureProxyIfNecessary(); - - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - // Returns true if bound and awaiting a response to a message. - bool has_pending_callbacks() const { - return endpoint_client_ && endpoint_client_->has_pending_responders(); - } - - AssociatedGroup* associated_group() { - ConfigureProxyIfNecessary(); - return endpoint_client_->associated_group(); - } - - void EnableTestingMode() { - ConfigureProxyIfNecessary(); - router_->EnableTestingMode(); - } - - void ForwardMessage(Message message) { - ConfigureProxyIfNecessary(); - endpoint_client_->Accept(&message); - } - - void ForwardMessageWithResponder(Message message, - std::unique_ptr<MessageReceiver> responder) { - ConfigureProxyIfNecessary(); - endpoint_client_->AcceptWithResponder(&message, std::move(responder)); - } - - private: - using Proxy = typename Interface::Proxy_; - - void ConfigureProxyIfNecessary() { - // The proxy has been configured. - if (proxy_) { - DCHECK(router_); - DCHECK(endpoint_client_); - return; - } - // The object hasn't been bound. - if (!handle_.is_valid()) - return; - - MultiplexRouter::Config config = - Interface::PassesAssociatedKinds_ - ? MultiplexRouter::MULTI_INTERFACE - : (Interface::HasSyncMethods_ - ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS - : MultiplexRouter::SINGLE_INTERFACE); - router_ = new MultiplexRouter(std::move(handle_), config, true, runner_); - router_->SetMasterInterfaceName(Interface::Name_); - endpoint_client_.reset(new InterfaceEndpointClient( - router_->CreateLocalEndpointHandle(kMasterInterfaceId), nullptr, - base::WrapUnique(new typename Interface::ResponseValidator_()), false, - std::move(runner_), - // The version is only queried from the client so the value passed here - // will not be used. - 0u)); - proxy_.reset(new Proxy(endpoint_client_.get())); - } - - void OnQueryVersion(const base::Callback<void(uint32_t)>& callback, - uint32_t version) { - version_ = version; - callback.Run(version); - } - - scoped_refptr<MultiplexRouter> router_; - - std::unique_ptr<InterfaceEndpointClient> endpoint_client_; - std::unique_ptr<Proxy> proxy_; - - // |router_| (as well as other members above) is not initialized until - // read/write with the message pipe handle is needed. |handle_| is valid - // between the Bind() call and the initialization of |router_|. - ScopedMessagePipeHandle handle_; - scoped_refptr<base::SingleThreadTaskRunner> runner_; - - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtrState); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/map_data_internal.h b/mojo/public/cpp/bindings/lib/map_data_internal.h deleted file mode 100644 index f8e3d29..0000000 --- a/mojo/public/cpp/bindings/lib/map_data_internal.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace internal { - -// Map serializes into a struct which has two arrays as struct fields, the keys -// and the values. -template <typename Key, typename Value> -class Map_Data { - public: - static Map_Data* New(Buffer* buf) { - return new (buf->Allocate(sizeof(Map_Data))) Map_Data(); - } - - // |validate_params| must have non-null |key_validate_params| and - // |element_validate_params| members. - static bool Validate(const void* data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!data) - return true; - - if (!ValidateStructHeaderAndClaimMemory(data, validation_context)) - return false; - - const Map_Data* object = static_cast<const Map_Data*>(data); - if (object->header_.num_bytes != sizeof(Map_Data) || - object->header_.version != 0) { - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } - - if (!ValidatePointerNonNullable( - object->keys, "null key array in map struct", validation_context) || - !ValidateContainer(object->keys, validation_context, - validate_params->key_validate_params)) { - return false; - } - - if (!ValidatePointerNonNullable(object->values, - "null value array in map struct", - validation_context) || - !ValidateContainer(object->values, validation_context, - validate_params->element_validate_params)) { - return false; - } - - if (object->keys.Get()->size() != object->values.Get()->size()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP); - return false; - } - - return true; - } - - StructHeader header_; - - Pointer<Array_Data<Key>> keys; - Pointer<Array_Data<Value>> values; - - private: - Map_Data() { - header_.num_bytes = sizeof(*this); - header_.version = 0; - } - ~Map_Data() = delete; -}; -static_assert(sizeof(Map_Data<char, char>) == 24, "Bad sizeof(Map_Data)"); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h deleted file mode 100644 index 718a763..0000000 --- a/mojo/public/cpp/bindings/lib/map_serialization.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ - -#include <type_traits> -#include <vector> - -#include "mojo/public/cpp/bindings/array_data_view.h" -#include "mojo/public/cpp/bindings/lib/array_serialization.h" -#include "mojo/public/cpp/bindings/lib/map_data_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/map_data_view.h" - -namespace mojo { -namespace internal { - -template <typename MaybeConstUserType> -class MapReaderBase { - public: - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = MapTraits<UserType>; - using MaybeConstIterator = - decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>())); - - explicit MapReaderBase(MaybeConstUserType& input) - : input_(input), iter_(Traits::GetBegin(input_)) {} - ~MapReaderBase() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - // Return null because key or value elements are not stored continuously in - // memory. - void* GetDataIfExists() { return nullptr; } - - protected: - MaybeConstUserType& input_; - MaybeConstIterator iter_; -}; - -// Used as the UserTypeReader template parameter of ArraySerializer. -template <typename MaybeConstUserType> -class MapKeyReader : public MapReaderBase<MaybeConstUserType> { - public: - using Base = MapReaderBase<MaybeConstUserType>; - using Traits = typename Base::Traits; - using MaybeConstIterator = typename Base::MaybeConstIterator; - - explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} - ~MapKeyReader() {} - - using GetNextResult = - decltype(Traits::GetKey(std::declval<MaybeConstIterator&>())); - GetNextResult GetNext() { - GetNextResult key = Traits::GetKey(this->iter_); - Traits::AdvanceIterator(this->iter_); - return key; - } -}; - -// Used as the UserTypeReader template parameter of ArraySerializer. -template <typename MaybeConstUserType> -class MapValueReader : public MapReaderBase<MaybeConstUserType> { - public: - using Base = MapReaderBase<MaybeConstUserType>; - using Traits = typename Base::Traits; - using MaybeConstIterator = typename Base::MaybeConstIterator; - - explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} - ~MapValueReader() {} - - using GetNextResult = - decltype(Traits::GetValue(std::declval<MaybeConstIterator&>())); - GetNextResult GetNext() { - GetNextResult value = Traits::GetValue(this->iter_); - Traits::AdvanceIterator(this->iter_); - return value; - } -}; - -template <typename Key, typename Value, typename MaybeConstUserType> -struct Serializer<MapDataView<Key, Value>, MaybeConstUserType> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = MapTraits<UserType>; - using UserKey = typename Traits::Key; - using UserValue = typename Traits::Value; - using Data = typename MojomTypeTraits<MapDataView<Key, Value>>::Data; - using KeyArraySerializer = ArraySerializer<ArrayDataView<Key>, - std::vector<UserKey>, - MapKeyReader<MaybeConstUserType>>; - using ValueArraySerializer = - ArraySerializer<ArrayDataView<Value>, - std::vector<UserValue>, - MapValueReader<MaybeConstUserType>>; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists<Traits>(input)) - return 0; - - size_t struct_overhead = sizeof(Data); - MapKeyReader<MaybeConstUserType> key_reader(input); - size_t keys_size = - KeyArraySerializer::GetSerializedSize(&key_reader, context); - MapValueReader<MaybeConstUserType> value_reader(input); - size_t values_size = - ValueArraySerializer::GetSerializedSize(&value_reader, context); - - return struct_overhead + keys_size + values_size; - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buf, - Data** output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(validate_params->key_validate_params); - DCHECK(validate_params->element_validate_params); - if (CallIsNullIfExists<Traits>(input)) { - *output = nullptr; - return; - } - - auto result = Data::New(buf); - if (result) { - auto keys_ptr = MojomTypeTraits<ArrayDataView<Key>>::Data::New( - Traits::GetSize(input), buf); - if (keys_ptr) { - MapKeyReader<MaybeConstUserType> key_reader(input); - KeyArraySerializer::SerializeElements( - &key_reader, buf, keys_ptr, validate_params->key_validate_params, - context); - result->keys.Set(keys_ptr); - } - - auto values_ptr = MojomTypeTraits<ArrayDataView<Value>>::Data::New( - Traits::GetSize(input), buf); - if (values_ptr) { - MapValueReader<MaybeConstUserType> value_reader(input); - ValueArraySerializer::SerializeElements( - &value_reader, buf, values_ptr, - validate_params->element_validate_params, context); - result->values.Set(values_ptr); - } - } - *output = result; - } - - static bool Deserialize(Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists<Traits>(output); - - std::vector<UserKey> keys; - std::vector<UserValue> values; - - if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys, - context) || - !ValueArraySerializer::DeserializeElements(input->values.Get(), &values, - context)) { - return false; - } - - DCHECK_EQ(keys.size(), values.size()); - size_t size = keys.size(); - Traits::SetToEmpty(output); - - for (size_t i = 0; i < size; ++i) { - if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i]))) - return false; - } - return true; - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/may_auto_lock.h b/mojo/public/cpp/bindings/lib/may_auto_lock.h deleted file mode 100644 index 06091fe..0000000 --- a/mojo/public/cpp/bindings/lib/may_auto_lock.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ - -#include "base/macros.h" -#include "base/optional.h" -#include "base/synchronization/lock.h" - -namespace mojo { -namespace internal { - -// Similar to base::AutoLock, except that it does nothing if |lock| passed into -// the constructor is null. -class MayAutoLock { - public: - explicit MayAutoLock(base::Optional<base::Lock>* lock) - : lock_(lock->has_value() ? &lock->value() : nullptr) { - if (lock_) - lock_->Acquire(); - } - - ~MayAutoLock() { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } - } - - private: - base::Lock* lock_; - DISALLOW_COPY_AND_ASSIGN(MayAutoLock); -}; - -// Similar to base::AutoUnlock, except that it does nothing if |lock| passed -// into the constructor is null. -class MayAutoUnlock { - public: - explicit MayAutoUnlock(base::Optional<base::Lock>* lock) - : lock_(lock->has_value() ? &lock->value() : nullptr) { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } - } - - ~MayAutoUnlock() { - if (lock_) - lock_->Acquire(); - } - - private: - base::Lock* lock_; - DISALLOW_COPY_AND_ASSIGN(MayAutoUnlock); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc deleted file mode 100644 index e5f3808..0000000 --- a/mojo/public/cpp/bindings/lib/message.cc +++ /dev/null @@ -1,332 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/message.h" - -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> - -#include <algorithm> -#include <utility> - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_local.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" - -namespace mojo { - -namespace { - -base::LazyInstance<base::ThreadLocalPointer<internal::MessageDispatchContext>>:: - DestructorAtExit g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER; - -base::LazyInstance<base::ThreadLocalPointer<SyncMessageResponseContext>>:: - DestructorAtExit g_tls_sync_response_context = LAZY_INSTANCE_INITIALIZER; - -void DoNotifyBadMessage(Message message, const std::string& error) { - message.NotifyBadMessage(error); -} - -} // namespace - -Message::Message() { -} - -Message::Message(Message&& other) - : buffer_(std::move(other.buffer_)), - handles_(std::move(other.handles_)), - associated_endpoint_handles_( - std::move(other.associated_endpoint_handles_)) {} - -Message::~Message() { - CloseHandles(); -} - -Message& Message::operator=(Message&& other) { - Reset(); - std::swap(other.buffer_, buffer_); - std::swap(other.handles_, handles_); - std::swap(other.associated_endpoint_handles_, associated_endpoint_handles_); - return *this; -} - -void Message::Reset() { - CloseHandles(); - handles_.clear(); - associated_endpoint_handles_.clear(); - buffer_.reset(); -} - -void Message::Initialize(size_t capacity, bool zero_initialized) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); -} - -void Message::InitializeFromMojoMessage(ScopedMessageHandle message, - uint32_t num_bytes, - std::vector<Handle>* handles) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); - handles_.swap(*handles); -} - -const uint8_t* Message::payload() const { - if (version() < 2) - return data() + header()->num_bytes; - - return static_cast<const uint8_t*>(header_v2()->payload.Get()); -} - -uint32_t Message::payload_num_bytes() const { - DCHECK_GE(data_num_bytes(), header()->num_bytes); - size_t num_bytes; - if (version() < 2) { - num_bytes = data_num_bytes() - header()->num_bytes; - } else { - auto payload = reinterpret_cast<uintptr_t>(header_v2()->payload.Get()); - if (!payload) { - num_bytes = 0; - } else { - auto payload_end = - reinterpret_cast<uintptr_t>(header_v2()->payload_interface_ids.Get()); - if (!payload_end) - payload_end = reinterpret_cast<uintptr_t>(data() + data_num_bytes()); - DCHECK_GE(payload_end, payload); - num_bytes = payload_end - payload; - } - } - DCHECK_LE(num_bytes, std::numeric_limits<uint32_t>::max()); - return static_cast<uint32_t>(num_bytes); -} - -uint32_t Message::payload_num_interface_ids() const { - auto* array_pointer = - version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); - return array_pointer ? static_cast<uint32_t>(array_pointer->size()) : 0; -} - -const uint32_t* Message::payload_interface_ids() const { - auto* array_pointer = - version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); - return array_pointer ? array_pointer->storage() : nullptr; -} - -ScopedMessageHandle Message::TakeMojoMessage() { - // If there are associated endpoints transferred, - // SerializeAssociatedEndpointHandles() must be called before this method. - DCHECK(associated_endpoint_handles_.empty()); - - if (handles_.empty()) // Fast path for the common case: No handles. - return buffer_->TakeMessage(); - - // Allocate a new message with space for the handles, then copy the buffer - // contents into it. - // - // TODO(rockot): We could avoid this copy by extending GetSerializedSize() - // behavior to collect handles. It's unoptimized for now because it's much - // more common to have messages with no handles. - ScopedMessageHandle new_message; - MojoResult rv = AllocMessage( - data_num_bytes(), - handles_.empty() ? nullptr - : reinterpret_cast<const MojoHandle*>(handles_.data()), - handles_.size(), - MOJO_ALLOC_MESSAGE_FLAG_NONE, - &new_message); - CHECK_EQ(rv, MOJO_RESULT_OK); - handles_.clear(); - - void* new_buffer = nullptr; - rv = GetMessageBuffer(new_message.get(), &new_buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - memcpy(new_buffer, data(), data_num_bytes()); - buffer_.reset(); - - return new_message; -} - -void Message::NotifyBadMessage(const std::string& error) { - DCHECK(buffer_); - buffer_->NotifyBadMessage(error); -} - -void Message::CloseHandles() { - for (std::vector<Handle>::iterator it = handles_.begin(); - it != handles_.end(); ++it) { - if (it->is_valid()) - CloseRaw(*it); - } -} - -void Message::SerializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller) { - if (associated_endpoint_handles_.empty()) - return; - - DCHECK_GE(version(), 2u); - DCHECK(header_v2()->payload_interface_ids.is_null()); - - size_t size = associated_endpoint_handles_.size(); - auto* data = internal::Array_Data<uint32_t>::New(size, buffer()); - header_v2()->payload_interface_ids.Set(data); - - for (size_t i = 0; i < size; ++i) { - ScopedInterfaceEndpointHandle& handle = associated_endpoint_handles_[i]; - - DCHECK(handle.pending_association()); - data->storage()[i] = - group_controller->AssociateInterface(std::move(handle)); - } - associated_endpoint_handles_.clear(); -} - -bool Message::DeserializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller) { - associated_endpoint_handles_.clear(); - - uint32_t num_ids = payload_num_interface_ids(); - if (num_ids == 0) - return true; - - associated_endpoint_handles_.reserve(num_ids); - uint32_t* ids = header_v2()->payload_interface_ids.Get()->storage(); - bool result = true; - for (uint32_t i = 0; i < num_ids; ++i) { - auto handle = group_controller->CreateLocalEndpointHandle(ids[i]); - if (IsValidInterfaceId(ids[i]) && !handle.is_valid()) { - // |ids[i]| itself is valid but handle creation failed. In that case, mark - // deserialization as failed but continue to deserialize the rest of - // handles. - result = false; - } - - associated_endpoint_handles_.push_back(std::move(handle)); - ids[i] = kInvalidInterfaceId; - } - return result; -} - -PassThroughFilter::PassThroughFilter() {} - -PassThroughFilter::~PassThroughFilter() {} - -bool PassThroughFilter::Accept(Message* message) { return true; } - -SyncMessageResponseContext::SyncMessageResponseContext() - : outer_context_(current()) { - g_tls_sync_response_context.Get().Set(this); -} - -SyncMessageResponseContext::~SyncMessageResponseContext() { - DCHECK_EQ(current(), this); - g_tls_sync_response_context.Get().Set(outer_context_); -} - -// static -SyncMessageResponseContext* SyncMessageResponseContext::current() { - return g_tls_sync_response_context.Get().Get(); -} - -void SyncMessageResponseContext::ReportBadMessage(const std::string& error) { - GetBadMessageCallback().Run(error); -} - -const ReportBadMessageCallback& -SyncMessageResponseContext::GetBadMessageCallback() { - if (bad_message_callback_.is_null()) { - bad_message_callback_ = - base::Bind(&DoNotifyBadMessage, base::Passed(&response_)); - } - return bad_message_callback_; -} - -MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { - MojoResult rv; - - std::vector<Handle> handles; - ScopedMessageHandle mojo_message; - uint32_t num_bytes = 0, num_handles = 0; - rv = ReadMessageNew(handle, - &mojo_message, - &num_bytes, - nullptr, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { - DCHECK_GT(num_handles, 0u); - handles.resize(num_handles); - rv = ReadMessageNew(handle, - &mojo_message, - &num_bytes, - reinterpret_cast<MojoHandle*>(handles.data()), - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - } - - if (rv != MOJO_RESULT_OK) - return rv; - - message->InitializeFromMojoMessage( - std::move(mojo_message), num_bytes, &handles); - return MOJO_RESULT_OK; -} - -void ReportBadMessage(const std::string& error) { - internal::MessageDispatchContext* context = - internal::MessageDispatchContext::current(); - DCHECK(context); - context->GetBadMessageCallback().Run(error); -} - -ReportBadMessageCallback GetBadMessageCallback() { - internal::MessageDispatchContext* context = - internal::MessageDispatchContext::current(); - DCHECK(context); - return context->GetBadMessageCallback(); -} - -namespace internal { - -MessageHeaderV2::MessageHeaderV2() = default; - -MessageDispatchContext::MessageDispatchContext(Message* message) - : outer_context_(current()), message_(message) { - g_tls_message_dispatch_context.Get().Set(this); -} - -MessageDispatchContext::~MessageDispatchContext() { - DCHECK_EQ(current(), this); - g_tls_message_dispatch_context.Get().Set(outer_context_); -} - -// static -MessageDispatchContext* MessageDispatchContext::current() { - return g_tls_message_dispatch_context.Get().Get(); -} - -const ReportBadMessageCallback& -MessageDispatchContext::GetBadMessageCallback() { - if (bad_message_callback_.is_null()) { - bad_message_callback_ = - base::Bind(&DoNotifyBadMessage, base::Passed(message_)); - } - return bad_message_callback_; -} - -// static -void SyncMessageResponseSetup::SetCurrentSyncResponseMessage(Message* message) { - SyncMessageResponseContext* context = SyncMessageResponseContext::current(); - if (context) - context->response_ = std::move(*message); -} - -} // namespace internal - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_buffer.cc b/mojo/public/cpp/bindings/lib/message_buffer.cc deleted file mode 100644 index cc12ef6..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_buffer.h" - -#include <limits> - -#include "mojo/public/cpp/bindings/lib/serialization_util.h" - -namespace mojo { -namespace internal { - -MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) { - DCHECK_LE(capacity, std::numeric_limits<uint32_t>::max()); - - MojoResult rv = AllocMessage(capacity, nullptr, 0, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_); - CHECK_EQ(rv, MOJO_RESULT_OK); - - void* buffer = nullptr; - if (capacity != 0) { - rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - if (zero_initialized) - memset(buffer, 0, capacity); - } - Initialize(buffer, capacity); -} - -MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) { - message_ = std::move(message); - - void* buffer = nullptr; - if (num_bytes != 0) { - MojoResult rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - } - Initialize(buffer, num_bytes); -} - -MessageBuffer::~MessageBuffer() {} - -void MessageBuffer::NotifyBadMessage(const std::string& error) { - DCHECK(message_.is_valid()); - MojoResult result = mojo::NotifyBadMessage(message_.get(), error); - DCHECK_EQ(result, MOJO_RESULT_OK); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_buffer.h b/mojo/public/cpp/bindings/lib/message_buffer.h deleted file mode 100644 index 96d5140..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ - -#include <stdint.h> - -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/system/message.h" - -namespace mojo { -namespace internal { - -// A fixed-size Buffer using a Mojo message object for storage. -class MessageBuffer : public Buffer { - public: - // Initializes this buffer to carry a fixed byte capacity and no handles. - MessageBuffer(size_t capacity, bool zero_initialized); - - // Initializes this buffer from an existing Mojo MessageHandle. - MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes); - - ~MessageBuffer(); - - ScopedMessageHandle TakeMessage() { return std::move(message_); } - - void NotifyBadMessage(const std::string& error); - - private: - ScopedMessageHandle message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/message_builder.cc b/mojo/public/cpp/bindings/lib/message_builder.cc deleted file mode 100644 index 6806a73..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.cc +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/lib/message_builder.h" - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/message_internal.h" - -namespace mojo { -namespace internal { - -template <typename Header> -void Allocate(Buffer* buf, Header** header) { - *header = static_cast<Header*>(buf->Allocate(sizeof(Header))); - (*header)->num_bytes = sizeof(Header); -} - -MessageBuilder::MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count) { - if (payload_interface_id_count > 0) { - // Version 2 - InitializeMessage( - sizeof(MessageHeaderV2) + Align(payload_size) + - ArrayDataTraits<uint32_t>::GetStorageSize( - static_cast<uint32_t>(payload_interface_id_count))); - - MessageHeaderV2* header; - Allocate(message_.buffer(), &header); - header->version = 2; - header->name = name; - header->flags = flags; - // The payload immediately follows the header. - header->payload.Set(header + 1); - } else if (flags & - (Message::kFlagExpectsResponse | Message::kFlagIsResponse)) { - // Version 1 - InitializeMessage(sizeof(MessageHeaderV1) + payload_size); - - MessageHeaderV1* header; - Allocate(message_.buffer(), &header); - header->version = 1; - header->name = name; - header->flags = flags; - } else { - InitializeMessage(sizeof(MessageHeader) + payload_size); - - MessageHeader* header; - Allocate(message_.buffer(), &header); - header->version = 0; - header->name = name; - header->flags = flags; - } -} - -MessageBuilder::~MessageBuilder() { -} - -void MessageBuilder::InitializeMessage(size_t size) { - message_.Initialize(static_cast<uint32_t>(Align(size)), - true /* zero_initialized */); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_builder.h b/mojo/public/cpp/bindings/lib/message_builder.h deleted file mode 100644 index 8a4d5c4..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class Message; - -namespace internal { - -class Buffer; - -class MOJO_CPP_BINDINGS_EXPORT MessageBuilder { - public: - MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count); - ~MessageBuilder(); - - Buffer* buffer() { return message_.buffer(); } - Message* message() { return &message_; } - - private: - void InitializeMessage(size_t size); - - Message message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuilder); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ diff --git a/mojo/public/cpp/bindings/lib/message_header_validator.cc b/mojo/public/cpp/bindings/lib/message_header_validator.cc deleted file mode 100644 index 9f8c627..0000000 --- a/mojo/public/cpp/bindings/lib/message_header_validator.cc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/message_header_validator.h" - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace { - -// TODO(yzshen): Define a mojom struct for message header and use the generated -// validation and data view code. -bool IsValidMessageHeader(const internal::MessageHeader* header, - internal::ValidationContext* validation_context) { - // NOTE: Our goal is to preserve support for future extension of the message - // header. If we encounter fields we do not understand, we must ignore them. - - // Extra validation of the struct header: - do { - if (header->version == 0) { - if (header->num_bytes == sizeof(internal::MessageHeader)) - break; - } else if (header->version == 1) { - if (header->num_bytes == sizeof(internal::MessageHeaderV1)) - break; - } else if (header->version == 2) { - if (header->num_bytes == sizeof(internal::MessageHeaderV2)) - break; - } else if (header->version > 2) { - if (header->num_bytes >= sizeof(internal::MessageHeaderV2)) - break; - } - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } while (false); - - // Validate flags (allow unknown bits): - - // These flags require a RequestID. - constexpr uint32_t kRequestIdFlags = - Message::kFlagExpectsResponse | Message::kFlagIsResponse; - if (header->version == 0 && (header->flags & kRequestIdFlags)) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID); - return false; - } - - // These flags are mutually exclusive. - if ((header->flags & kRequestIdFlags) == kRequestIdFlags) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - - if (header->version < 2) - return true; - - auto* header_v2 = static_cast<const internal::MessageHeaderV2*>(header); - // For the payload pointer: - // - Check that the pointer can be safely decoded. - // - Claim one byte that the pointer points to. It makes sure not only the - // address is within the message, but also the address precedes the array - // storing interface IDs (which is important for safely calculating the - // payload size). - // - Validation of the payload contents will be done separately based on the - // payload type. - if (!header_v2->payload.is_null() && - (!internal::ValidatePointer(header_v2->payload, validation_context) || - !validation_context->ClaimMemory(header_v2->payload.Get(), 1))) { - return false; - } - - const internal::ContainerValidateParams validate_params(0, false, nullptr); - if (!internal::ValidateContainer(header_v2->payload_interface_ids, - validation_context, &validate_params)) { - return false; - } - - if (!header_v2->payload_interface_ids.is_null()) { - size_t num_ids = header_v2->payload_interface_ids.Get()->size(); - const uint32_t* ids = header_v2->payload_interface_ids.Get()->storage(); - for (size_t i = 0; i < num_ids; ++i) { - if (!IsValidInterfaceId(ids[i]) || IsMasterInterfaceId(ids[i])) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); - return false; - } - } - } - - return true; -} - -} // namespace - -MessageHeaderValidator::MessageHeaderValidator() - : MessageHeaderValidator("MessageHeaderValidator") {} - -MessageHeaderValidator::MessageHeaderValidator(const std::string& description) - : description_(description) { -} - -void MessageHeaderValidator::SetDescription(const std::string& description) { - description_ = description; -} - -bool MessageHeaderValidator::Accept(Message* message) { - // Pass 0 as number of handles and associated endpoint handles because we - // don't expect any in the header, even if |message| contains handles. - internal::ValidationContext validation_context( - message->data(), message->data_num_bytes(), 0, 0, message, description_); - - if (!internal::ValidateStructHeaderAndClaimMemory(message->data(), - &validation_context)) - return false; - - if (!IsValidMessageHeader(message->header(), &validation_context)) - return false; - - return true; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_internal.h b/mojo/public/cpp/bindings/lib/message_internal.h deleted file mode 100644 index 6693198..0000000 --- a/mojo/public/cpp/bindings/lib/message_internal.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ - -#include <stdint.h> - -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" - -namespace mojo { - -class Message; - -namespace internal { - -template <typename T> -class Array_Data; - -#pragma pack(push, 1) - -struct MessageHeader : internal::StructHeader { - // Interface ID for identifying multiple interfaces running on the same - // message pipe. - uint32_t interface_id; - // Message name, which is scoped to the interface that the message belongs to. - uint32_t name; - // 0 or either of the enum values defined above. - uint32_t flags; - // Unused padding to make the struct size a multiple of 8 bytes. - uint32_t padding; -}; -static_assert(sizeof(MessageHeader) == 24, "Bad sizeof(MessageHeader)"); - -struct MessageHeaderV1 : MessageHeader { - // Only used if either kFlagExpectsResponse or kFlagIsResponse is set in - // order to match responses with corresponding requests. - uint64_t request_id; -}; -static_assert(sizeof(MessageHeaderV1) == 32, "Bad sizeof(MessageHeaderV1)"); - -struct MessageHeaderV2 : MessageHeaderV1 { - MessageHeaderV2(); - GenericPointer payload; - Pointer<Array_Data<uint32_t>> payload_interface_ids; -}; -static_assert(sizeof(MessageHeaderV2) == 48, "Bad sizeof(MessageHeaderV2)"); - -#pragma pack(pop) - -class MOJO_CPP_BINDINGS_EXPORT MessageDispatchContext { - public: - explicit MessageDispatchContext(Message* message); - ~MessageDispatchContext(); - - static MessageDispatchContext* current(); - - const base::Callback<void(const std::string&)>& GetBadMessageCallback(); - - private: - MessageDispatchContext* outer_context_; - Message* message_; - base::Callback<void(const std::string&)> bad_message_callback_; - - DISALLOW_COPY_AND_ASSIGN(MessageDispatchContext); -}; - -class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseSetup { - public: - static void SetCurrentSyncResponseMessage(Message* message); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc deleted file mode 100644 index ff7c678..0000000 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ /dev/null @@ -1,960 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" - -#include <stdint.h> - -#include <utility> - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/sync_event_watcher.h" - -namespace mojo { -namespace internal { - -// InterfaceEndpoint stores the information of an interface endpoint registered -// with the router. -// No one other than the router's |endpoints_| and |tasks_| should hold refs to -// this object. -class MultiplexRouter::InterfaceEndpoint - : public base::RefCountedThreadSafe<InterfaceEndpoint>, - public InterfaceEndpointController { - public: - InterfaceEndpoint(MultiplexRouter* router, InterfaceId id) - : router_(router), - id_(id), - closed_(false), - peer_closed_(false), - handle_created_(false), - client_(nullptr) {} - - // --------------------------------------------------------------------------- - // The following public methods are safe to call from any threads without - // locking. - - InterfaceId id() const { return id_; } - - // --------------------------------------------------------------------------- - // The following public methods are called under the router's lock. - - bool closed() const { return closed_; } - void set_closed() { - router_->AssertLockAcquired(); - closed_ = true; - } - - bool peer_closed() const { return peer_closed_; } - void set_peer_closed() { - router_->AssertLockAcquired(); - peer_closed_ = true; - } - - bool handle_created() const { return handle_created_; } - void set_handle_created() { - router_->AssertLockAcquired(); - handle_created_ = true; - } - - const base::Optional<DisconnectReason>& disconnect_reason() const { - return disconnect_reason_; - } - void set_disconnect_reason( - const base::Optional<DisconnectReason>& disconnect_reason) { - router_->AssertLockAcquired(); - disconnect_reason_ = disconnect_reason; - } - - base::SingleThreadTaskRunner* task_runner() const { - return task_runner_.get(); - } - - InterfaceEndpointClient* client() const { return client_; } - - void AttachClient(InterfaceEndpointClient* client, - scoped_refptr<base::SingleThreadTaskRunner> runner) { - router_->AssertLockAcquired(); - DCHECK(!client_); - DCHECK(!closed_); - DCHECK(runner->BelongsToCurrentThread()); - - task_runner_ = std::move(runner); - client_ = client; - } - - // This method must be called on the same thread as the corresponding - // AttachClient() call. - void DetachClient() { - router_->AssertLockAcquired(); - DCHECK(client_); - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(!closed_); - - task_runner_ = nullptr; - client_ = nullptr; - sync_watcher_.reset(); - } - - void SignalSyncMessageEvent() { - router_->AssertLockAcquired(); - if (sync_message_event_signaled_) - return; - sync_message_event_signaled_ = true; - if (sync_message_event_) - sync_message_event_->Signal(); - } - - void ResetSyncMessageSignal() { - router_->AssertLockAcquired(); - if (!sync_message_event_signaled_) - return; - sync_message_event_signaled_ = false; - if (sync_message_event_) - sync_message_event_->Reset(); - } - - // --------------------------------------------------------------------------- - // The following public methods (i.e., InterfaceEndpointController - // implementation) are called by the client on the same thread as the - // AttachClient() call. They are called outside of the router's lock. - - bool SendMessage(Message* message) override { - DCHECK(task_runner_->BelongsToCurrentThread()); - message->set_interface_id(id_); - return router_->connector_.Accept(message); - } - - void AllowWokenUpBySyncWatchOnSameThread() override { - DCHECK(task_runner_->BelongsToCurrentThread()); - - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); - } - - bool SyncWatch(const bool* should_stop) override { - DCHECK(task_runner_->BelongsToCurrentThread()); - - EnsureSyncWatcherExists(); - return sync_watcher_->SyncWatch(should_stop); - } - - private: - friend class base::RefCountedThreadSafe<InterfaceEndpoint>; - - ~InterfaceEndpoint() override { - router_->AssertLockAcquired(); - - DCHECK(!client_); - DCHECK(closed_); - DCHECK(peer_closed_); - DCHECK(!sync_watcher_); - } - - void OnSyncEventSignaled() { - DCHECK(task_runner_->BelongsToCurrentThread()); - scoped_refptr<MultiplexRouter> router_protector(router_); - - MayAutoLock locker(&router_->lock_); - scoped_refptr<InterfaceEndpoint> self_protector(this); - - bool more_to_process = router_->ProcessFirstSyncMessageForEndpoint(id_); - - if (!more_to_process) - ResetSyncMessageSignal(); - - // Currently there are no queued sync messages and the peer has closed so - // there won't be incoming sync messages in the future. - if (!more_to_process && peer_closed_) { - // If a SyncWatch() call (or multiple ones) of this interface endpoint is - // on the call stack, resetting the sync watcher will allow it to exit - // when the call stack unwinds to that frame. - sync_watcher_.reset(); - } - } - - void EnsureSyncWatcherExists() { - DCHECK(task_runner_->BelongsToCurrentThread()); - if (sync_watcher_) - return; - - { - MayAutoLock locker(&router_->lock_); - if (!sync_message_event_) { - sync_message_event_.emplace( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - if (sync_message_event_signaled_) - sync_message_event_->Signal(); - } - } - sync_watcher_.reset( - new SyncEventWatcher(&sync_message_event_.value(), - base::Bind(&InterfaceEndpoint::OnSyncEventSignaled, - base::Unretained(this)))); - } - - // --------------------------------------------------------------------------- - // The following members are safe to access from any threads. - - MultiplexRouter* const router_; - const InterfaceId id_; - - // --------------------------------------------------------------------------- - // The following members are accessed under the router's lock. - - // Whether the endpoint has been closed. - bool closed_; - // Whether the peer endpoint has been closed. - bool peer_closed_; - - // Whether there is already a ScopedInterfaceEndpointHandle created for this - // endpoint. - bool handle_created_; - - base::Optional<DisconnectReason> disconnect_reason_; - - // The task runner on which |client_|'s methods can be called. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // Not owned. It is null if no client is attached to this endpoint. - InterfaceEndpointClient* client_; - - // An event used to signal that sync messages are available. The event is - // initialized under the router's lock and remains unchanged afterwards. It - // may be accessed outside of the router's lock later. - base::Optional<base::WaitableEvent> sync_message_event_; - bool sync_message_event_signaled_ = false; - - // --------------------------------------------------------------------------- - // The following members are only valid while a client is attached. They are - // used exclusively on the client's thread. They may be accessed outside of - // the router's lock. - - std::unique_ptr<SyncEventWatcher> sync_watcher_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); -}; - -// MessageWrapper objects are always destroyed under the router's lock. On -// destruction, if the message it wrappers contains -// ScopedInterfaceEndpointHandles (which cannot be destructed under the -// router's lock), the wrapper unlocks to clean them up. -class MultiplexRouter::MessageWrapper { - public: - MessageWrapper() = default; - - MessageWrapper(MultiplexRouter* router, Message message) - : router_(router), value_(std::move(message)) {} - - MessageWrapper(MessageWrapper&& other) - : router_(other.router_), value_(std::move(other.value_)) {} - - ~MessageWrapper() { - if (value_.associated_endpoint_handles()->empty()) - return; - - router_->AssertLockAcquired(); - { - MayAutoUnlock unlocker(&router_->lock_); - value_.mutable_associated_endpoint_handles()->clear(); - } - } - - MessageWrapper& operator=(MessageWrapper&& other) { - router_ = other.router_; - value_ = std::move(other.value_); - return *this; - } - - Message& value() { return value_; } - - private: - MultiplexRouter* router_ = nullptr; - Message value_; - - DISALLOW_COPY_AND_ASSIGN(MessageWrapper); -}; - -struct MultiplexRouter::Task { - public: - // Doesn't take ownership of |message| but takes its contents. - static std::unique_ptr<Task> CreateMessageTask( - MessageWrapper message_wrapper) { - Task* task = new Task(MESSAGE); - task->message_wrapper = std::move(message_wrapper); - return base::WrapUnique(task); - } - static std::unique_ptr<Task> CreateNotifyErrorTask( - InterfaceEndpoint* endpoint) { - Task* task = new Task(NOTIFY_ERROR); - task->endpoint_to_notify = endpoint; - return base::WrapUnique(task); - } - - ~Task() {} - - bool IsMessageTask() const { return type == MESSAGE; } - bool IsNotifyErrorTask() const { return type == NOTIFY_ERROR; } - - MessageWrapper message_wrapper; - scoped_refptr<InterfaceEndpoint> endpoint_to_notify; - - enum Type { MESSAGE, NOTIFY_ERROR }; - Type type; - - private: - explicit Task(Type in_type) : type(in_type) {} - - DISALLOW_COPY_AND_ASSIGN(Task); -}; - -MultiplexRouter::MultiplexRouter( - ScopedMessagePipeHandle message_pipe, - Config config, - bool set_interface_id_namesapce_bit, - scoped_refptr<base::SingleThreadTaskRunner> runner) - : set_interface_id_namespace_bit_(set_interface_id_namesapce_bit), - task_runner_(runner), - header_validator_(nullptr), - filters_(this), - connector_(std::move(message_pipe), - config == MULTI_INTERFACE ? Connector::MULTI_THREADED_SEND - : Connector::SINGLE_THREADED_SEND, - std::move(runner)), - control_message_handler_(this), - control_message_proxy_(&connector_), - next_interface_id_value_(1), - posted_to_process_tasks_(false), - encountered_error_(false), - paused_(false), - testing_mode_(false) { - DCHECK(task_runner_->BelongsToCurrentThread()); - - if (config == MULTI_INTERFACE) - lock_.emplace(); - - if (config == SINGLE_INTERFACE_WITH_SYNC_METHODS || - config == MULTI_INTERFACE) { - // Always participate in sync handle watching in multi-interface mode, - // because even if it doesn't expect sync requests during sync handle - // watching, it may still need to dispatch messages to associated endpoints - // on a different thread. - connector_.AllowWokenUpBySyncWatchOnSameThread(); - } - connector_.set_incoming_receiver(&filters_); - connector_.set_connection_error_handler( - base::Bind(&MultiplexRouter::OnPipeConnectionError, - base::Unretained(this))); - - std::unique_ptr<MessageHeaderValidator> header_validator = - base::MakeUnique<MessageHeaderValidator>(); - header_validator_ = header_validator.get(); - filters_.Append(std::move(header_validator)); -} - -MultiplexRouter::~MultiplexRouter() { - MayAutoLock locker(&lock_); - - sync_message_tasks_.clear(); - tasks_.clear(); - - for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { - InterfaceEndpoint* endpoint = iter->second.get(); - // Increment the iterator before calling UpdateEndpointStateMayRemove() - // because it may remove the corresponding value from the map. - ++iter; - - if (!endpoint->closed()) { - // This happens when a NotifyPeerEndpointClosed message been received, but - // the interface ID hasn't been used to create local endpoint handle. - DCHECK(!endpoint->client()); - DCHECK(endpoint->peer_closed()); - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - } else { - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - } - - DCHECK(endpoints_.empty()); -} - -void MultiplexRouter::SetMasterInterfaceName(const char* name) { - DCHECK(thread_checker_.CalledOnValidThread()); - header_validator_->SetDescription( - std::string(name) + " [master] MessageHeaderValidator"); - control_message_handler_.SetDescription( - std::string(name) + " [master] PipeControlMessageHandler"); - connector_.SetWatcherHeapProfilerTag(name); -} - -InterfaceId MultiplexRouter::AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) { - if (!handle_to_send.pending_association()) - return kInvalidInterfaceId; - - uint32_t id = 0; - { - MayAutoLock locker(&lock_); - do { - if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) - next_interface_id_value_ = 1; - id = next_interface_id_value_++; - if (set_interface_id_namespace_bit_) - id |= kInterfaceIdNamespaceMask; - } while (base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); - endpoints_[id] = endpoint; - if (encountered_error_) - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - endpoint->set_handle_created(); - } - - if (!NotifyAssociation(&handle_to_send, id)) { - // The peer handle of |handle_to_send|, which is supposed to join this - // associated group, has been closed. - { - MayAutoLock locker(&lock_); - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (endpoint) - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - } - - control_message_proxy_.NotifyPeerEndpointClosed( - id, handle_to_send.disconnect_reason()); - } - return id; -} - -ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( - InterfaceId id) { - if (!IsValidInterfaceId(id)) - return ScopedInterfaceEndpointHandle(); - - MayAutoLock locker(&lock_); - bool inserted = false; - InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); - if (inserted) { - DCHECK(!endpoint->handle_created()); - - if (encountered_error_) - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } else { - // If the endpoint already exist, it is because we have received a - // notification that the peer endpoint has closed. - CHECK(!endpoint->closed()); - CHECK(endpoint->peer_closed()); - - if (endpoint->handle_created()) - return ScopedInterfaceEndpointHandle(); - } - - endpoint->set_handle_created(); - return CreateScopedInterfaceEndpointHandle(id); -} - -void MultiplexRouter::CloseEndpointHandle( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) { - if (!IsValidInterfaceId(id)) - return; - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - InterfaceEndpoint* endpoint = endpoints_[id].get(); - DCHECK(!endpoint->client()); - DCHECK(!endpoint->closed()); - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - - if (!IsMasterInterfaceId(id) || reason) { - MayAutoUnlock unlocker(&lock_); - control_message_proxy_.NotifyPeerEndpointClosed(id, reason); - } - - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); -} - -InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* client, - scoped_refptr<base::SingleThreadTaskRunner> runner) { - const InterfaceId id = handle.id(); - - DCHECK(IsValidInterfaceId(id)); - DCHECK(client); - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = endpoints_[id].get(); - endpoint->AttachClient(client, std::move(runner)); - - if (endpoint->peer_closed()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); - - return endpoint; -} - -void MultiplexRouter::DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) { - const InterfaceId id = handle.id(); - - DCHECK(IsValidInterfaceId(id)); - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = endpoints_[id].get(); - endpoint->DetachClient(); -} - -void MultiplexRouter::RaiseError() { - if (task_runner_->BelongsToCurrentThread()) { - connector_.RaiseError(); - } else { - task_runner_->PostTask(FROM_HERE, - base::Bind(&MultiplexRouter::RaiseError, this)); - } -} - -void MultiplexRouter::CloseMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.CloseMessagePipe(); - // CloseMessagePipe() above won't trigger connection error handler. - // Explicitly call OnPipeConnectionError() so that associated endpoints will - // get notified. - OnPipeConnectionError(); -} - -void MultiplexRouter::PauseIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.PauseIncomingMethodCallProcessing(); - - MayAutoLock locker(&lock_); - paused_ = true; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) - iter->second->ResetSyncMessageSignal(); -} - -void MultiplexRouter::ResumeIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.ResumeIncomingMethodCallProcessing(); - - MayAutoLock locker(&lock_); - paused_ = false; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) { - auto sync_iter = sync_message_tasks_.find(iter->first); - if (iter->second->peer_closed() || - (sync_iter != sync_message_tasks_.end() && - !sync_iter->second.empty())) { - iter->second->SignalSyncMessageEvent(); - } - } - - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); -} - -bool MultiplexRouter::HasAssociatedEndpoints() const { - DCHECK(thread_checker_.CalledOnValidThread()); - MayAutoLock locker(&lock_); - - if (endpoints_.size() > 1) - return true; - if (endpoints_.size() == 0) - return false; - - return !base::ContainsKey(endpoints_, kMasterInterfaceId); -} - -void MultiplexRouter::EnableTestingMode() { - DCHECK(thread_checker_.CalledOnValidThread()); - MayAutoLock locker(&lock_); - - testing_mode_ = true; - connector_.set_enforce_errors_from_incoming_receiver(false); -} - -bool MultiplexRouter::Accept(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!message->DeserializeAssociatedEndpointHandles(this)) - return false; - - scoped_refptr<MultiplexRouter> protector(this); - MayAutoLock locker(&lock_); - - DCHECK(!paused_); - - ClientCallBehavior client_call_behavior = - connector_.during_sync_handle_watcher_callback() - ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES - : ALLOW_DIRECT_CLIENT_CALLS; - - bool processed = - tasks_.empty() && ProcessIncomingMessage(message, client_call_behavior, - connector_.task_runner()); - - if (!processed) { - // Either the task queue is not empty or we cannot process the message - // directly. In both cases, there is no need to call ProcessTasks(). - tasks_.push_back( - Task::CreateMessageTask(MessageWrapper(this, std::move(*message)))); - Task* task = tasks_.back().get(); - - if (task->message_wrapper.value().has_flag(Message::kFlagIsSync)) { - InterfaceId id = task->message_wrapper.value().interface_id(); - sync_message_tasks_[id].push_back(task); - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (endpoint) - endpoint->SignalSyncMessageEvent(); - } - } else if (!tasks_.empty()) { - // Processing the message may result in new tasks (for error notification) - // being added to the queue. In this case, we have to attempt to process the - // tasks. - ProcessTasks(client_call_behavior, connector_.task_runner()); - } - - // Always return true. If we see errors during message processing, we will - // explicitly call Connector::RaiseError() to disconnect the message pipe. - return true; -} - -bool MultiplexRouter::OnPeerAssociatedEndpointClosed( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) { - DCHECK(!IsMasterInterfaceId(id) || reason); - - MayAutoLock locker(&lock_); - InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, nullptr); - - if (reason) - endpoint->set_disconnect_reason(reason); - - // It is possible that this endpoint has been set as peer closed. That is - // because when the message pipe is closed, all the endpoints are updated with - // PEER_ENDPOINT_CLOSED. We continue to process remaining tasks in the queue, - // as long as there are refs keeping the router alive. If there is a - // PeerAssociatedEndpointClosedEvent control message in the queue, we will get - // here and see that the endpoint has been marked as peer closed. - if (!endpoint->peer_closed()) { - if (endpoint->client()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - - // No need to trigger a ProcessTasks() because it is already on the stack. - - return true; -} - -void MultiplexRouter::OnPipeConnectionError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - scoped_refptr<MultiplexRouter> protector(this); - MayAutoLock locker(&lock_); - - encountered_error_ = true; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { - InterfaceEndpoint* endpoint = iter->second.get(); - // Increment the iterator before calling UpdateEndpointStateMayRemove() - // because it may remove the corresponding value from the map. - ++iter; - - if (endpoint->client()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - - ProcessTasks(connector_.during_sync_handle_watcher_callback() - ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES - : ALLOW_DIRECT_CLIENT_CALLS, - connector_.task_runner()); -} - -void MultiplexRouter::ProcessTasks( - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - AssertLockAcquired(); - - if (posted_to_process_tasks_) - return; - - while (!tasks_.empty() && !paused_) { - std::unique_ptr<Task> task(std::move(tasks_.front())); - tasks_.pop_front(); - - InterfaceId id = kInvalidInterfaceId; - bool sync_message = - task->IsMessageTask() && !task->message_wrapper.value().IsNull() && - task->message_wrapper.value().has_flag(Message::kFlagIsSync); - if (sync_message) { - id = task->message_wrapper.value().interface_id(); - auto& sync_message_queue = sync_message_tasks_[id]; - DCHECK_EQ(task.get(), sync_message_queue.front()); - sync_message_queue.pop_front(); - } - - bool processed = - task->IsNotifyErrorTask() - ? ProcessNotifyErrorTask(task.get(), client_call_behavior, - current_task_runner) - : ProcessIncomingMessage(&task->message_wrapper.value(), - client_call_behavior, current_task_runner); - - if (!processed) { - if (sync_message) { - auto& sync_message_queue = sync_message_tasks_[id]; - sync_message_queue.push_front(task.get()); - } - tasks_.push_front(std::move(task)); - break; - } else { - if (sync_message) { - auto iter = sync_message_tasks_.find(id); - if (iter != sync_message_tasks_.end() && iter->second.empty()) - sync_message_tasks_.erase(iter); - } - } - } -} - -bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) { - AssertLockAcquired(); - - auto iter = sync_message_tasks_.find(id); - if (iter == sync_message_tasks_.end()) - return false; - - if (paused_) - return true; - - MultiplexRouter::Task* task = iter->second.front(); - iter->second.pop_front(); - - DCHECK(task->IsMessageTask()); - MessageWrapper message_wrapper = std::move(task->message_wrapper); - - // Note: after this call, |task| and |iter| may be invalidated. - bool processed = ProcessIncomingMessage( - &message_wrapper.value(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, - nullptr); - DCHECK(processed); - - iter = sync_message_tasks_.find(id); - if (iter == sync_message_tasks_.end()) - return false; - - if (iter->second.empty()) { - sync_message_tasks_.erase(iter); - return false; - } - - return true; -} - -bool MultiplexRouter::ProcessNotifyErrorTask( - Task* task, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); - DCHECK(!paused_); - - AssertLockAcquired(); - InterfaceEndpoint* endpoint = task->endpoint_to_notify.get(); - if (!endpoint->client()) - return true; - - if (client_call_behavior != ALLOW_DIRECT_CLIENT_CALLS || - endpoint->task_runner() != current_task_runner) { - MaybePostToProcessTasks(endpoint->task_runner()); - return false; - } - - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); - - InterfaceEndpointClient* client = endpoint->client(); - base::Optional<DisconnectReason> disconnect_reason( - endpoint->disconnect_reason()); - - { - // We must unlock before calling into |client| because it may call this - // object within NotifyError(). Holding the lock will lead to deadlock. - // - // It is safe to call into |client| without the lock. Because |client| is - // always accessed on the same thread, including DetachEndpointClient(). - MayAutoUnlock unlocker(&lock_); - client->NotifyError(disconnect_reason); - } - return true; -} - -bool MultiplexRouter::ProcessIncomingMessage( - Message* message, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); - DCHECK(!paused_); - DCHECK(message); - AssertLockAcquired(); - - if (message->IsNull()) { - // This is a sync message and has been processed during sync handle - // watching. - return true; - } - - if (PipeControlMessageHandler::IsPipeControlMessage(message)) { - bool result = false; - - { - MayAutoUnlock unlocker(&lock_); - result = control_message_handler_.Accept(message); - } - - if (!result) - RaiseErrorInNonTestingMode(); - - return true; - } - - InterfaceId id = message->interface_id(); - DCHECK(IsValidInterfaceId(id)); - - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (!endpoint || endpoint->closed()) - return true; - - if (!endpoint->client()) { - // We need to wait until a client is attached in order to dispatch further - // messages. - return false; - } - - bool can_direct_call; - if (message->has_flag(Message::kFlagIsSync)) { - can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS && - endpoint->task_runner()->BelongsToCurrentThread(); - } else { - can_direct_call = client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS && - endpoint->task_runner() == current_task_runner; - } - - if (!can_direct_call) { - MaybePostToProcessTasks(endpoint->task_runner()); - return false; - } - - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); - - InterfaceEndpointClient* client = endpoint->client(); - bool result = false; - { - // We must unlock before calling into |client| because it may call this - // object within HandleIncomingMessage(). Holding the lock will lead to - // deadlock. - // - // It is safe to call into |client| without the lock. Because |client| is - // always accessed on the same thread, including DetachEndpointClient(). - MayAutoUnlock unlocker(&lock_); - result = client->HandleIncomingMessage(message); - } - if (!result) - RaiseErrorInNonTestingMode(); - - return true; -} - -void MultiplexRouter::MaybePostToProcessTasks( - base::SingleThreadTaskRunner* task_runner) { - AssertLockAcquired(); - if (posted_to_process_tasks_) - return; - - posted_to_process_tasks_ = true; - posted_to_task_runner_ = task_runner; - task_runner->PostTask( - FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); -} - -void MultiplexRouter::LockAndCallProcessTasks() { - // There is no need to hold a ref to this class in this case because this is - // always called using base::Bind(), which holds a ref. - MayAutoLock locker(&lock_); - posted_to_process_tasks_ = false; - scoped_refptr<base::SingleThreadTaskRunner> runner( - std::move(posted_to_task_runner_)); - ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS, runner.get()); -} - -void MultiplexRouter::UpdateEndpointStateMayRemove( - InterfaceEndpoint* endpoint, - EndpointStateUpdateType type) { - if (type == ENDPOINT_CLOSED) { - endpoint->set_closed(); - } else { - endpoint->set_peer_closed(); - // If the interface endpoint is performing a sync watch, this makes sure - // it is notified and eventually exits the sync watch. - endpoint->SignalSyncMessageEvent(); - } - if (endpoint->closed() && endpoint->peer_closed()) - endpoints_.erase(endpoint->id()); -} - -void MultiplexRouter::RaiseErrorInNonTestingMode() { - AssertLockAcquired(); - if (!testing_mode_) - RaiseError(); -} - -MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint( - InterfaceId id, - bool* inserted) { - AssertLockAcquired(); - // Either |inserted| is nullptr or it points to a boolean initialized as - // false. - DCHECK(!inserted || !*inserted); - - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (!endpoint) { - endpoint = new InterfaceEndpoint(this, id); - endpoints_[id] = endpoint; - if (inserted) - *inserted = true; - } - - return endpoint; -} - -MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindEndpoint( - InterfaceId id) { - AssertLockAcquired(); - auto iter = endpoints_.find(id); - return iter != endpoints_.end() ? iter->second.get() : nullptr; -} - -void MultiplexRouter::AssertLockAcquired() { -#if DCHECK_IS_ON() - if (lock_) - lock_->AssertAcquired(); -#endif -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h deleted file mode 100644 index cac138b..0000000 --- a/mojo/public/cpp/bindings/lib/multiplex_router.h +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ - -#include <stdint.h> - -#include <deque> -#include <map> -#include <memory> -#include <string> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connector.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace mojo { - -namespace internal { - -// MultiplexRouter supports routing messages for multiple interfaces over a -// single message pipe. -// -// It is created on the thread where the master interface of the message pipe -// lives. Although it is ref-counted, it is guarateed to be destructed on the -// same thread. -// Some public methods are only allowed to be called on the creating thread; -// while the others are safe to call from any threads. Please see the method -// comments for more details. -// -// NOTE: CloseMessagePipe() or PassMessagePipe() MUST be called on |runner|'s -// thread before this object is destroyed. -class MOJO_CPP_BINDINGS_EXPORT MultiplexRouter - : NON_EXPORTED_BASE(public MessageReceiver), - public AssociatedGroupController, - NON_EXPORTED_BASE(public PipeControlMessageHandlerDelegate) { - public: - enum Config { - // There is only the master interface running on this router. Please note - // that because of interface versioning, the other side of the message pipe - // may use a newer master interface definition which passes associated - // interfaces. In that case, this router may still receive pipe control - // messages or messages targetting associated interfaces. - SINGLE_INTERFACE, - // Similar to the mode above, there is only the master interface running on - // this router. Besides, the master interface has sync methods. - SINGLE_INTERFACE_WITH_SYNC_METHODS, - // There may be associated interfaces running on this router. - MULTI_INTERFACE - }; - - // If |set_interface_id_namespace_bit| is true, the interface IDs generated by - // this router will have the highest bit set. - MultiplexRouter(ScopedMessagePipeHandle message_pipe, - Config config, - bool set_interface_id_namespace_bit, - scoped_refptr<base::SingleThreadTaskRunner> runner); - - // Sets the master interface name for this router. Only used when reporting - // message header or control message validation errors. - // |name| must be a string literal. - void SetMasterInterfaceName(const char* name); - - // --------------------------------------------------------------------------- - // The following public methods are safe to call from any threads. - - // AssociatedGroupController implementation: - InterfaceId AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) override; - ScopedInterfaceEndpointHandle CreateLocalEndpointHandle( - InterfaceId id) override; - void CloseEndpointHandle( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) override; - InterfaceEndpointController* AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* endpoint_client, - scoped_refptr<base::SingleThreadTaskRunner> runner) override; - void DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) override; - void RaiseError() override; - - // --------------------------------------------------------------------------- - // The following public methods are called on the creating thread. - - // Please note that this method shouldn't be called unless it results from an - // explicit request of the user of bindings (e.g., the user sets an - // InterfacePtr to null or closes a Binding). - void CloseMessagePipe(); - - // Extracts the underlying message pipe. - ScopedMessagePipeHandle PassMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!HasAssociatedEndpoints()); - return connector_.PassMessagePipe(); - } - - // Blocks the current thread until the first incoming message, or |deadline|. - bool WaitForIncomingMessage(MojoDeadline deadline) { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.WaitForIncomingMessage(deadline); - } - - // See Binding for details of pause/resume. - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - // Whether there are any associated interfaces running currently. - bool HasAssociatedEndpoints() const; - - // Sets this object to testing mode. - // In testing mode, the object doesn't disconnect the underlying message pipe - // when it receives unexpected or invalid messages. - void EnableTestingMode(); - - // Is the router bound to a message pipe handle? - bool is_valid() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.is_valid(); - } - - // TODO(yzshen): consider removing this getter. - MessagePipeHandle handle() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.handle(); - } - - bool SimulateReceivingMessageForTesting(Message* message) { - return filters_.Accept(message); - } - - private: - class InterfaceEndpoint; - class MessageWrapper; - struct Task; - - ~MultiplexRouter() override; - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - // PipeControlMessageHandlerDelegate implementation: - bool OnPeerAssociatedEndpointClosed( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) override; - - void OnPipeConnectionError(); - - // Specifies whether we are allowed to directly call into - // InterfaceEndpointClient (given that we are already on the same thread as - // the client). - enum ClientCallBehavior { - // Don't call any InterfaceEndpointClient methods directly. - NO_DIRECT_CLIENT_CALLS, - // Only call InterfaceEndpointClient::HandleIncomingMessage directly to - // handle sync messages. - ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, - // Allow to call any InterfaceEndpointClient methods directly. - ALLOW_DIRECT_CLIENT_CALLS - }; - - // Processes enqueued tasks (incoming messages and error notifications). - // |current_task_runner| is only used when |client_call_behavior| is - // ALLOW_DIRECT_CLIENT_CALLS to determine whether we are on the right task - // runner to make client calls for async messages or connection error - // notifications. - // - // Note: Because calling into InterfaceEndpointClient may lead to destruction - // of this object, if direct calls are allowed, the caller needs to hold on to - // a ref outside of |lock_| before calling this method. - void ProcessTasks(ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - - // Processes the first queued sync message for the endpoint corresponding to - // |id|; returns whether there are more sync messages for that endpoint in the - // queue. - // - // This method is only used by enpoints during sync watching. Therefore, not - // all sync messages are handled by it. - bool ProcessFirstSyncMessageForEndpoint(InterfaceId id); - - // Returns true to indicate that |task|/|message| has been processed. - bool ProcessNotifyErrorTask( - Task* task, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - bool ProcessIncomingMessage( - Message* message, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - - void MaybePostToProcessTasks(base::SingleThreadTaskRunner* task_runner); - void LockAndCallProcessTasks(); - - // Updates the state of |endpoint|. If both the endpoint and its peer have - // been closed, removes it from |endpoints_|. - // NOTE: The method may invalidate |endpoint|. - enum EndpointStateUpdateType { ENDPOINT_CLOSED, PEER_ENDPOINT_CLOSED }; - void UpdateEndpointStateMayRemove(InterfaceEndpoint* endpoint, - EndpointStateUpdateType type); - - void RaiseErrorInNonTestingMode(); - - InterfaceEndpoint* FindOrInsertEndpoint(InterfaceId id, bool* inserted); - InterfaceEndpoint* FindEndpoint(InterfaceId id); - - void AssertLockAcquired(); - - // Whether to set the namespace bit when generating interface IDs. Please see - // comments of kInterfaceIdNamespaceMask. - const bool set_interface_id_namespace_bit_; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - // Owned by |filters_| below. - MessageHeaderValidator* header_validator_; - - FilterChain filters_; - Connector connector_; - - base::ThreadChecker thread_checker_; - - // Protects the following members. - // Not set in Config::SINGLE_INTERFACE* mode. - mutable base::Optional<base::Lock> lock_; - PipeControlMessageHandler control_message_handler_; - - // NOTE: It is unsafe to call into this object while holding |lock_|. - PipeControlMessageProxy control_message_proxy_; - - std::map<InterfaceId, scoped_refptr<InterfaceEndpoint>> endpoints_; - uint32_t next_interface_id_value_; - - std::deque<std::unique_ptr<Task>> tasks_; - // It refers to tasks in |tasks_| and doesn't own any of them. - std::map<InterfaceId, std::deque<Task*>> sync_message_tasks_; - - bool posted_to_process_tasks_; - scoped_refptr<base::SingleThreadTaskRunner> posted_to_task_runner_; - - bool encountered_error_; - - bool paused_; - - bool testing_mode_; - - DISALLOW_COPY_AND_ASSIGN(MultiplexRouter); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ diff --git a/mojo/public/cpp/bindings/lib/native_enum_data.h b/mojo/public/cpp/bindings/lib/native_enum_data.h deleted file mode 100644 index dcafce2..0000000 --- a/mojo/public/cpp/bindings/lib/native_enum_data.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ - -namespace mojo { -namespace internal { - -class ValidationContext; - -class NativeEnum_Data { - public: - static bool const kIsExtensible = true; - - static bool IsKnownValue(int32_t value) { return false; } - - static bool Validate(int32_t value, - ValidationContext* validation_context) { return true; } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ diff --git a/mojo/public/cpp/bindings/lib/native_enum_serialization.h b/mojo/public/cpp/bindings/lib/native_enum_serialization.h deleted file mode 100644 index 4faf957..0000000 --- a/mojo/public/cpp/bindings/lib/native_enum_serialization.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <type_traits> - -#include "base/logging.h" -#include "base/pickle.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/native_enum.h" - -namespace mojo { -namespace internal { - -template <typename MaybeConstUserType> -struct NativeEnumSerializerImpl { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = IPC::ParamTraits<UserType>; - - // IPC_ENUM_TRAITS* macros serialize enum as int, make sure that fits into - // mojo native-only enum. - static_assert(sizeof(NativeEnum) >= sizeof(int), - "Cannot store the serialization result in NativeEnum."); - - static void Serialize(UserType input, int32_t* output) { - base::Pickle pickle; - Traits::Write(&pickle, input); - - CHECK_GE(sizeof(int32_t), pickle.payload_size()); - *output = 0; - memcpy(reinterpret_cast<char*>(output), pickle.payload(), - pickle.payload_size()); - } - - struct PickleData { - uint32_t payload_size; - int32_t value; - }; - static_assert(sizeof(PickleData) == 8, "PickleData size mismatch."); - - static bool Deserialize(int32_t input, UserType* output) { - PickleData data = {sizeof(int32_t), input}; - base::Pickle pickle_view(reinterpret_cast<const char*>(&data), - sizeof(PickleData)); - base::PickleIterator iter(pickle_view); - return Traits::Read(&pickle_view, &iter, output); - } -}; - -struct UnmappedNativeEnumSerializerImpl { - static void Serialize(NativeEnum input, int32_t* output) { - *output = static_cast<int32_t>(input); - } - static bool Deserialize(int32_t input, NativeEnum* output) { - *output = static_cast<NativeEnum>(input); - return true; - } -}; - -template <> -struct NativeEnumSerializerImpl<NativeEnum> - : public UnmappedNativeEnumSerializerImpl {}; - -template <> -struct NativeEnumSerializerImpl<const NativeEnum> - : public UnmappedNativeEnumSerializerImpl {}; - -template <typename MaybeConstUserType> -struct Serializer<NativeEnum, MaybeConstUserType> - : public NativeEnumSerializerImpl<MaybeConstUserType> {}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/native_struct.cc b/mojo/public/cpp/bindings/lib/native_struct.cc deleted file mode 100644 index 7b1a1a6..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/native_struct.h" - -#include "mojo/public/cpp/bindings/lib/hash_util.h" - -namespace mojo { - -// static -NativeStructPtr NativeStruct::New() { - return NativeStructPtr(base::in_place); -} - -NativeStruct::NativeStruct() {} - -NativeStruct::~NativeStruct() {} - -NativeStructPtr NativeStruct::Clone() const { - NativeStructPtr rv(New()); - rv->data = data; - return rv; -} - -bool NativeStruct::Equals(const NativeStruct& other) const { - return data == other.data; -} - -size_t NativeStruct::Hash(size_t seed) const { - return internal::Hash(seed, data); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.cc b/mojo/public/cpp/bindings/lib/native_struct_data.cc deleted file mode 100644 index 0e5d245..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" - -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" - -namespace mojo { -namespace internal { - -// static -bool NativeStruct_Data::Validate(const void* data, - ValidationContext* validation_context) { - const ContainerValidateParams data_validate_params(0, false, nullptr); - return Array_Data<uint8_t>::Validate(data, validation_context, - &data_validate_params); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.h b/mojo/public/cpp/bindings/lib/native_struct_data.h deleted file mode 100644 index 1c7cd81..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ - -#include <vector> - -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -class ValidationContext; - -class MOJO_CPP_BINDINGS_EXPORT NativeStruct_Data { - public: - static bool Validate(const void* data, ValidationContext* validation_context); - - // Unlike normal structs, the memory layout is exactly the same as an array - // of uint8_t. - Array_Data<uint8_t> data; - - private: - NativeStruct_Data() = delete; - ~NativeStruct_Data() = delete; -}; - -static_assert(sizeof(Array_Data<uint8_t>) == sizeof(NativeStruct_Data), - "Mismatched NativeStruct_Data and Array_Data<uint8_t> size"); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc deleted file mode 100644 index fa0dbf3..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" - -#include "mojo/public/cpp/bindings/lib/serialization.h" - -namespace mojo { -namespace internal { - -// static -size_t UnmappedNativeStructSerializerImpl::PrepareToSerialize( - const NativeStructPtr& input, - SerializationContext* context) { - if (!input) - return 0; - return internal::PrepareToSerialize<ArrayDataView<uint8_t>>(input->data, - context); -} - -// static -void UnmappedNativeStructSerializerImpl::Serialize( - const NativeStructPtr& input, - Buffer* buffer, - NativeStruct_Data** output, - SerializationContext* context) { - if (!input) { - *output = nullptr; - return; - } - - Array_Data<uint8_t>* data = nullptr; - const ContainerValidateParams params(0, false, nullptr); - internal::Serialize<ArrayDataView<uint8_t>>(input->data, buffer, &data, - ¶ms, context); - *output = reinterpret_cast<NativeStruct_Data*>(data); -} - -// static -bool UnmappedNativeStructSerializerImpl::Deserialize( - NativeStruct_Data* input, - NativeStructPtr* output, - SerializationContext* context) { - Array_Data<uint8_t>* data = reinterpret_cast<Array_Data<uint8_t>*>(input); - - NativeStructPtr result(NativeStruct::New()); - if (!internal::Deserialize<ArrayDataView<uint8_t>>(data, &result->data, - context)) { - output = nullptr; - return false; - } - if (!result->data) - *output = nullptr; - else - result.Swap(output); - return true; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/mojo/public/cpp/bindings/lib/native_struct_serialization.h deleted file mode 100644 index 457435b..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "base/logging.h" -#include "base/pickle.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/native_struct.h" -#include "mojo/public/cpp/bindings/native_struct_data_view.h" - -namespace mojo { -namespace internal { - -template <typename MaybeConstUserType> -struct NativeStructSerializerImpl { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = IPC::ParamTraits<UserType>; - - static size_t PrepareToSerialize(MaybeConstUserType& value, - SerializationContext* context) { - base::PickleSizer sizer; - Traits::GetSize(&sizer, value); - return Align(sizer.payload_size() + sizeof(ArrayHeader)); - } - - static void Serialize(MaybeConstUserType& value, - Buffer* buffer, - NativeStruct_Data** out, - SerializationContext* context) { - base::Pickle pickle; - Traits::Write(&pickle, value); - -#if DCHECK_IS_ON() - base::PickleSizer sizer; - Traits::GetSize(&sizer, value); - DCHECK_EQ(sizer.payload_size(), pickle.payload_size()); -#endif - - size_t total_size = pickle.payload_size() + sizeof(ArrayHeader); - DCHECK_LT(total_size, std::numeric_limits<uint32_t>::max()); - - // Allocate a uint8 array, initialize its header, and copy the Pickle in. - ArrayHeader* header = - reinterpret_cast<ArrayHeader*>(buffer->Allocate(total_size)); - header->num_bytes = static_cast<uint32_t>(total_size); - header->num_elements = static_cast<uint32_t>(pickle.payload_size()); - memcpy(reinterpret_cast<char*>(header) + sizeof(ArrayHeader), - pickle.payload(), pickle.payload_size()); - - *out = reinterpret_cast<NativeStruct_Data*>(header); - } - - static bool Deserialize(NativeStruct_Data* data, - UserType* out, - SerializationContext* context) { - if (!data) - return false; - - // Construct a temporary base::Pickle view over the array data. Note that - // the Array_Data is laid out like this: - // - // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] - // - // and base::Pickle expects to view data like this: - // - // [payload_size (4 bytes)] [header bytes ...] [payload...] - // - // Because ArrayHeader's num_bytes includes the length of the header and - // Pickle's payload_size does not, we need to adjust the stored value - // momentarily so Pickle can view the data. - ArrayHeader* header = reinterpret_cast<ArrayHeader*>(data); - DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); - header->num_bytes -= sizeof(ArrayHeader); - - { - // Construct a view over the full Array_Data, including our hacked up - // header. Pickle will infer from this that the header is 8 bytes long, - // and the payload will contain all of the pickled bytes. - base::Pickle pickle_view(reinterpret_cast<const char*>(header), - header->num_bytes + sizeof(ArrayHeader)); - base::PickleIterator iter(pickle_view); - if (!Traits::Read(&pickle_view, &iter, out)) - return false; - } - - // Return the header to its original state. - header->num_bytes += sizeof(ArrayHeader); - - return true; - } -}; - -struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { - static size_t PrepareToSerialize(const NativeStructPtr& input, - SerializationContext* context); - static void Serialize(const NativeStructPtr& input, - Buffer* buffer, - NativeStruct_Data** output, - SerializationContext* context); - static bool Deserialize(NativeStruct_Data* input, - NativeStructPtr* output, - SerializationContext* context); -}; - -template <> -struct NativeStructSerializerImpl<NativeStructPtr> - : public UnmappedNativeStructSerializerImpl {}; - -template <> -struct NativeStructSerializerImpl<const NativeStructPtr> - : public UnmappedNativeStructSerializerImpl {}; - -template <typename MaybeConstUserType> -struct Serializer<NativeStructDataView, MaybeConstUserType> - : public NativeStructSerializerImpl<MaybeConstUserType> {}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc deleted file mode 100644 index d451c05..0000000 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/pipe_control_message_handler.h" - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" -#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" - -namespace mojo { - -PipeControlMessageHandler::PipeControlMessageHandler( - PipeControlMessageHandlerDelegate* delegate) - : delegate_(delegate) {} - -PipeControlMessageHandler::~PipeControlMessageHandler() {} - -void PipeControlMessageHandler::SetDescription(const std::string& description) { - description_ = description; -} - -// static -bool PipeControlMessageHandler::IsPipeControlMessage(const Message* message) { - return !IsValidInterfaceId(message->interface_id()); -} - -bool PipeControlMessageHandler::Accept(Message* message) { - if (!Validate(message)) - return false; - - if (message->name() == pipe_control::kRunOrClosePipeMessageId) - return RunOrClosePipe(message); - - NOTREACHED(); - return false; -} - -bool PipeControlMessageHandler::Validate(Message* message) { - internal::ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), - 0, 0, message, description_); - - if (message->name() == pipe_control::kRunOrClosePipeMessageId) { - if (!internal::ValidateMessageIsRequestWithoutResponse( - message, &validation_context)) { - return false; - } - return internal::ValidateMessagePayload< - pipe_control::internal::RunOrClosePipeMessageParams_Data>( - message, &validation_context); - } - - return false; -} - -bool PipeControlMessageHandler::RunOrClosePipe(Message* message) { - internal::SerializationContext context; - pipe_control::internal::RunOrClosePipeMessageParams_Data* params = - reinterpret_cast< - pipe_control::internal::RunOrClosePipeMessageParams_Data*>( - message->mutable_payload()); - pipe_control::RunOrClosePipeMessageParamsPtr params_ptr; - internal::Deserialize<pipe_control::RunOrClosePipeMessageParamsDataView>( - params, ¶ms_ptr, &context); - - if (params_ptr->input->is_peer_associated_endpoint_closed_event()) { - const auto& event = - params_ptr->input->get_peer_associated_endpoint_closed_event(); - - base::Optional<DisconnectReason> reason; - if (event->disconnect_reason) { - reason.emplace(event->disconnect_reason->custom_reason, - event->disconnect_reason->description); - } - return delegate_->OnPeerAssociatedEndpointClosed(event->id, reason); - } - - DVLOG(1) << "Unsupported command in a RunOrClosePipe message pipe control " - << "message. Closing the pipe."; - return false; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc deleted file mode 100644 index 1029c2c..0000000 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" - -#include <stddef.h> -#include <utility> - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" - -namespace mojo { -namespace { - -Message ConstructRunOrClosePipeMessage( - pipe_control::RunOrClosePipeInputPtr input_ptr) { - internal::SerializationContext context; - - auto params_ptr = pipe_control::RunOrClosePipeMessageParams::New(); - params_ptr->input = std::move(input_ptr); - - size_t size = internal::PrepareToSerialize< - pipe_control::RunOrClosePipeMessageParamsDataView>(params_ptr, &context); - internal::MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId, 0, - size, 0); - - pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr; - internal::Serialize<pipe_control::RunOrClosePipeMessageParamsDataView>( - params_ptr, builder.buffer(), ¶ms, &context); - builder.message()->set_interface_id(kInvalidInterfaceId); - return std::move(*builder.message()); -} - -} // namespace - -PipeControlMessageProxy::PipeControlMessageProxy(MessageReceiver* receiver) - : receiver_(receiver) {} - -void PipeControlMessageProxy::NotifyPeerEndpointClosed( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) { - Message message(ConstructPeerEndpointClosedMessage(id, reason)); - ignore_result(receiver_->Accept(&message)); -} - -// static -Message PipeControlMessageProxy::ConstructPeerEndpointClosedMessage( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) { - auto event = pipe_control::PeerAssociatedEndpointClosedEvent::New(); - event->id = id; - if (reason) { - event->disconnect_reason = pipe_control::DisconnectReason::New(); - event->disconnect_reason->custom_reason = reason->custom_reason; - event->disconnect_reason->description = reason->description; - } - - auto input = pipe_control::RunOrClosePipeInput::New(); - input->set_peer_associated_endpoint_closed_event(std::move(event)); - - return ConstructRunOrClosePipeMessage(std::move(input)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc deleted file mode 100644 index c134507..0000000 --- a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" - -namespace mojo { - -// ScopedInterfaceEndpointHandle::State ---------------------------------------- - -// State could be called from multiple threads. -class ScopedInterfaceEndpointHandle::State - : public base::RefCountedThreadSafe<State> { - public: - State() = default; - - State(InterfaceId id, - scoped_refptr<AssociatedGroupController> group_controller) - : id_(id), group_controller_(group_controller) {} - - void InitPendingState(scoped_refptr<State> peer) { - DCHECK(!lock_); - DCHECK(!pending_association_); - - lock_.emplace(); - pending_association_ = true; - peer_state_ = std::move(peer); - } - - void Close(const base::Optional<DisconnectReason>& reason) { - scoped_refptr<AssociatedGroupController> cached_group_controller; - InterfaceId cached_id = kInvalidInterfaceId; - scoped_refptr<State> cached_peer_state; - - { - internal::MayAutoLock locker(&lock_); - - if (!association_event_handler_.is_null()) { - association_event_handler_.Reset(); - runner_ = nullptr; - } - - if (!pending_association_) { - if (IsValidInterfaceId(id_)) { - // Intentionally keep |group_controller_| unchanged. - // That is because the callback created by - // CreateGroupControllerGetter() could still be used after this point, - // potentially from another thread. We would like it to continue - // returning the same group controller. - // - // Imagine there is a ThreadSafeForwarder A: - // (1) On the IO thread, A's underlying associated interface pointer - // is closed. - // (2) On the proxy thread, the user makes a call on A to pass an - // associated request B_asso_req. The callback returned by - // CreateGroupControllerGetter() is used to associate B_asso_req. - // (3) On the proxy thread, the user immediately binds B_asso_ptr_info - // to B_asso_ptr and makes calls on it. - // - // If we reset |group_controller_| in step (1), step (2) won't be able - // to associate B_asso_req. Therefore, in step (3) B_asso_ptr won't be - // able to serialize associated endpoints or send message because it - // is still in "pending_association" state and doesn't have a group - // controller. - // - // We could "address" this issue by ignoring messages if there isn't a - // group controller. But the side effect is that we cannot detect - // programming errors of "using associated interface pointer before - // sending associated request". - - cached_group_controller = group_controller_; - cached_id = id_; - id_ = kInvalidInterfaceId; - } - } else { - pending_association_ = false; - cached_peer_state = std::move(peer_state_); - } - } - - if (cached_group_controller) { - cached_group_controller->CloseEndpointHandle(cached_id, reason); - } else if (cached_peer_state) { - cached_peer_state->OnPeerClosedBeforeAssociation(reason); - } - } - - void SetAssociationEventHandler(AssociationEventCallback handler) { - internal::MayAutoLock locker(&lock_); - - if (!pending_association_ && !IsValidInterfaceId(id_)) - return; - - association_event_handler_ = std::move(handler); - if (association_event_handler_.is_null()) { - runner_ = nullptr; - return; - } - - runner_ = base::ThreadTaskRunnerHandle::Get(); - if (!pending_association_) { - runner_->PostTask( - FROM_HERE, - base::Bind( - &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler, - this, runner_, ASSOCIATED)); - } else if (!peer_state_) { - runner_->PostTask( - FROM_HERE, - base::Bind( - &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler, - this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION)); - } - } - - bool NotifyAssociation( - InterfaceId id, - scoped_refptr<AssociatedGroupController> peer_group_controller) { - scoped_refptr<State> cached_peer_state; - { - internal::MayAutoLock locker(&lock_); - - DCHECK(pending_association_); - pending_association_ = false; - cached_peer_state = std::move(peer_state_); - } - - if (cached_peer_state) { - cached_peer_state->OnAssociated(id, std::move(peer_group_controller)); - return true; - } - return false; - } - - bool is_valid() const { - internal::MayAutoLock locker(&lock_); - return pending_association_ || IsValidInterfaceId(id_); - } - - bool pending_association() const { - internal::MayAutoLock locker(&lock_); - return pending_association_; - } - - InterfaceId id() const { - internal::MayAutoLock locker(&lock_); - return id_; - } - - AssociatedGroupController* group_controller() const { - internal::MayAutoLock locker(&lock_); - return group_controller_.get(); - } - - const base::Optional<DisconnectReason>& disconnect_reason() const { - internal::MayAutoLock locker(&lock_); - return disconnect_reason_; - } - - private: - friend class base::RefCountedThreadSafe<State>; - - ~State() { - DCHECK(!pending_association_); - DCHECK(!IsValidInterfaceId(id_)); - } - - // Called by the peer, maybe from a different thread. - void OnAssociated(InterfaceId id, - scoped_refptr<AssociatedGroupController> group_controller) { - AssociationEventCallback handler; - { - internal::MayAutoLock locker(&lock_); - - // There may be race between Close() of endpoint A and - // NotifyPeerAssociation() of endpoint A_peer on different threads. - // Therefore, it is possible that endpoint A has been closed but it - // still gets OnAssociated() call from its peer. - if (!pending_association_) - return; - - pending_association_ = false; - peer_state_ = nullptr; - id_ = id; - group_controller_ = std::move(group_controller); - - if (!association_event_handler_.is_null()) { - if (runner_->BelongsToCurrentThread()) { - handler = std::move(association_event_handler_); - runner_ = nullptr; - } else { - runner_->PostTask(FROM_HERE, - base::Bind(&ScopedInterfaceEndpointHandle::State:: - RunAssociationEventHandler, - this, runner_, ASSOCIATED)); - } - } - } - - if (!handler.is_null()) - std::move(handler).Run(ASSOCIATED); - } - - // Called by the peer, maybe from a different thread. - void OnPeerClosedBeforeAssociation( - const base::Optional<DisconnectReason>& reason) { - AssociationEventCallback handler; - { - internal::MayAutoLock locker(&lock_); - - // There may be race between Close()/NotifyPeerAssociation() of endpoint - // A and Close() of endpoint A_peer on different threads. - // Therefore, it is possible that endpoint A is not in pending association - // state but still gets OnPeerClosedBeforeAssociation() call from its - // peer. - if (!pending_association_) - return; - - disconnect_reason_ = reason; - // NOTE: This handle itself is still pending. - peer_state_ = nullptr; - - if (!association_event_handler_.is_null()) { - if (runner_->BelongsToCurrentThread()) { - handler = std::move(association_event_handler_); - runner_ = nullptr; - } else { - runner_->PostTask( - FROM_HERE, - base::Bind(&ScopedInterfaceEndpointHandle::State:: - RunAssociationEventHandler, - this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION)); - } - } - } - - if (!handler.is_null()) - std::move(handler).Run(PEER_CLOSED_BEFORE_ASSOCIATION); - } - - void RunAssociationEventHandler( - scoped_refptr<base::SingleThreadTaskRunner> posted_to_runner, - AssociationEvent event) { - AssociationEventCallback handler; - - { - internal::MayAutoLock locker(&lock_); - if (posted_to_runner == runner_) { - runner_ = nullptr; - handler = std::move(association_event_handler_); - } - } - - if (!handler.is_null()) - std::move(handler).Run(event); - } - - // Protects the following members if the handle is initially set to pending - // association. - mutable base::Optional<base::Lock> lock_; - - bool pending_association_ = false; - base::Optional<DisconnectReason> disconnect_reason_; - - scoped_refptr<State> peer_state_; - - AssociationEventCallback association_event_handler_; - scoped_refptr<base::SingleThreadTaskRunner> runner_; - - InterfaceId id_ = kInvalidInterfaceId; - scoped_refptr<AssociatedGroupController> group_controller_; - - DISALLOW_COPY_AND_ASSIGN(State); -}; - -// ScopedInterfaceEndpointHandle ----------------------------------------------- - -// static -void ScopedInterfaceEndpointHandle::CreatePairPendingAssociation( - ScopedInterfaceEndpointHandle* handle0, - ScopedInterfaceEndpointHandle* handle1) { - ScopedInterfaceEndpointHandle result0; - ScopedInterfaceEndpointHandle result1; - result0.state_->InitPendingState(result1.state_); - result1.state_->InitPendingState(result0.state_); - - *handle0 = std::move(result0); - *handle1 = std::move(result1); -} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle() - : state_(new State) {} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( - ScopedInterfaceEndpointHandle&& other) - : state_(new State) { - state_.swap(other.state_); -} - -ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() { - state_->Close(base::nullopt); -} - -ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=( - ScopedInterfaceEndpointHandle&& other) { - reset(); - state_.swap(other.state_); - return *this; -} - -bool ScopedInterfaceEndpointHandle::is_valid() const { - return state_->is_valid(); -} - -bool ScopedInterfaceEndpointHandle::pending_association() const { - return state_->pending_association(); -} - -InterfaceId ScopedInterfaceEndpointHandle::id() const { - return state_->id(); -} - -AssociatedGroupController* ScopedInterfaceEndpointHandle::group_controller() - const { - return state_->group_controller(); -} - -const base::Optional<DisconnectReason>& -ScopedInterfaceEndpointHandle::disconnect_reason() const { - return state_->disconnect_reason(); -} - -void ScopedInterfaceEndpointHandle::SetAssociationEventHandler( - AssociationEventCallback handler) { - state_->SetAssociationEventHandler(std::move(handler)); -} - -void ScopedInterfaceEndpointHandle::reset() { - ResetInternal(base::nullopt); -} - -void ScopedInterfaceEndpointHandle::ResetWithReason( - uint32_t custom_reason, - const std::string& description) { - ResetInternal(DisconnectReason(custom_reason, description)); -} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( - InterfaceId id, - scoped_refptr<AssociatedGroupController> group_controller) - : state_(new State(id, std::move(group_controller))) { - DCHECK(!IsValidInterfaceId(state_->id()) || state_->group_controller()); -} - -bool ScopedInterfaceEndpointHandle::NotifyAssociation( - InterfaceId id, - scoped_refptr<AssociatedGroupController> peer_group_controller) { - return state_->NotifyAssociation(id, peer_group_controller); -} - -void ScopedInterfaceEndpointHandle::ResetInternal( - const base::Optional<DisconnectReason>& reason) { - scoped_refptr<State> new_state(new State); - state_->Close(reason); - state_.swap(new_state); -} - -base::Callback<AssociatedGroupController*()> -ScopedInterfaceEndpointHandle::CreateGroupControllerGetter() const { - // We allow this callback to be run on any thread. If this handle is created - // in non-pending state, we don't have a lock but it should still be safe - // because the group controller never changes. - return base::Bind(&State::group_controller, state_); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h deleted file mode 100644 index 2a7d288..0000000 --- a/mojo/public/cpp/bindings/lib/serialization.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ - -#include <string.h> - -#include "mojo/public/cpp/bindings/array_traits_carray.h" -#include "mojo/public/cpp/bindings/array_traits_stl.h" -#include "mojo/public/cpp/bindings/lib/array_serialization.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h" -#include "mojo/public/cpp/bindings/lib/map_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_enum_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" -#include "mojo/public/cpp/bindings/lib/string_serialization.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/map_traits_stl.h" -#include "mojo/public/cpp/bindings/string_traits_stl.h" -#include "mojo/public/cpp/bindings/string_traits_string16.h" -#include "mojo/public/cpp/bindings/string_traits_string_piece.h" - -namespace mojo { -namespace internal { - -template <typename MojomType, typename DataArrayType, typename UserType> -DataArrayType StructSerializeImpl(UserType* input) { - static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value, - "Unexpected type."); - - SerializationContext context; - size_t size = PrepareToSerialize<MojomType>(*input, &context); - DCHECK_EQ(size, Align(size)); - - DataArrayType result(size); - if (size == 0) - return result; - - void* result_buffer = &result.front(); - // The serialization logic requires that the buffer is 8-byte aligned. If the - // result buffer is not properly aligned, we have to do an extra copy. In - // practice, this should never happen for std::vector. - bool need_copy = !IsAligned(result_buffer); - - if (need_copy) { - // calloc sets the memory to all zero. - result_buffer = calloc(size, 1); - DCHECK(IsAligned(result_buffer)); - } - - Buffer buffer; - buffer.Initialize(result_buffer, size); - typename MojomTypeTraits<MojomType>::Data* data = nullptr; - Serialize<MojomType>(*input, &buffer, &data, &context); - - if (need_copy) { - memcpy(&result.front(), result_buffer, size); - free(result_buffer); - } - - return result; -} - -template <typename MojomType, typename DataArrayType, typename UserType> -bool StructDeserializeImpl(const DataArrayType& input, - UserType* output, - bool (*validate_func)(const void*, - ValidationContext*)) { - static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value, - "Unexpected type."); - using DataType = typename MojomTypeTraits<MojomType>::Data; - - // TODO(sammc): Use DataArrayType::empty() once WTF::Vector::empty() exists. - void* input_buffer = - input.size() == 0 - ? nullptr - : const_cast<void*>(reinterpret_cast<const void*>(&input.front())); - - // Please see comments in StructSerializeImpl. - bool need_copy = !IsAligned(input_buffer); - - if (need_copy) { - input_buffer = malloc(input.size()); - DCHECK(IsAligned(input_buffer)); - memcpy(input_buffer, &input.front(), input.size()); - } - - ValidationContext validation_context(input_buffer, input.size(), 0, 0); - bool result = false; - if (validate_func(input_buffer, &validation_context)) { - auto data = reinterpret_cast<DataType*>(input_buffer); - SerializationContext context; - result = Deserialize<MojomType>(data, output, &context); - } - - if (need_copy) - free(input_buffer); - - return result; -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_context.cc b/mojo/public/cpp/bindings/lib/serialization_context.cc deleted file mode 100644 index e2fd5c6..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_context.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -#include <limits> - -#include "base/logging.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace internal { - -SerializedHandleVector::SerializedHandleVector() {} - -SerializedHandleVector::~SerializedHandleVector() { - for (auto handle : handles_) { - if (handle.is_valid()) { - MojoResult rv = MojoClose(handle.value()); - DCHECK_EQ(rv, MOJO_RESULT_OK); - } - } -} - -Handle_Data SerializedHandleVector::AddHandle(mojo::Handle handle) { - Handle_Data data; - if (!handle.is_valid()) { - data.value = kEncodedInvalidHandleValue; - } else { - DCHECK_LT(handles_.size(), std::numeric_limits<uint32_t>::max()); - data.value = static_cast<uint32_t>(handles_.size()); - handles_.push_back(handle); - } - return data; -} - -mojo::Handle SerializedHandleVector::TakeHandle( - const Handle_Data& encoded_handle) { - if (!encoded_handle.is_valid()) - return mojo::Handle(); - DCHECK_LT(encoded_handle.value, handles_.size()); - return FetchAndReset(&handles_[encoded_handle.value]); -} - -void SerializedHandleVector::Swap(std::vector<mojo::Handle>* other) { - handles_.swap(*other); -} - -SerializationContext::SerializationContext() {} - -SerializationContext::~SerializationContext() { - DCHECK(!custom_contexts || custom_contexts->empty()); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/serialization_context.h b/mojo/public/cpp/bindings/lib/serialization_context.h deleted file mode 100644 index a34fe3d..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_context.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ - -#include <stddef.h> - -#include <memory> -#include <queue> -#include <vector> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -// A container for handles during serialization/deserialization. -class MOJO_CPP_BINDINGS_EXPORT SerializedHandleVector { - public: - SerializedHandleVector(); - ~SerializedHandleVector(); - - size_t size() const { return handles_.size(); } - - // Adds a handle to the handle list and returns its index for encoding. - Handle_Data AddHandle(mojo::Handle handle); - - // Takes a handle from the list of serialized handle data. - mojo::Handle TakeHandle(const Handle_Data& encoded_handle); - - // Takes a handle from the list of serialized handle data and returns it in - // |*out_handle| as a specific scoped handle type. - template <typename T> - ScopedHandleBase<T> TakeHandleAs(const Handle_Data& encoded_handle) { - return MakeScopedHandle(T(TakeHandle(encoded_handle).value())); - } - - // Swaps all owned handles out with another Handle vector. - void Swap(std::vector<mojo::Handle>* other); - - private: - // Handles are owned by this object. - std::vector<mojo::Handle> handles_; - - DISALLOW_COPY_AND_ASSIGN(SerializedHandleVector); -}; - -// Context information for serialization/deserialization routines. -struct MOJO_CPP_BINDINGS_EXPORT SerializationContext { - SerializationContext(); - - ~SerializationContext(); - - // Opaque context pointers returned by StringTraits::SetUpContext(). - std::unique_ptr<std::queue<void*>> custom_contexts; - - // Stashes handles encoded in a message by index. - SerializedHandleVector handles; - - // The number of ScopedInterfaceEndpointHandles that need to be serialized. - // It is calculated by PrepareToSerialize(). - uint32_t associated_endpoint_count = 0; - - // Stashes ScopedInterfaceEndpointHandles encoded in a message by index. - std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles; -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h deleted file mode 100644 index 55c9982..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_forward.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/array_traits.h" -#include "mojo/public/cpp/bindings/enum_traits.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/map_traits.h" -#include "mojo/public/cpp/bindings/string_traits.h" -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/union_traits.h" - -// This file is included by serialization implementation files to avoid circular -// includes. -// Users of the serialization funtions should include serialization.h (and also -// wtf_serialization.h if necessary). - -namespace mojo { -namespace internal { - -template <typename MojomType, typename MaybeConstUserType> -struct Serializer; - -template <typename T> -struct IsOptionalWrapper { - static const bool value = IsSpecializationOf< - base::Optional, - typename std::remove_const< - typename std::remove_reference<T>::type>::type>::value; -}; - -// PrepareToSerialize() must be matched by a Serialize() for the same input -// later. Moreover, within the same SerializationContext if PrepareToSerialize() -// is called for |input_1|, ..., |input_n|, Serialize() must be called for -// those objects in the exact same order. -template <typename MojomType, - typename InputUserType, - typename... Args, - typename std::enable_if< - !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { - return Serializer<MojomType, - typename std::remove_reference<InputUserType>::type>:: - PrepareToSerialize(std::forward<InputUserType>(input), - std::forward<Args>(args)...); -} - -template <typename MojomType, - typename InputUserType, - typename... Args, - typename std::enable_if< - !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -void Serialize(InputUserType&& input, Args&&... args) { - Serializer<MojomType, typename std::remove_reference<InputUserType>::type>:: - Serialize(std::forward<InputUserType>(input), - std::forward<Args>(args)...); -} - -template <typename MojomType, - typename DataType, - typename InputUserType, - typename... Args, - typename std::enable_if< - !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { - return Serializer<MojomType, InputUserType>::Deserialize( - std::forward<DataType>(input), output, std::forward<Args>(args)...); -} - -// Specialization that unwraps base::Optional<>. -template <typename MojomType, - typename InputUserType, - typename... Args, - typename std::enable_if< - IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { - if (!input) - return 0; - return PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...); -} - -template <typename MojomType, - typename InputUserType, - typename DataType, - typename... Args, - typename std::enable_if< - IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -void Serialize(InputUserType&& input, - Buffer* buffer, - DataType** output, - Args&&... args) { - if (!input) { - *output = nullptr; - return; - } - Serialize<MojomType>(*input, buffer, output, std::forward<Args>(args)...); -} - -template <typename MojomType, - typename DataType, - typename InputUserType, - typename... Args, - typename std::enable_if< - IsOptionalWrapper<InputUserType>::value>::type* = nullptr> -bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { - if (!input) { - *output = base::nullopt; - return true; - } - if (!*output) - output->emplace(); - return Deserialize<MojomType>(std::forward<DataType>(input), &output->value(), - std::forward<Args>(args)...); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_util.h b/mojo/public/cpp/bindings/lib/serialization_util.h deleted file mode 100644 index 4820a01..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_util.h +++ /dev/null @@ -1,213 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <queue> - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { -namespace internal { - -template <typename T> -struct HasIsNullMethod { - template <typename U> - static char Test(decltype(U::IsNull)*); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template < - typename Traits, - typename UserType, - typename std::enable_if<HasIsNullMethod<Traits>::value>::type* = nullptr> -bool CallIsNullIfExists(const UserType& input) { - return Traits::IsNull(input); -} - -template < - typename Traits, - typename UserType, - typename std::enable_if<!HasIsNullMethod<Traits>::value>::type* = nullptr> -bool CallIsNullIfExists(const UserType& input) { - return false; -} -template <typename T> -struct HasSetToNullMethod { - template <typename U> - static char Test(decltype(U::SetToNull)*); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template < - typename Traits, - typename UserType, - typename std::enable_if<HasSetToNullMethod<Traits>::value>::type* = nullptr> -bool CallSetToNullIfExists(UserType* output) { - Traits::SetToNull(output); - return true; -} - -template <typename Traits, - typename UserType, - typename std::enable_if<!HasSetToNullMethod<Traits>::value>::type* = - nullptr> -bool CallSetToNullIfExists(UserType* output) { - LOG(ERROR) << "A null value is received. But the Struct/Array/StringTraits " - << "class doesn't define a SetToNull() function and therefore is " - << "unable to deserialize the value."; - return false; -} - -template <typename T> -struct HasSetUpContextMethod { - template <typename U> - static char Test(decltype(U::SetUpContext)*); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename Traits, - bool has_context = HasSetUpContextMethod<Traits>::value> -struct CustomContextHelper; - -template <typename Traits> -struct CustomContextHelper<Traits, true> { - template <typename MaybeConstUserType> - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - void* custom_context = Traits::SetUpContext(input); - if (!context->custom_contexts) - context->custom_contexts.reset(new std::queue<void*>()); - context->custom_contexts->push(custom_context); - return custom_context; - } - - static void* GetNext(SerializationContext* context) { - void* custom_context = context->custom_contexts->front(); - context->custom_contexts->pop(); - return custom_context; - } - - template <typename MaybeConstUserType> - static void TearDown(MaybeConstUserType& input, void* custom_context) { - Traits::TearDownContext(input, custom_context); - } -}; - -template <typename Traits> -struct CustomContextHelper<Traits, false> { - template <typename MaybeConstUserType> - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - return nullptr; - } - - static void* GetNext(SerializationContext* context) { return nullptr; } - - template <typename MaybeConstUserType> - static void TearDown(MaybeConstUserType& input, void* custom_context) { - DCHECK(!custom_context); - } -}; - -template <typename ReturnType, typename ParamType, typename InputUserType> -ReturnType CallWithContext(ReturnType (*f)(ParamType, void*), - InputUserType&& input, - void* context) { - return f(std::forward<InputUserType>(input), context); -} - -template <typename ReturnType, typename ParamType, typename InputUserType> -ReturnType CallWithContext(ReturnType (*f)(ParamType), - InputUserType&& input, - void* context) { - return f(std::forward<InputUserType>(input)); -} - -template <typename T, typename MaybeConstUserType> -struct HasGetBeginMethod { - template <typename U> - static char Test(decltype(U::GetBegin(std::declval<MaybeConstUserType&>()))*); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> -decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>())) -CallGetBeginIfExists(MaybeConstUserType& input) { - return Traits::GetBegin(input); -} - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - !HasGetBeginMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> -size_t CallGetBeginIfExists(MaybeConstUserType& input) { - return 0; -} - -template <typename T, typename MaybeConstUserType> -struct HasGetDataMethod { - template <typename U> - static char Test(decltype(U::GetData(std::declval<MaybeConstUserType&>()))*); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> -decltype(Traits::GetData(std::declval<MaybeConstUserType&>())) -CallGetDataIfExists(MaybeConstUserType& input) { - return Traits::GetData(input); -} - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - !HasGetDataMethod<Traits, MaybeConstUserType>::value>::type* = nullptr> -void* CallGetDataIfExists(MaybeConstUserType& input) { - return nullptr; -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h deleted file mode 100644 index 6e0c758..0000000 --- a/mojo/public/cpp/bindings/lib/string_serialization.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ - -#include <stddef.h> -#include <string.h> - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/string_data_view.h" -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { -namespace internal { - -template <typename MaybeConstUserType> -struct Serializer<StringDataView, MaybeConstUserType> { - using UserType = typename std::remove_const<MaybeConstUserType>::type; - using Traits = StringTraits<UserType>; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists<Traits>(input)) - return 0; - - void* custom_context = CustomContextHelper<Traits>::SetUp(input, context); - return Align(sizeof(String_Data) + - CallWithContext(Traits::GetSize, input, custom_context)); - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buffer, - String_Data** output, - SerializationContext* context) { - if (CallIsNullIfExists<Traits>(input)) { - *output = nullptr; - return; - } - - void* custom_context = CustomContextHelper<Traits>::GetNext(context); - - String_Data* result = String_Data::New( - CallWithContext(Traits::GetSize, input, custom_context), buffer); - if (result) { - memcpy(result->storage(), - CallWithContext(Traits::GetData, input, custom_context), - CallWithContext(Traits::GetSize, input, custom_context)); - } - *output = result; - - CustomContextHelper<Traits>::TearDown(input, custom_context); - } - - static bool Deserialize(String_Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists<Traits>(output); - return Traits::Read(StringDataView(input, context), output); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/string_traits_string16.cc b/mojo/public/cpp/bindings/lib/string_traits_string16.cc deleted file mode 100644 index 95ff6cc..0000000 --- a/mojo/public/cpp/bindings/lib/string_traits_string16.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/string_traits_string16.h" - -#include <string> - -#include "base/strings/utf_string_conversions.h" - -namespace mojo { - -// static -void* StringTraits<base::string16>::SetUpContext(const base::string16& input) { - return new std::string(base::UTF16ToUTF8(input)); -} - -// static -void StringTraits<base::string16>::TearDownContext(const base::string16& input, - void* context) { - delete static_cast<std::string*>(context); -} - -// static -size_t StringTraits<base::string16>::GetSize(const base::string16& input, - void* context) { - return static_cast<std::string*>(context)->size(); -} - -// static -const char* StringTraits<base::string16>::GetData(const base::string16& input, - void* context) { - return static_cast<std::string*>(context)->data(); -} - -// static -bool StringTraits<base::string16>::Read(StringDataView input, - base::string16* output) { - return base::UTF8ToUTF16(input.storage(), input.size(), output); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/mojo/public/cpp/bindings/lib/string_traits_wtf.cc deleted file mode 100644 index 203f6f5..0000000 --- a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/string_traits_wtf.h" - -#include <string.h> - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "third_party/WebKit/Source/wtf/text/StringUTF8Adaptor.h" - -namespace mojo { -namespace { - -struct UTF8AdaptorInfo { - explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) { -#if DCHECK_IS_ON() - original_size_in_bytes = input.charactersSizeInBytes(); -#endif - } - - ~UTF8AdaptorInfo() {} - - WTF::StringUTF8Adaptor utf8_adaptor; - -#if DCHECK_IS_ON() - // For sanity check only. - size_t original_size_in_bytes; -#endif -}; - -UTF8AdaptorInfo* ToAdaptor(const WTF::String& input, void* context) { - UTF8AdaptorInfo* adaptor = static_cast<UTF8AdaptorInfo*>(context); - -#if DCHECK_IS_ON() - DCHECK_EQ(adaptor->original_size_in_bytes, input.charactersSizeInBytes()); -#endif - return adaptor; -} - -} // namespace - -// static -void StringTraits<WTF::String>::SetToNull(WTF::String* output) { - if (output->isNull()) - return; - - WTF::String result; - output->swap(result); -} - -// static -void* StringTraits<WTF::String>::SetUpContext(const WTF::String& input) { - return new UTF8AdaptorInfo(input); -} - -// static -void StringTraits<WTF::String>::TearDownContext(const WTF::String& input, - void* context) { - delete ToAdaptor(input, context); -} - -// static -size_t StringTraits<WTF::String>::GetSize(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.length(); -} - -// static -const char* StringTraits<WTF::String>::GetData(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.data(); -} - -// static -bool StringTraits<WTF::String>::Read(StringDataView input, - WTF::String* output) { - WTF::String result = WTF::String::fromUTF8(input.storage(), input.size()); - output->swap(result); - return true; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc deleted file mode 100644 index 585a8f0..0000000 --- a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" - -#if ENABLE_SYNC_CALL_RESTRICTIONS - -#include "base/debug/leak_annotations.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { - -namespace { - -class SyncCallSettings { - public: - static SyncCallSettings* current(); - - bool allowed() const { - return scoped_allow_count_ > 0 || system_defined_value_; - } - - void IncreaseScopedAllowCount() { scoped_allow_count_++; } - void DecreaseScopedAllowCount() { - DCHECK_LT(0u, scoped_allow_count_); - scoped_allow_count_--; - } - - private: - SyncCallSettings(); - ~SyncCallSettings(); - - bool system_defined_value_ = true; - size_t scoped_allow_count_ = 0; -}; - -base::LazyInstance<base::ThreadLocalPointer<SyncCallSettings>>::DestructorAtExit - g_sync_call_settings = LAZY_INSTANCE_INITIALIZER; - -// static -SyncCallSettings* SyncCallSettings::current() { - SyncCallSettings* result = g_sync_call_settings.Pointer()->Get(); - if (!result) { - result = new SyncCallSettings(); - ANNOTATE_LEAKING_OBJECT_PTR(result); - DCHECK_EQ(result, g_sync_call_settings.Pointer()->Get()); - } - return result; -} - -SyncCallSettings::SyncCallSettings() { - MojoResult result = MojoGetProperty(MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, - &system_defined_value_); - DCHECK_EQ(MOJO_RESULT_OK, result); - - DCHECK(!g_sync_call_settings.Pointer()->Get()); - g_sync_call_settings.Pointer()->Set(this); -} - -SyncCallSettings::~SyncCallSettings() { - g_sync_call_settings.Pointer()->Set(nullptr); -} - -} // namespace - -// static -void SyncCallRestrictions::AssertSyncCallAllowed() { - if (!SyncCallSettings::current()->allowed()) { - LOG(FATAL) << "Mojo sync calls are not allowed in this process because " - << "they can lead to jank and deadlock. If you must make an " - << "exception, please see " - << "SyncCallRestrictions::ScopedAllowSyncCall and consult " - << "mojo/OWNERS."; - } -} - -// static -void SyncCallRestrictions::IncreaseScopedAllowCount() { - SyncCallSettings::current()->IncreaseScopedAllowCount(); -} - -// static -void SyncCallRestrictions::DecreaseScopedAllowCount() { - SyncCallSettings::current()->DecreaseScopedAllowCount(); -} - -} // namespace mojo - -#endif // ENABLE_SYNC_CALL_RESTRICTIONS diff --git a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc b/mojo/public/cpp/bindings/lib/sync_event_watcher.cc deleted file mode 100644 index b1c97e3..0000000 --- a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_event_watcher.h" - -#include "base/logging.h" - -namespace mojo { - -SyncEventWatcher::SyncEventWatcher(base::WaitableEvent* event, - const base::Closure& callback) - : event_(event), - callback_(callback), - registry_(SyncHandleRegistry::current()), - destroyed_(new base::RefCountedData<bool>(false)) {} - -SyncEventWatcher::~SyncEventWatcher() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (registered_) - registry_->UnregisterEvent(event_); - destroyed_->data = true; -} - -void SyncEventWatcher::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); -} - -bool SyncEventWatcher::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); - if (!registered_) { - DecrementRegisterCount(); - return false; - } - - // This object may be destroyed during the Wait() call. So we have to preserve - // the boolean that Wait uses. - auto destroyed = destroyed_; - const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = registry_->Wait(should_stop_array, 2); - - // This object has been destroyed. - if (destroyed->data) - return false; - - DecrementRegisterCount(); - return result; -} - -void SyncEventWatcher::IncrementRegisterCount() { - register_request_count_++; - if (!registered_) - registered_ = registry_->RegisterEvent(event_, callback_); -} - -void SyncEventWatcher::DecrementRegisterCount() { - DCHECK_GT(register_request_count_, 0u); - register_request_count_--; - if (register_request_count_ == 0 && registered_) { - registry_->UnregisterEvent(event_); - registered_ = false; - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc deleted file mode 100644 index fd3df39..0000000 --- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_handle_registry.h" - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/threading/thread_local.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { -namespace { - -base::LazyInstance<base::ThreadLocalPointer<SyncHandleRegistry>>::Leaky - g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -scoped_refptr<SyncHandleRegistry> SyncHandleRegistry::current() { - scoped_refptr<SyncHandleRegistry> result( - g_current_sync_handle_watcher.Pointer()->Get()); - if (!result) { - result = new SyncHandleRegistry(); - DCHECK_EQ(result.get(), g_current_sync_handle_watcher.Pointer()->Get()); - } - return result; -} - -bool SyncHandleRegistry::RegisterHandle(const Handle& handle, - MojoHandleSignals handle_signals, - const HandleCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (base::ContainsKey(handles_, handle)) - return false; - - MojoResult result = wait_set_.AddHandle(handle, handle_signals); - if (result != MOJO_RESULT_OK) - return false; - - handles_[handle] = callback; - return true; -} - -void SyncHandleRegistry::UnregisterHandle(const Handle& handle) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!base::ContainsKey(handles_, handle)) - return; - - MojoResult result = wait_set_.RemoveHandle(handle); - DCHECK_EQ(MOJO_RESULT_OK, result); - handles_.erase(handle); -} - -bool SyncHandleRegistry::RegisterEvent(base::WaitableEvent* event, - const base::Closure& callback) { - auto result = events_.insert({event, callback}); - DCHECK(result.second); - MojoResult rv = wait_set_.AddEvent(event); - if (rv == MOJO_RESULT_OK) - return true; - DCHECK_EQ(MOJO_RESULT_ALREADY_EXISTS, rv); - return false; -} - -void SyncHandleRegistry::UnregisterEvent(base::WaitableEvent* event) { - auto it = events_.find(event); - DCHECK(it != events_.end()); - events_.erase(it); - MojoResult rv = wait_set_.RemoveEvent(event); - DCHECK_EQ(MOJO_RESULT_OK, rv); -} - -bool SyncHandleRegistry::Wait(const bool* should_stop[], size_t count) { - DCHECK(thread_checker_.CalledOnValidThread()); - - size_t num_ready_handles; - Handle ready_handle; - MojoResult ready_handle_result; - - scoped_refptr<SyncHandleRegistry> preserver(this); - while (true) { - for (size_t i = 0; i < count; ++i) - if (*should_stop[i]) - return true; - - // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we - // give priority to the handle that is waiting for sync response. - base::WaitableEvent* ready_event = nullptr; - num_ready_handles = 1; - wait_set_.Wait(&ready_event, &num_ready_handles, &ready_handle, - &ready_handle_result); - if (num_ready_handles) { - DCHECK_EQ(1u, num_ready_handles); - const auto iter = handles_.find(ready_handle); - iter->second.Run(ready_handle_result); - } - - if (ready_event) { - const auto iter = events_.find(ready_event); - DCHECK(iter != events_.end()); - iter->second.Run(); - } - }; - - return false; -} - -SyncHandleRegistry::SyncHandleRegistry() { - DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); - g_current_sync_handle_watcher.Pointer()->Set(this); -} - -SyncHandleRegistry::~SyncHandleRegistry() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // This object may be destructed after the thread local storage slot used by - // |g_current_sync_handle_watcher| is reset during thread shutdown. - // For example, another slot in the thread local storage holds a referrence to - // this object, and that slot is cleaned up after - // |g_current_sync_handle_watcher|. - if (!g_current_sync_handle_watcher.Pointer()->Get()) - return; - - // If this breaks, it is likely that the global variable is bulit into and - // accessed from multiple modules. - DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); - - g_current_sync_handle_watcher.Pointer()->Set(nullptr); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc deleted file mode 100644 index f20af56..0000000 --- a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" - -#include "base/logging.h" - -namespace mojo { - -SyncHandleWatcher::SyncHandleWatcher( - const Handle& handle, - MojoHandleSignals handle_signals, - const SyncHandleRegistry::HandleCallback& callback) - : handle_(handle), - handle_signals_(handle_signals), - callback_(callback), - registered_(false), - register_request_count_(0), - registry_(SyncHandleRegistry::current()), - destroyed_(new base::RefCountedData<bool>(false)) {} - -SyncHandleWatcher::~SyncHandleWatcher() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (registered_) - registry_->UnregisterHandle(handle_); - - destroyed_->data = true; -} - -void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); -} - -bool SyncHandleWatcher::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); - if (!registered_) { - DecrementRegisterCount(); - return false; - } - - // This object may be destroyed during the Wait() call. So we have to preserve - // the boolean that Wait uses. - auto destroyed = destroyed_; - const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = registry_->Wait(should_stop_array, 2); - - // This object has been destroyed. - if (destroyed->data) - return false; - - DecrementRegisterCount(); - return result; -} - -void SyncHandleWatcher::IncrementRegisterCount() { - register_request_count_++; - if (!registered_) { - registered_ = - registry_->RegisterHandle(handle_, handle_signals_, callback_); - } -} - -void SyncHandleWatcher::DecrementRegisterCount() { - DCHECK_GT(register_request_count_, 0u); - - register_request_count_--; - if (register_request_count_ == 0 && registered_) { - registry_->UnregisterHandle(handle_); - registered_ = false; - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/template_util.h b/mojo/public/cpp/bindings/lib/template_util.h deleted file mode 100644 index 5151123..0000000 --- a/mojo/public/cpp/bindings/lib/template_util.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_ - -#include <type_traits> - -namespace mojo { -namespace internal { - -template <class T, T v> -struct IntegralConstant { - static const T value = v; -}; - -template <class T, T v> -const T IntegralConstant<T, v>::value; - -typedef IntegralConstant<bool, true> TrueType; -typedef IntegralConstant<bool, false> FalseType; - -template <class T> -struct IsConst : FalseType {}; -template <class T> -struct IsConst<const T> : TrueType {}; - -template <class T> -struct IsPointer : FalseType {}; -template <class T> -struct IsPointer<T*> : TrueType {}; - -template <bool B, typename T = void> -struct EnableIf {}; - -template <typename T> -struct EnableIf<true, T> { - typedef T type; -}; - -// Types YesType and NoType are guaranteed such that sizeof(YesType) < -// sizeof(NoType). -typedef char YesType; - -struct NoType { - YesType dummy[2]; -}; - -// A helper template to determine if given type is non-const move-only-type, -// i.e. if a value of the given type should be passed via std::move() in a -// destructive way. -template <typename T> -struct IsMoveOnlyType { - static const bool value = std::is_constructible<T, T&&>::value && - !std::is_constructible<T, const T&>::value; -}; - -// This goop is a trick used to implement a template that can be used to -// determine if a given class is the base class of another given class. -template <typename, typename> -struct IsSame { - static bool const value = false; -}; -template <typename A> -struct IsSame<A, A> { - static bool const value = true; -}; - -template <typename T> -struct EnsureTypeIsComplete { - // sizeof() cannot be applied to incomplete types, this line will fail - // compilation if T is forward declaration. - using CheckSize = char (*)[sizeof(T)]; -}; - -template <typename Base, typename Derived> -struct IsBaseOf { - private: - static Derived* CreateDerived(); - static char(&Check(Base*))[1]; - static char(&Check(...))[2]; - - EnsureTypeIsComplete<Base> check_base_; - EnsureTypeIsComplete<Derived> check_derived_; - - public: - static bool const value = sizeof Check(CreateDerived()) == 1 && - !IsSame<Base const, void const>::value; -}; - -template <class T> -struct RemovePointer { - typedef T type; -}; -template <class T> -struct RemovePointer<T*> { - typedef T type; -}; - -template <template <typename...> class Template, typename T> -struct IsSpecializationOf : FalseType {}; - -template <template <typename...> class Template, typename... Args> -struct IsSpecializationOf<Template, Template<Args...>> : TrueType {}; - -template <bool B, typename T, typename F> -struct Conditional { - typedef T type; -}; - -template <typename T, typename F> -struct Conditional<false, T, F> { - typedef F type; -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/union_accessor.h b/mojo/public/cpp/bindings/lib/union_accessor.h deleted file mode 100644 index 821aede..0000000 --- a/mojo/public/cpp/bindings/lib/union_accessor.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_UNION_ACCESSOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_UNION_ACCESSOR_H_ - -namespace mojo { -namespace internal { - -// When serializing and deserializing Unions, it is necessary to access -// the private fields and methods of the Union. This allows us to do that -// without leaking those same fields and methods in the Union interface. -// All Union wrappers are friends of this class allowing such access. -template <typename U> -class UnionAccessor { - public: - explicit UnionAccessor(U* u) : u_(u) {} - - typename U::Union_* data() { return &(u_->data_); } - - typename U::Tag* tag() { return &(u_->tag_); } - - void SwitchActive(typename U::Tag new_tag) { u_->SwitchActive(new_tag); } - - private: - U* u_; -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_UNION_ACCESSOR_H_ diff --git a/mojo/public/cpp/bindings/lib/validate_params.h b/mojo/public/cpp/bindings/lib/validate_params.h deleted file mode 100644 index c0ee8e0..0000000 --- a/mojo/public/cpp/bindings/lib/validate_params.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATE_PARAMS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATE_PARAMS_H_ - -#include <stdint.h> - -#include "base/macros.h" - -namespace mojo { -namespace internal { - -class ValidationContext; - -using ValidateEnumFunc = bool (*)(int32_t, ValidationContext*); - -class ContainerValidateParams { - public: - // Validates a map. A map is validated as a pair of arrays, one for the keys - // and one for the values. Both arguments must be non-null. - // - // ContainerValidateParams takes ownership of |in_key_validate params| and - // |in_element_validate params|. - ContainerValidateParams(ContainerValidateParams* in_key_validate_params, - ContainerValidateParams* in_element_validate_params) - : key_validate_params(in_key_validate_params), - element_validate_params(in_element_validate_params) { - DCHECK(in_key_validate_params) - << "Map validate params require key validate params"; - DCHECK(in_element_validate_params) - << "Map validate params require element validate params"; - } - - // Validates an array. - // - // ContainerValidateParams takes ownership of |in_element_validate params|. - ContainerValidateParams(uint32_t in_expected_num_elements, - bool in_element_is_nullable, - ContainerValidateParams* in_element_validate_params) - : expected_num_elements(in_expected_num_elements), - element_is_nullable(in_element_is_nullable), - element_validate_params(in_element_validate_params) {} - - // Validates an array of enums. - ContainerValidateParams(uint32_t in_expected_num_elements, - ValidateEnumFunc in_validate_enum_func) - : expected_num_elements(in_expected_num_elements), - validate_enum_func(in_validate_enum_func) {} - - ~ContainerValidateParams() { - if (element_validate_params) - delete element_validate_params; - if (key_validate_params) - delete key_validate_params; - } - - // If |expected_num_elements| is not 0, the array is expected to have exactly - // that number of elements. - uint32_t expected_num_elements = 0; - - // Whether the elements are nullable. - bool element_is_nullable = false; - - // Validation information for the map key array. May contain other - // ArrayValidateParams e.g. if the keys are strings. - ContainerValidateParams* key_validate_params = nullptr; - - // For arrays: validation information for elements. It is either a pointer to - // another instance of ArrayValidateParams (if elements are arrays or maps), - // or nullptr. - // - // For maps: validation information for the whole value array. May contain - // other ArrayValidateParams e.g. if the values are arrays or maps. - ContainerValidateParams* element_validate_params = nullptr; - - // Validation function for enum elements. - ValidateEnumFunc validate_enum_func = nullptr; - - private: - DISALLOW_COPY_AND_ASSIGN(ContainerValidateParams); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATE_PARAMS_H_ diff --git a/mojo/public/cpp/bindings/lib/validation_context.cc b/mojo/public/cpp/bindings/lib/validation_context.cc deleted file mode 100644 index ad0a364..0000000 --- a/mojo/public/cpp/bindings/lib/validation_context.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/validation_context.h" - -#include "base/logging.h" - -namespace mojo { -namespace internal { - -ValidationContext::ValidationContext(const void* data, - size_t data_num_bytes, - size_t num_handles, - size_t num_associated_endpoint_handles, - Message* message, - const base::StringPiece& description, - int stack_depth) - : message_(message), - description_(description), - data_begin_(reinterpret_cast<uintptr_t>(data)), - data_end_(data_begin_ + data_num_bytes), - handle_begin_(0), - handle_end_(static_cast<uint32_t>(num_handles)), - associated_endpoint_handle_begin_(0), - associated_endpoint_handle_end_( - static_cast<uint32_t>(num_associated_endpoint_handles)), - stack_depth_(stack_depth) { - // Check whether the calculation of |data_end_| or static_cast from size_t to - // uint32_t causes overflow. - // They shouldn't happen but they do, set the corresponding range to empty. - if (data_end_ < data_begin_) { - NOTREACHED(); - data_end_ = data_begin_; - } - if (handle_end_ < num_handles) { - NOTREACHED(); - handle_end_ = 0; - } - if (associated_endpoint_handle_end_ < num_associated_endpoint_handles) { - NOTREACHED(); - associated_endpoint_handle_end_ = 0; - } -} - -ValidationContext::~ValidationContext() { -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/validation_context.h b/mojo/public/cpp/bindings/lib/validation_context.h deleted file mode 100644 index ed6c654..0000000 --- a/mojo/public/cpp/bindings/lib/validation_context.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_CONTEXT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_CONTEXT_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/strings/string_piece.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" - -static const int kMaxRecursionDepth = 100; - -namespace mojo { - -class Message; - -namespace internal { - -// ValidationContext is used when validating object sizes, pointers and handle -// indices in the payload of incoming messages. -class MOJO_CPP_BINDINGS_EXPORT ValidationContext { - public: - // [data, data + data_num_bytes) specifies the initial valid memory range. - // [0, num_handles) specifies the initial valid range of handle indices. - // [0, num_associated_endpoint_handles) specifies the initial valid range of - // associated endpoint handle indices. - // - // If provided, |message| and |description| provide additional information - // to use when reporting validation errors. In addition if |message| is - // provided, the MojoNotifyBadMessage API will be used to notify the system of - // such errors. - ValidationContext(const void* data, - size_t data_num_bytes, - size_t num_handles, - size_t num_associated_endpoint_handles, - Message* message = nullptr, - const base::StringPiece& description = "", - int stack_depth = 0); - - ~ValidationContext(); - - // Claims the specified memory range. - // The method succeeds if the range is valid to claim. (Please see - // the comments for IsValidRange().) - // On success, the valid memory range is shrinked to begin right after the end - // of the claimed range. - bool ClaimMemory(const void* position, uint32_t num_bytes) { - uintptr_t begin = reinterpret_cast<uintptr_t>(position); - uintptr_t end = begin + num_bytes; - - if (!InternalIsValidRange(begin, end)) - return false; - - data_begin_ = end; - return true; - } - - // Claims the specified encoded handle (which is basically a handle index). - // The method succeeds if: - // - |encoded_handle|'s value is |kEncodedInvalidHandleValue|. - // - the handle is contained inside the valid range of handle indices. In this - // case, the valid range is shinked to begin right after the claimed handle. - bool ClaimHandle(const Handle_Data& encoded_handle) { - uint32_t index = encoded_handle.value; - if (index == kEncodedInvalidHandleValue) - return true; - - if (index < handle_begin_ || index >= handle_end_) - return false; - - // |index| + 1 shouldn't overflow, because |index| is not the max value of - // uint32_t (it is less than |handle_end_|). - handle_begin_ = index + 1; - return true; - } - - // Claims the specified encoded associated endpoint handle. - // The method succeeds if: - // - |encoded_handle|'s value is |kEncodedInvalidHandleValue|. - // - the handle is contained inside the valid range of associated endpoint - // handle indices. In this case, the valid range is shinked to begin right - // after the claimed handle. - bool ClaimAssociatedEndpointHandle( - const AssociatedEndpointHandle_Data& encoded_handle) { - uint32_t index = encoded_handle.value; - if (index == kEncodedInvalidHandleValue) - return true; - - if (index < associated_endpoint_handle_begin_ || - index >= associated_endpoint_handle_end_) - return false; - - // |index| + 1 shouldn't overflow, because |index| is not the max value of - // uint32_t (it is less than |associated_endpoint_handle_end_|). - associated_endpoint_handle_begin_ = index + 1; - return true; - } - - // Returns true if the specified range is not empty, and the range is - // contained inside the valid memory range. - bool IsValidRange(const void* position, uint32_t num_bytes) const { - uintptr_t begin = reinterpret_cast<uintptr_t>(position); - uintptr_t end = begin + num_bytes; - - return InternalIsValidRange(begin, end); - } - - // This object should be created on the stack once every time we recurse down - // into a subfield during validation to make sure we don't recurse too deep - // and blow the stack. - class ScopedDepthTracker { - public: - // |ctx| must outlive this object. - explicit ScopedDepthTracker(ValidationContext* ctx) : ctx_(ctx) { - ++ctx_->stack_depth_; - } - - ~ScopedDepthTracker() { --ctx_->stack_depth_; } - - private: - ValidationContext* ctx_; - - DISALLOW_COPY_AND_ASSIGN(ScopedDepthTracker); - }; - - // Returns true if the recursion depth limit has been reached. - bool ExceedsMaxDepth() WARN_UNUSED_RESULT { - return stack_depth_ > kMaxRecursionDepth; - } - - Message* message() const { return message_; } - const base::StringPiece& description() const { return description_; } - - private: - bool InternalIsValidRange(uintptr_t begin, uintptr_t end) const { - return end > begin && begin >= data_begin_ && end <= data_end_; - } - - Message* const message_; - const base::StringPiece description_; - - // [data_begin_, data_end_) is the valid memory range. - uintptr_t data_begin_; - uintptr_t data_end_; - - // [handle_begin_, handle_end_) is the valid handle index range. - uint32_t handle_begin_; - uint32_t handle_end_; - - // [associated_endpoint_handle_begin_, associated_endpoint_handle_end_) is the - // valid associated endpoint handle index range. - uint32_t associated_endpoint_handle_begin_; - uint32_t associated_endpoint_handle_end_; - - int stack_depth_; - - DISALLOW_COPY_AND_ASSIGN(ValidationContext); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_CONTEXT_H_ diff --git a/mojo/public/cpp/bindings/lib/validation_errors.cc b/mojo/public/cpp/bindings/lib/validation_errors.cc deleted file mode 100644 index 904f5e4..0000000 --- a/mojo/public/cpp/bindings/lib/validation_errors.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/validation_errors.h" - -#include "base/strings/stringprintf.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace internal { -namespace { - -ValidationErrorObserverForTesting* g_validation_error_observer = nullptr; -SerializationWarningObserverForTesting* g_serialization_warning_observer = - nullptr; -bool g_suppress_logging = false; - -} // namespace - -const char* ValidationErrorToString(ValidationError error) { - switch (error) { - case VALIDATION_ERROR_NONE: - return "VALIDATION_ERROR_NONE"; - case VALIDATION_ERROR_MISALIGNED_OBJECT: - return "VALIDATION_ERROR_MISALIGNED_OBJECT"; - case VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE: - return "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE"; - case VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER: - return "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER"; - case VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER: - return "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER"; - case VALIDATION_ERROR_ILLEGAL_HANDLE: - return "VALIDATION_ERROR_ILLEGAL_HANDLE"; - case VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE: - return "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE"; - case VALIDATION_ERROR_ILLEGAL_POINTER: - return "VALIDATION_ERROR_ILLEGAL_POINTER"; - case VALIDATION_ERROR_UNEXPECTED_NULL_POINTER: - return "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER"; - case VALIDATION_ERROR_ILLEGAL_INTERFACE_ID: - return "VALIDATION_ERROR_ILLEGAL_INTERFACE_ID"; - case VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID: - return "VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID"; - case VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS: - return "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS"; - case VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID: - return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID"; - case VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD: - return "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD"; - case VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP: - return "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP"; - case VALIDATION_ERROR_UNKNOWN_UNION_TAG: - return "VALIDATION_ERROR_UNKNOWN_UNION_TAG"; - case VALIDATION_ERROR_UNKNOWN_ENUM_VALUE: - return "VALIDATION_ERROR_UNKNOWN_ENUM_VALUE"; - case VALIDATION_ERROR_DESERIALIZATION_FAILED: - return "VALIDATION_ERROR_DESERIALIZATION_FAILED"; - case VALIDATION_ERROR_MAX_RECURSION_DEPTH: - return "VALIDATION_ERROR_MAX_RECURSION_DEPTH"; - } - - return "Unknown error"; -} - -void ReportValidationError(ValidationContext* context, - ValidationError error, - const char* description) { - if (g_validation_error_observer) { - g_validation_error_observer->set_last_error(error); - return; - } - - if (description) { - if (!g_suppress_logging) { - LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error) - << " (" << description << ")"; - } - if (context->message()) { - context->message()->NotifyBadMessage( - base::StringPrintf("Validation failed for %s [%s (%s)]", - context->description().data(), - ValidationErrorToString(error), description)); - } - } else { - if (!g_suppress_logging) - LOG(ERROR) << "Invalid message: " << ValidationErrorToString(error); - if (context->message()) { - context->message()->NotifyBadMessage( - base::StringPrintf("Validation failed for %s [%s]", - context->description().data(), - ValidationErrorToString(error))); - } - } -} - -void ReportValidationErrorForMessage( - mojo::Message* message, - ValidationError error, - const char* description) { - ValidationContext validation_context(nullptr, 0, 0, 0, message, description); - ReportValidationError(&validation_context, error); -} - -ScopedSuppressValidationErrorLoggingForTests - ::ScopedSuppressValidationErrorLoggingForTests() - : was_suppressed_(g_suppress_logging) { - g_suppress_logging = true; -} - -ScopedSuppressValidationErrorLoggingForTests - ::~ScopedSuppressValidationErrorLoggingForTests() { - g_suppress_logging = was_suppressed_; -} - -ValidationErrorObserverForTesting::ValidationErrorObserverForTesting( - const base::Closure& callback) - : last_error_(VALIDATION_ERROR_NONE), callback_(callback) { - DCHECK(!g_validation_error_observer); - g_validation_error_observer = this; -} - -ValidationErrorObserverForTesting::~ValidationErrorObserverForTesting() { - DCHECK(g_validation_error_observer == this); - g_validation_error_observer = nullptr; -} - -bool ReportSerializationWarning(ValidationError error) { - if (g_serialization_warning_observer) { - g_serialization_warning_observer->set_last_warning(error); - return true; - } - - return false; -} - -SerializationWarningObserverForTesting::SerializationWarningObserverForTesting() - : last_warning_(VALIDATION_ERROR_NONE) { - DCHECK(!g_serialization_warning_observer); - g_serialization_warning_observer = this; -} - -SerializationWarningObserverForTesting:: - ~SerializationWarningObserverForTesting() { - DCHECK(g_serialization_warning_observer == this); - g_serialization_warning_observer = nullptr; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/validation_errors.h b/mojo/public/cpp/bindings/lib/validation_errors.h deleted file mode 100644 index 122418d..0000000 --- a/mojo/public/cpp/bindings/lib/validation_errors.h +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_ - -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" - -namespace mojo { - -class Message; - -namespace internal { - -enum ValidationError { - // There is no validation error. - VALIDATION_ERROR_NONE, - // An object (struct or array) is not 8-byte aligned. - VALIDATION_ERROR_MISALIGNED_OBJECT, - // An object is not contained inside the message data, or it overlaps other - // objects. - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE, - // A struct header doesn't make sense, for example: - // - |num_bytes| is smaller than the size of the struct header. - // - |num_bytes| and |version| don't match. - // TODO(yzshen): Consider splitting it into two different error codes. Because - // the former indicates someone is misbehaving badly whereas the latter could - // be due to an inappropriately-modified .mojom file. - VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER, - // An array header doesn't make sense, for example: - // - |num_bytes| is smaller than the size of the header plus the size required - // to store |num_elements| elements. - // - For fixed-size arrays, |num_elements| is different than the specified - // size. - VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - // An encoded handle is illegal. - VALIDATION_ERROR_ILLEGAL_HANDLE, - // A non-nullable handle field is set to invalid handle. - VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - // An encoded pointer is illegal. - VALIDATION_ERROR_ILLEGAL_POINTER, - // A non-nullable pointer field is set to null. - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - // An interface ID is illegal. - VALIDATION_ERROR_ILLEGAL_INTERFACE_ID, - // A non-nullable interface ID field is set to invalid. - VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, - // |flags| in the message header is invalid. The flags are either - // inconsistent with one another, inconsistent with other parts of the - // message, or unexpected for the message receiver. For example the - // receiver is expecting a request message but the flags indicate that - // the message is a response message. - VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS, - // |flags| in the message header indicates that a request ID is required but - // there isn't one. - VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID, - // The |name| field in a message header contains an unexpected value. - VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD, - // Two parallel arrays which are supposed to represent a map have different - // lengths. - VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP, - // Attempted to deserialize a tagged union with an unknown tag. - VALIDATION_ERROR_UNKNOWN_UNION_TAG, - // A value of a non-extensible enum type is unknown. - VALIDATION_ERROR_UNKNOWN_ENUM_VALUE, - // Message deserialization failure, for example due to rejection by custom - // validation logic. - VALIDATION_ERROR_DESERIALIZATION_FAILED, - // The message contains a too deeply nested value, for example a recursively - // defined field which runtime value is too large. - VALIDATION_ERROR_MAX_RECURSION_DEPTH, -}; - -MOJO_CPP_BINDINGS_EXPORT const char* ValidationErrorToString( - ValidationError error); - -MOJO_CPP_BINDINGS_EXPORT void ReportValidationError( - ValidationContext* context, - ValidationError error, - const char* description = nullptr); - -MOJO_CPP_BINDINGS_EXPORT void ReportValidationErrorForMessage( - mojo::Message* message, - ValidationError error, - const char* description = nullptr); - -// This class may be used by tests to suppress validation error logging. This is -// not thread-safe and must only be instantiated on the main thread with no -// other threads using Mojo bindings at the time of construction or destruction. -class MOJO_CPP_BINDINGS_EXPORT ScopedSuppressValidationErrorLoggingForTests { - public: - ScopedSuppressValidationErrorLoggingForTests(); - ~ScopedSuppressValidationErrorLoggingForTests(); - - private: - const bool was_suppressed_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSuppressValidationErrorLoggingForTests); -}; - -// Only used by validation tests and when there is only one thread doing message -// validation. -class MOJO_CPP_BINDINGS_EXPORT ValidationErrorObserverForTesting { - public: - explicit ValidationErrorObserverForTesting(const base::Closure& callback); - ~ValidationErrorObserverForTesting(); - - ValidationError last_error() const { return last_error_; } - void set_last_error(ValidationError error) { - last_error_ = error; - callback_.Run(); - } - - private: - ValidationError last_error_; - base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting); -}; - -// Used only by MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING. Don't use it directly. -// -// The function returns true if the error is recorded (by a -// SerializationWarningObserverForTesting object), false otherwise. -MOJO_CPP_BINDINGS_EXPORT bool ReportSerializationWarning(ValidationError error); - -// Only used by serialization tests and when there is only one thread doing -// message serialization. -class MOJO_CPP_BINDINGS_EXPORT SerializationWarningObserverForTesting { - public: - SerializationWarningObserverForTesting(); - ~SerializationWarningObserverForTesting(); - - ValidationError last_warning() const { return last_warning_; } - void set_last_warning(ValidationError error) { last_warning_ = error; } - - private: - ValidationError last_warning_; - - DISALLOW_COPY_AND_ASSIGN(SerializationWarningObserverForTesting); -}; - -} // namespace internal -} // namespace mojo - -// In debug build, logs a serialization warning if |condition| evaluates to -// true: -// - if there is a SerializationWarningObserverForTesting object alive, -// records |error| in it; -// - otherwise, logs a fatal-level message. -// |error| is the validation error that will be triggered by the receiver -// of the serialzation result. -// -// In non-debug build, does nothing (not even compiling |condition|). -#define MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(condition, error, \ - description) \ - DLOG_IF(FATAL, (condition) && !ReportSerializationWarning(error)) \ - << "The outgoing message will trigger " \ - << ValidationErrorToString(error) << " at the receiving side (" \ - << description << ")."; - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_ diff --git a/mojo/public/cpp/bindings/lib/validation_util.cc b/mojo/public/cpp/bindings/lib/validation_util.cc deleted file mode 100644 index 7614df5..0000000 --- a/mojo/public/cpp/bindings/lib/validation_util.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -#include <stdint.h> - -#include <limits> - -#include "mojo/public/cpp/bindings/lib/message_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" - -namespace mojo { -namespace internal { - -bool ValidateStructHeaderAndClaimMemory(const void* data, - ValidationContext* validation_context) { - if (!IsAligned(data)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MISALIGNED_OBJECT); - return false; - } - if (!validation_context->IsValidRange(data, sizeof(StructHeader))) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - const StructHeader* header = static_cast<const StructHeader*>(data); - - if (header->num_bytes < sizeof(StructHeader)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } - - if (!validation_context->ClaimMemory(data, header->num_bytes)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - return true; -} - -bool ValidateNonInlinedUnionHeaderAndClaimMemory( - const void* data, - ValidationContext* validation_context) { - if (!IsAligned(data)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MISALIGNED_OBJECT); - return false; - } - - if (!validation_context->ClaimMemory(data, kUnionDataSize) || - *static_cast<const uint32_t*>(data) != kUnionDataSize) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - return true; -} - -bool ValidateMessageIsRequestWithoutResponse( - const Message* message, - ValidationContext* validation_context) { - if (message->has_flag(Message::kFlagIsResponse) || - message->has_flag(Message::kFlagExpectsResponse)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - return true; -} - -bool ValidateMessageIsRequestExpectingResponse( - const Message* message, - ValidationContext* validation_context) { - if (message->has_flag(Message::kFlagIsResponse) || - !message->has_flag(Message::kFlagExpectsResponse)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - return true; -} - -bool ValidateMessageIsResponse(const Message* message, - ValidationContext* validation_context) { - if (message->has_flag(Message::kFlagExpectsResponse) || - !message->has_flag(Message::kFlagIsResponse)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - return true; -} - -bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input) { - return input.handle.is_valid(); -} - -bool IsHandleOrInterfaceValid(const AssociatedEndpointHandle_Data& input) { - return input.is_valid(); -} - -bool IsHandleOrInterfaceValid(const Interface_Data& input) { - return input.handle.is_valid(); -} - -bool IsHandleOrInterfaceValid(const Handle_Data& input) { - return input.is_valid(); -} - -bool ValidateHandleOrInterfaceNonNullable( - const AssociatedInterface_Data& input, - const char* error_message, - ValidationContext* validation_context) { - if (IsHandleOrInterfaceValid(input)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, - error_message); - return false; -} - -bool ValidateHandleOrInterfaceNonNullable( - const AssociatedEndpointHandle_Data& input, - const char* error_message, - ValidationContext* validation_context) { - if (IsHandleOrInterfaceValid(input)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, - error_message); - return false; -} - -bool ValidateHandleOrInterfaceNonNullable( - const Interface_Data& input, - const char* error_message, - ValidationContext* validation_context) { - if (IsHandleOrInterfaceValid(input)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - error_message); - return false; -} - -bool ValidateHandleOrInterfaceNonNullable( - const Handle_Data& input, - const char* error_message, - ValidationContext* validation_context) { - if (IsHandleOrInterfaceValid(input)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - error_message); - return false; -} - -bool ValidateHandleOrInterface(const AssociatedInterface_Data& input, - ValidationContext* validation_context) { - if (validation_context->ClaimAssociatedEndpointHandle(input.handle)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); - return false; -} - -bool ValidateHandleOrInterface(const AssociatedEndpointHandle_Data& input, - ValidationContext* validation_context) { - if (validation_context->ClaimAssociatedEndpointHandle(input)) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); - return false; -} - -bool ValidateHandleOrInterface(const Interface_Data& input, - ValidationContext* validation_context) { - if (validation_context->ClaimHandle(input.handle)) - return true; - - ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE); - return false; -} - -bool ValidateHandleOrInterface(const Handle_Data& input, - ValidationContext* validation_context) { - if (validation_context->ClaimHandle(input)) - return true; - - ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE); - return false; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/validation_util.h b/mojo/public/cpp/bindings/lib/validation_util.h deleted file mode 100644 index ea5a991..0000000 --- a/mojo/public/cpp/bindings/lib/validation_util.h +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ - -#include <stdint.h> - -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace internal { - -// Checks whether decoding the pointer will overflow and produce a pointer -// smaller than |offset|. -inline bool ValidateEncodedPointer(const uint64_t* offset) { - // - Make sure |*offset| is no more than 32-bits. - // - Cast |offset| to uintptr_t so overflow behavior is well defined across - // 32-bit and 64-bit systems. - return *offset <= std::numeric_limits<uint32_t>::max() && - (reinterpret_cast<uintptr_t>(offset) + - static_cast<uint32_t>(*offset) >= - reinterpret_cast<uintptr_t>(offset)); -} - -template <typename T> -bool ValidatePointer(const Pointer<T>& input, - ValidationContext* validation_context) { - bool result = ValidateEncodedPointer(&input.offset); - if (!result) - ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER); - - return result; -} - -// Validates that |data| contains a valid struct header, in terms of alignment -// and size (i.e., the |num_bytes| field of the header is sufficient for storing -// the header itself). Besides, it checks that the memory range -// [data, data + num_bytes) is not marked as occupied by other objects in -// |validation_context|. On success, the memory range is marked as occupied. -// Note: Does not verify |version| or that |num_bytes| is correct for the -// claimed version. -MOJO_CPP_BINDINGS_EXPORT bool ValidateStructHeaderAndClaimMemory( - const void* data, - ValidationContext* validation_context); - -// Validates that |data| contains a valid union header, in terms of alignment -// and size. It checks that the memory range [data, data + kUnionDataSize) is -// not marked as occupied by other objects in |validation_context|. On success, -// the memory range is marked as occupied. -MOJO_CPP_BINDINGS_EXPORT bool ValidateNonInlinedUnionHeaderAndClaimMemory( - const void* data, - ValidationContext* validation_context); - -// Validates that the message is a request which doesn't expect a response. -MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestWithoutResponse( - const Message* message, - ValidationContext* validation_context); - -// Validates that the message is a request expecting a response. -MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestExpectingResponse( - const Message* message, - ValidationContext* validation_context); - -// Validates that the message is a response. -MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsResponse( - const Message* message, - ValidationContext* validation_context); - -// Validates that the message payload is a valid struct of type ParamsType. -template <typename ParamsType> -bool ValidateMessagePayload(const Message* message, - ValidationContext* validation_context) { - return ParamsType::Validate(message->payload(), validation_context); -} - -// The following Validate.*NonNullable() functions validate that the given -// |input| is not null/invalid. -template <typename T> -bool ValidatePointerNonNullable(const T& input, - const char* error_message, - ValidationContext* validation_context) { - if (input.offset) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - error_message); - return false; -} - -template <typename T> -bool ValidateInlinedUnionNonNullable(const T& input, - const char* error_message, - ValidationContext* validation_context) { - if (!input.is_null()) - return true; - - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - error_message); - return false; -} - -MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid( - const AssociatedInterface_Data& input); -MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid( - const AssociatedEndpointHandle_Data& input); -MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid( - const Interface_Data& input); -MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid( - const Handle_Data& input); - -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable( - const AssociatedInterface_Data& input, - const char* error_message, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable( - const AssociatedEndpointHandle_Data& input, - const char* error_message, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable( - const Interface_Data& input, - const char* error_message, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable( - const Handle_Data& input, - const char* error_message, - ValidationContext* validation_context); - -template <typename T> -bool ValidateContainer(const Pointer<T>& input, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - ValidationContext::ScopedDepthTracker depth_tracker(validation_context); - if (validation_context->ExceedsMaxDepth()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MAX_RECURSION_DEPTH); - return false; - } - return ValidatePointer(input, validation_context) && - T::Validate(input.Get(), validation_context, validate_params); -} - -template <typename T> -bool ValidateStruct(const Pointer<T>& input, - ValidationContext* validation_context) { - ValidationContext::ScopedDepthTracker depth_tracker(validation_context); - if (validation_context->ExceedsMaxDepth()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MAX_RECURSION_DEPTH); - return false; - } - return ValidatePointer(input, validation_context) && - T::Validate(input.Get(), validation_context); -} - -template <typename T> -bool ValidateInlinedUnion(const T& input, - ValidationContext* validation_context) { - ValidationContext::ScopedDepthTracker depth_tracker(validation_context); - if (validation_context->ExceedsMaxDepth()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MAX_RECURSION_DEPTH); - return false; - } - return T::Validate(&input, validation_context, true); -} - -template <typename T> -bool ValidateNonInlinedUnion(const Pointer<T>& input, - ValidationContext* validation_context) { - ValidationContext::ScopedDepthTracker depth_tracker(validation_context); - if (validation_context->ExceedsMaxDepth()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MAX_RECURSION_DEPTH); - return false; - } - return ValidatePointer(input, validation_context) && - T::Validate(input.Get(), validation_context, false); -} - -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface( - const AssociatedInterface_Data& input, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface( - const AssociatedEndpointHandle_Data& input, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface( - const Interface_Data& input, - ValidationContext* validation_context); -MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface( - const Handle_Data& input, - ValidationContext* validation_context); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h b/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h deleted file mode 100644 index cb24bc4..0000000 --- a/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_ - -#include <type_traits> - -#include "mojo/public/cpp/bindings/clone_traits.h" -#include "mojo/public/cpp/bindings/lib/equals_traits.h" -#include "third_party/WebKit/Source/wtf/HashMap.h" -#include "third_party/WebKit/Source/wtf/Optional.h" -#include "third_party/WebKit/Source/wtf/Vector.h" -#include "third_party/WebKit/Source/wtf/text/WTFString.h" - -namespace mojo { - -template <typename T> -struct CloneTraits<WTF::Vector<T>, false> { - static WTF::Vector<T> Clone(const WTF::Vector<T>& input) { - WTF::Vector<T> result; - result.reserveCapacity(input.size()); - for (const auto& element : input) - result.push_back(mojo::Clone(element)); - - return result; - } -}; - -template <typename K, typename V> -struct CloneTraits<WTF::HashMap<K, V>, false> { - static WTF::HashMap<K, V> Clone(const WTF::HashMap<K, V>& input) { - WTF::HashMap<K, V> result; - auto input_end = input.end(); - for (auto it = input.begin(); it != input_end; ++it) - result.add(mojo::Clone(it->key), mojo::Clone(it->value)); - return result; - } -}; - -namespace internal { - -template <typename T> -struct EqualsTraits<WTF::Vector<T>, false> { - static bool Equals(const WTF::Vector<T>& a, const WTF::Vector<T>& b) { - if (a.size() != b.size()) - return false; - for (size_t i = 0; i < a.size(); ++i) { - if (!internal::Equals(a[i], b[i])) - return false; - } - return true; - } -}; - -template <typename K, typename V> -struct EqualsTraits<WTF::HashMap<K, V>, false> { - static bool Equals(const WTF::HashMap<K, V>& a, const WTF::HashMap<K, V>& b) { - if (a.size() != b.size()) - return false; - - auto a_end = a.end(); - auto b_end = b.end(); - - for (auto iter = a.begin(); iter != a_end; ++iter) { - auto b_iter = b.find(iter->key); - if (b_iter == b_end || !internal::Equals(iter->value, b_iter->value)) - return false; - } - return true; - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/wtf_hash_util.h b/mojo/public/cpp/bindings/lib/wtf_hash_util.h deleted file mode 100644 index cc590da..0000000 --- a/mojo/public/cpp/bindings/lib/wtf_hash_util.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_HASH_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_HASH_UTIL_H_ - -#include <type_traits> - -#include "mojo/public/cpp/bindings/lib/hash_util.h" -#include "mojo/public/cpp/bindings/struct_ptr.h" -#include "third_party/WebKit/Source/wtf/HashFunctions.h" -#include "third_party/WebKit/Source/wtf/text/StringHash.h" -#include "third_party/WebKit/Source/wtf/text/WTFString.h" - -namespace mojo { -namespace internal { - -template <typename T> -size_t WTFHashCombine(size_t seed, const T& value) { - // Based on proposal in: - // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf - // - // TODO(tibell): We'd like to use WTF::DefaultHash instead of std::hash, but - // there is no general template specialization of DefaultHash for enums - // and there can't be an instance for bool. - return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2)); -} - -template <typename T, bool has_hash_method = HasHashMethod<T>::value> -struct WTFHashTraits; - -template <typename T> -size_t WTFHash(size_t seed, const T& value); - -template <typename T> -struct WTFHashTraits<T, true> { - static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } -}; - -template <typename T> -struct WTFHashTraits<T, false> { - static size_t Hash(size_t seed, const T& value) { - return WTFHashCombine(seed, value); - } -}; - -template <> -struct WTFHashTraits<WTF::String, false> { - static size_t Hash(size_t seed, const WTF::String& value) { - return HashCombine(seed, WTF::StringHash::hash(value)); - } -}; - -template <typename T> -size_t WTFHash(size_t seed, const T& value) { - return WTFHashTraits<T>::Hash(seed, value); -} - -template <typename T> -struct StructPtrHashFn { - static unsigned hash(const StructPtr<T>& value) { - return value.Hash(kHashSeed); - } - static bool equal(const StructPtr<T>& left, const StructPtr<T>& right) { - return left.Equals(right); - } - static const bool safeToCompareToEmptyOrDeleted = false; -}; - -template <typename T> -struct InlinedStructPtrHashFn { - static unsigned hash(const InlinedStructPtr<T>& value) { - return value.Hash(kHashSeed); - } - static bool equal(const InlinedStructPtr<T>& left, - const InlinedStructPtr<T>& right) { - return left.Equals(right); - } - static const bool safeToCompareToEmptyOrDeleted = false; -}; - -} // namespace internal -} // namespace mojo - -namespace WTF { - -template <typename T> -struct DefaultHash<mojo::StructPtr<T>> { - using Hash = mojo::internal::StructPtrHashFn<T>; -}; - -template <typename T> -struct HashTraits<mojo::StructPtr<T>> - : public GenericHashTraits<mojo::StructPtr<T>> { - static const bool hasIsEmptyValueFunction = true; - static bool isEmptyValue(const mojo::StructPtr<T>& value) { - return value.is_null(); - } - static void constructDeletedValue(mojo::StructPtr<T>& slot, bool) { - mojo::internal::StructPtrWTFHelper<T>::ConstructDeletedValue(slot); - } - static bool isDeletedValue(const mojo::StructPtr<T>& value) { - return mojo::internal::StructPtrWTFHelper<T>::IsHashTableDeletedValue( - value); - } -}; - -template <typename T> -struct DefaultHash<mojo::InlinedStructPtr<T>> { - using Hash = mojo::internal::InlinedStructPtrHashFn<T>; -}; - -template <typename T> -struct HashTraits<mojo::InlinedStructPtr<T>> - : public GenericHashTraits<mojo::InlinedStructPtr<T>> { - static const bool hasIsEmptyValueFunction = true; - static bool isEmptyValue(const mojo::InlinedStructPtr<T>& value) { - return value.is_null(); - } - static void constructDeletedValue(mojo::InlinedStructPtr<T>& slot, bool) { - mojo::internal::InlinedStructPtrWTFHelper<T>::ConstructDeletedValue(slot); - } - static bool isDeletedValue(const mojo::InlinedStructPtr<T>& value) { - return mojo::internal::InlinedStructPtrWTFHelper< - T>::IsHashTableDeletedValue(value); - } -}; - -} // namespace WTF - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_HASH_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/wtf_serialization.h b/mojo/public/cpp/bindings/lib/wtf_serialization.h deleted file mode 100644 index 0f112b9..0000000 --- a/mojo/public/cpp/bindings/lib/wtf_serialization.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ - -#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" -#include "mojo/public/cpp/bindings/map_traits_wtf_hash_map.h" -#include "mojo/public/cpp/bindings/string_traits_wtf.h" - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/map.h b/mojo/public/cpp/bindings/map.h deleted file mode 100644 index c1ba075..0000000 --- a/mojo/public/cpp/bindings/map.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ - -#include <map> -#include <unordered_map> -#include <utility> - -namespace mojo { - -// TODO(yzshen): These conversion functions should be removed and callsites -// should be revisited and changed to use the same map type. -template <typename Key, typename Value> -std::unordered_map<Key, Value> MapToUnorderedMap( - const std::map<Key, Value>& input) { - return std::unordered_map<Key, Value>(input.begin(), input.end()); -} - -template <typename Key, typename Value> -std::unordered_map<Key, Value> MapToUnorderedMap(std::map<Key, Value>&& input) { - return std::unordered_map<Key, Value>(std::make_move_iterator(input.begin()), - std::make_move_iterator(input.end())); -} - -template <typename Key, typename Value> -std::map<Key, Value> UnorderedMapToMap( - const std::unordered_map<Key, Value>& input) { - return std::map<Key, Value>(input.begin(), input.end()); -} - -template <typename Key, typename Value> -std::map<Key, Value> UnorderedMapToMap(std::unordered_map<Key, Value>&& input) { - return std::map<Key, Value>(std::make_move_iterator(input.begin()), - std::make_move_iterator(input.end())); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ diff --git a/mojo/public/cpp/bindings/map_data_view.h b/mojo/public/cpp/bindings/map_data_view.h deleted file mode 100644 index a65bb9e..0000000 --- a/mojo/public/cpp/bindings/map_data_view.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_ - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/array_data_view.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/map_data_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" - -namespace mojo { - -template <typename K, typename V> -class MapDataView { - public: - using Data_ = typename internal::MojomTypeTraits<MapDataView<K, V>>::Data; - - MapDataView() {} - - MapDataView(Data_* data, internal::SerializationContext* context) - : keys_(data ? data->keys.Get() : nullptr, context), - values_(data ? data->values.Get() : nullptr, context) {} - - bool is_null() const { - DCHECK_EQ(keys_.is_null(), values_.is_null()); - return keys_.is_null(); - } - - size_t size() const { - DCHECK_EQ(keys_.size(), values_.size()); - return keys_.size(); - } - - ArrayDataView<K>& keys() { return keys_; } - const ArrayDataView<K>& keys() const { return keys_; } - - template <typename U> - bool ReadKeys(U* output) { - return internal::Deserialize<ArrayDataView<K>>(keys_.data_, output, - keys_.context_); - } - - ArrayDataView<V>& values() { return values_; } - const ArrayDataView<V>& values() const { return values_; } - - template <typename U> - bool ReadValues(U* output) { - return internal::Deserialize<ArrayDataView<V>>(values_.data_, output, - values_.context_); - } - - private: - ArrayDataView<K> keys_; - ArrayDataView<V> values_; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/map_traits.h b/mojo/public/cpp/bindings/map_traits.h deleted file mode 100644 index 5c0d8b2..0000000 --- a/mojo/public/cpp/bindings/map_traits.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom map. -// -// Usually you would like to do a partial specialization for a map template. -// Imagine you want to specialize it for CustomMap<>, you need to implement: -// -// template <typename K, typename V> -// struct MapTraits<CustomMap<K, V>> { -// using Key = K; -// using Value = V; -// -// // These two methods are optional. Please see comments in struct_traits.h -// static bool IsNull(const CustomMap<K, V>& input); -// static void SetToNull(CustomMap<K, V>* output); -// -// static size_t GetSize(const CustomMap<K, V>& input); -// -// static CustomConstIterator GetBegin(const CustomMap<K, V>& input); -// static CustomIterator GetBegin(CustomMap<K, V>& input); -// -// static void AdvanceIterator(CustomConstIterator& iterator); -// static void AdvanceIterator(CustomIterator& iterator); -// -// static const K& GetKey(CustomIterator& iterator); -// static const K& GetKey(CustomConstIterator& iterator); -// -// static V& GetValue(CustomIterator& iterator); -// static const V& GetValue(CustomConstIterator& iterator); -// -// // Returning false results in deserialization failure and causes the -// // message pipe receiving it to be disconnected. |IK| and |IV| are -// // separate input key/value template parameters that allows for the -// // the key/value types to be forwarded. -// template <typename IK, typename IV> -// static bool Insert(CustomMap<K, V>& input, -// IK&& key, -// IV&& value); -// -// static void SetToEmpty(CustomMap<K, V>* output); -// }; -// -template <typename T> -struct MapTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/map_traits_stl.h b/mojo/public/cpp/bindings/map_traits_stl.h deleted file mode 100644 index 83a4399..0000000 --- a/mojo/public/cpp/bindings/map_traits_stl.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_ - -#include <map> -#include <unordered_map> - -#include "mojo/public/cpp/bindings/map_traits.h" - -namespace mojo { - -template <typename K, typename V> -struct MapTraits<std::map<K, V>> { - using Key = K; - using Value = V; - using Iterator = typename std::map<K, V>::iterator; - using ConstIterator = typename std::map<K, V>::const_iterator; - - static bool IsNull(const std::map<K, V>& input) { - // std::map<> is always converted to non-null mojom map. - return false; - } - - static void SetToNull(std::map<K, V>* output) { - // std::map<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const std::map<K, V>& input) { return input.size(); } - - static ConstIterator GetBegin(const std::map<K, V>& input) { - return input.begin(); - } - static Iterator GetBegin(std::map<K, V>& input) { return input.begin(); } - - static void AdvanceIterator(ConstIterator& iterator) { iterator++; } - static void AdvanceIterator(Iterator& iterator) { iterator++; } - - static const K& GetKey(Iterator& iterator) { return iterator->first; } - static const K& GetKey(ConstIterator& iterator) { return iterator->first; } - - static V& GetValue(Iterator& iterator) { return iterator->second; } - static const V& GetValue(ConstIterator& iterator) { return iterator->second; } - - static bool Insert(std::map<K, V>& input, const K& key, V&& value) { - input.insert(std::make_pair(key, std::forward<V>(value))); - return true; - } - static bool Insert(std::map<K, V>& input, const K& key, const V& value) { - input.insert(std::make_pair(key, value)); - return true; - } - - static void SetToEmpty(std::map<K, V>* output) { output->clear(); } -}; - -template <typename K, typename V> -struct MapTraits<std::unordered_map<K, V>> { - using Key = K; - using Value = V; - using Iterator = typename std::unordered_map<K, V>::iterator; - using ConstIterator = typename std::unordered_map<K, V>::const_iterator; - - static bool IsNull(const std::unordered_map<K, V>& input) { - // std::unordered_map<> is always converted to non-null mojom map. - return false; - } - - static void SetToNull(std::unordered_map<K, V>* output) { - // std::unordered_map<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const std::unordered_map<K, V>& input) { - return input.size(); - } - - static ConstIterator GetBegin(const std::unordered_map<K, V>& input) { - return input.begin(); - } - static Iterator GetBegin(std::unordered_map<K, V>& input) { - return input.begin(); - } - - static void AdvanceIterator(ConstIterator& iterator) { iterator++; } - static void AdvanceIterator(Iterator& iterator) { iterator++; } - - static const K& GetKey(Iterator& iterator) { return iterator->first; } - static const K& GetKey(ConstIterator& iterator) { return iterator->first; } - - static V& GetValue(Iterator& iterator) { return iterator->second; } - static const V& GetValue(ConstIterator& iterator) { return iterator->second; } - - template <typename IK, typename IV> - static bool Insert(std::unordered_map<K, V>& input, IK&& key, IV&& value) { - input.insert( - std::make_pair(std::forward<IK>(key), std::forward<IV>(value))); - return true; - } - - static void SetToEmpty(std::unordered_map<K, V>* output) { output->clear(); } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_ diff --git a/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h b/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h deleted file mode 100644 index dd68b36..0000000 --- a/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_ - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/map_traits.h" -#include "third_party/WebKit/Source/wtf/HashMap.h" - -namespace mojo { - -template <typename K, typename V> -struct MapTraits<WTF::HashMap<K, V>> { - using Key = K; - using Value = V; - using Iterator = typename WTF::HashMap<K, V>::iterator; - using ConstIterator = typename WTF::HashMap<K, V>::const_iterator; - - static bool IsNull(const WTF::HashMap<K, V>& input) { - // WTF::HashMap<> is always converted to non-null mojom map. - return false; - } - - static void SetToNull(WTF::HashMap<K, V>* output) { - // WTF::HashMap<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const WTF::HashMap<K, V>& input) { - return input.size(); - } - - static ConstIterator GetBegin(const WTF::HashMap<K, V>& input) { - return input.begin(); - } - static Iterator GetBegin(WTF::HashMap<K, V>& input) { return input.begin(); } - - static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } - static void AdvanceIterator(Iterator& iterator) { ++iterator; } - - static const K& GetKey(Iterator& iterator) { return iterator->key; } - static const K& GetKey(ConstIterator& iterator) { return iterator->key; } - - static V& GetValue(Iterator& iterator) { return iterator->value; } - static const V& GetValue(ConstIterator& iterator) { return iterator->value; } - - template <typename IK, typename IV> - static bool Insert(WTF::HashMap<K, V>& input, IK&& key, IV&& value) { - if (!WTF::HashMap<K, V>::isValidKey(key)) { - LOG(ERROR) << "The key value is disallowed by WTF::HashMap"; - return false; - } - input.insert(std::forward<IK>(key), std::forward<IV>(value)); - return true; - } - - static void SetToEmpty(WTF::HashMap<K, V>* output) { output->clear(); } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_ diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h deleted file mode 100644 index 48e6900..0000000 --- a/mojo/public/cpp/bindings/message.h +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <memory> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/message_buffer.h" -#include "mojo/public/cpp/bindings/lib/message_internal.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/message.h" - -namespace mojo { - -class AssociatedGroupController; - -using ReportBadMessageCallback = base::Callback<void(const std::string& error)>; - -// Message is a holder for the data and handles to be sent over a MessagePipe. -// Message owns its data and handles, but a consumer of Message is free to -// mutate the data and handles. The message's data is comprised of a header -// followed by payload. -class MOJO_CPP_BINDINGS_EXPORT Message { - public: - static const uint32_t kFlagExpectsResponse = 1 << 0; - static const uint32_t kFlagIsResponse = 1 << 1; - static const uint32_t kFlagIsSync = 1 << 2; - - Message(); - Message(Message&& other); - - ~Message(); - - Message& operator=(Message&& other); - - // Resets the Message to an uninitialized state. Upon reset, the Message - // exists as if it were default-constructed: it has no data buffer and owns no - // handles. - void Reset(); - - // Indicates whether this Message is uninitialized. - bool IsNull() const { return !buffer_; } - - // Initializes a Message with enough space for |capacity| bytes. - void Initialize(size_t capacity, bool zero_initialized); - - // Initializes a Message from an existing Mojo MessageHandle. - void InitializeFromMojoMessage(ScopedMessageHandle message, - uint32_t num_bytes, - std::vector<Handle>* handles); - - uint32_t data_num_bytes() const { - return static_cast<uint32_t>(buffer_->size()); - } - - // Access the raw bytes of the message. - const uint8_t* data() const { - return static_cast<const uint8_t*>(buffer_->data()); - } - - uint8_t* mutable_data() { return static_cast<uint8_t*>(buffer_->data()); } - - // Access the header. - const internal::MessageHeader* header() const { - return static_cast<const internal::MessageHeader*>(buffer_->data()); - } - internal::MessageHeader* header() { - return static_cast<internal::MessageHeader*>(buffer_->data()); - } - - const internal::MessageHeaderV1* header_v1() const { - DCHECK_GE(version(), 1u); - return static_cast<const internal::MessageHeaderV1*>(buffer_->data()); - } - internal::MessageHeaderV1* header_v1() { - DCHECK_GE(version(), 1u); - return static_cast<internal::MessageHeaderV1*>(buffer_->data()); - } - - const internal::MessageHeaderV2* header_v2() const { - DCHECK_GE(version(), 2u); - return static_cast<const internal::MessageHeaderV2*>(buffer_->data()); - } - internal::MessageHeaderV2* header_v2() { - DCHECK_GE(version(), 2u); - return static_cast<internal::MessageHeaderV2*>(buffer_->data()); - } - - uint32_t version() const { return header()->version; } - - uint32_t interface_id() const { return header()->interface_id; } - void set_interface_id(uint32_t id) { header()->interface_id = id; } - - uint32_t name() const { return header()->name; } - bool has_flag(uint32_t flag) const { return !!(header()->flags & flag); } - - // Access the request_id field (if present). - uint64_t request_id() const { return header_v1()->request_id; } - void set_request_id(uint64_t request_id) { - header_v1()->request_id = request_id; - } - - // Access the payload. - const uint8_t* payload() const; - uint8_t* mutable_payload() { return const_cast<uint8_t*>(payload()); } - uint32_t payload_num_bytes() const; - - uint32_t payload_num_interface_ids() const; - const uint32_t* payload_interface_ids() const; - - // Access the handles. - const std::vector<Handle>* handles() const { return &handles_; } - std::vector<Handle>* mutable_handles() { return &handles_; } - - const std::vector<ScopedInterfaceEndpointHandle>* - associated_endpoint_handles() const { - return &associated_endpoint_handles_; - } - std::vector<ScopedInterfaceEndpointHandle>* - mutable_associated_endpoint_handles() { - return &associated_endpoint_handles_; - } - - // Access the underlying Buffer interface. - internal::Buffer* buffer() { return buffer_.get(); } - - // Takes a scoped MessageHandle which may be passed to |WriteMessageNew()| for - // transmission. Note that this invalidates this Message object, taking - // ownership of its internal storage and any attached handles. - ScopedMessageHandle TakeMojoMessage(); - - // Notifies the system that this message is "bad," in this case meaning it was - // rejected by bindings validation code. - void NotifyBadMessage(const std::string& error); - - // Serializes |associated_endpoint_handles_| into the payload_interface_ids - // field. - void SerializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller); - - // Deserializes |associated_endpoint_handles_| from the payload_interface_ids - // field. - bool DeserializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller); - - private: - void CloseHandles(); - - std::unique_ptr<internal::MessageBuffer> buffer_; - std::vector<Handle> handles_; - std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles_; - - DISALLOW_COPY_AND_ASSIGN(Message); -}; - -class MessageReceiver { - public: - virtual ~MessageReceiver() {} - - // The receiver may mutate the given message. Returns true if the message - // was accepted and false otherwise, indicating that the message was invalid - // or malformed. - virtual bool Accept(Message* message) WARN_UNUSED_RESULT = 0; -}; - -class MessageReceiverWithResponder : public MessageReceiver { - public: - ~MessageReceiverWithResponder() override {} - - // A variant on Accept that registers a MessageReceiver (known as the - // responder) to handle the response message generated from the given - // message. The responder's Accept method may be called during - // AcceptWithResponder or some time after its return. - virtual bool AcceptWithResponder(Message* message, - std::unique_ptr<MessageReceiver> responder) - WARN_UNUSED_RESULT = 0; -}; - -// A MessageReceiver that is also able to provide status about the state -// of the underlying MessagePipe to which it will be forwarding messages -// received via the |Accept()| call. -class MessageReceiverWithStatus : public MessageReceiver { - public: - ~MessageReceiverWithStatus() override {} - - // Returns |true| if this MessageReceiver is currently bound to a MessagePipe, - // the pipe has not been closed, and the pipe has not encountered an error. - virtual bool IsValid() = 0; - - // DCHECKs if this MessageReceiver is currently bound to a MessagePipe, the - // pipe has not been closed, and the pipe has not encountered an error. - // This function may be called on any thread. - virtual void DCheckInvalid(const std::string& message) = 0; -}; - -// An alternative to MessageReceiverWithResponder for cases in which it -// is necessary for the implementor of this interface to know about the status -// of the MessagePipe which will carry the responses. -class MessageReceiverWithResponderStatus : public MessageReceiver { - public: - ~MessageReceiverWithResponderStatus() override {} - - // A variant on Accept that registers a MessageReceiverWithStatus (known as - // the responder) to handle the response message generated from the given - // message. Any of the responder's methods (Accept or IsValid) may be called - // during AcceptWithResponder or some time after its return. - virtual bool AcceptWithResponder(Message* message, - std::unique_ptr<MessageReceiverWithStatus> - responder) WARN_UNUSED_RESULT = 0; -}; - -class MOJO_CPP_BINDINGS_EXPORT PassThroughFilter - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - PassThroughFilter(); - ~PassThroughFilter() override; - - // MessageReceiver: - bool Accept(Message* message) override; - - private: - DISALLOW_COPY_AND_ASSIGN(PassThroughFilter); -}; - -namespace internal { -class SyncMessageResponseSetup; -} - -// An object which should be constructed on the stack immediately before making -// a sync request for which the caller wishes to perform custom validation of -// the response value(s). It is illegal to make more than one sync call during -// the lifetime of the topmost SyncMessageResponseContext, but it is legal to -// nest contexts to support reentrancy. -// -// Usage should look something like: -// -// SyncMessageResponseContext response_context; -// foo_interface->SomeSyncCall(&response_value); -// if (response_value.IsBad()) -// response_context.ReportBadMessage("Bad response_value!"); -// -class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseContext { - public: - SyncMessageResponseContext(); - ~SyncMessageResponseContext(); - - static SyncMessageResponseContext* current(); - - void ReportBadMessage(const std::string& error); - - const ReportBadMessageCallback& GetBadMessageCallback(); - - private: - friend class internal::SyncMessageResponseSetup; - - SyncMessageResponseContext* outer_context_; - Message response_; - ReportBadMessageCallback bad_message_callback_; - - DISALLOW_COPY_AND_ASSIGN(SyncMessageResponseContext); -}; - -// Read a single message from the pipe. The caller should have created the -// Message, but not called Initialize(). Returns MOJO_RESULT_SHOULD_WAIT if -// the caller should wait on the handle to become readable. Returns -// MOJO_RESULT_OK if the message was read successfully and should be -// dispatched, otherwise returns an error code if something went wrong. -// -// NOTE: The message hasn't been validated and may be malformed! -MojoResult ReadMessage(MessagePipeHandle handle, Message* message); - -// Reports the currently dispatching Message as bad. Note that this is only -// legal to call from directly within the stack frame of a message dispatch. If -// you need to do asynchronous work before you can determine the legitimacy of -// a message, use TakeBadMessageCallback() and retain its result until you're -// ready to invoke or discard it. -MOJO_CPP_BINDINGS_EXPORT -void ReportBadMessage(const std::string& error); - -// Acquires a callback which may be run to report the currently dispatching -// Message as bad. Note that this is only legal to call from directly within the -// stack frame of a message dispatch, but the returned callback may be called -// exactly once any time thereafter to report the message as bad. This may only -// be called once per message. -MOJO_CPP_BINDINGS_EXPORT -ReportBadMessageCallback GetBadMessageCallback(); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_ diff --git a/mojo/public/cpp/bindings/message_header_validator.h b/mojo/public/cpp/bindings/message_header_validator.h deleted file mode 100644 index 50c19db..0000000 --- a/mojo/public/cpp/bindings/message_header_validator.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_HEADER_VALIDATOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_HEADER_VALIDATOR_H_ - -#include "base/compiler_specific.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class MOJO_CPP_BINDINGS_EXPORT MessageHeaderValidator - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - MessageHeaderValidator(); - explicit MessageHeaderValidator(const std::string& description); - - // Sets the description associated with this validator. Used for reporting - // more detailed validation errors. - void SetDescription(const std::string& description); - - bool Accept(Message* message) override; - - private: - std::string description_; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_HEADER_VALIDATOR_H_ diff --git a/mojo/public/cpp/bindings/native_enum.h b/mojo/public/cpp/bindings/native_enum.h deleted file mode 100644 index 08b43b7..0000000 --- a/mojo/public/cpp/bindings/native_enum.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_ - -#include <functional> - -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/native_enum_data.h" - -namespace mojo { - -// Native-only enums correspond to "[Native] enum Foo;" definitions in mojom. -enum class NativeEnum : int32_t {}; - -} // namespace mojo - -namespace std { - -template <> -struct hash<mojo::NativeEnum> - : public mojo::internal::EnumHashImpl<mojo::NativeEnum> {}; - -} // namespace std - -#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_ diff --git a/mojo/public/cpp/bindings/native_struct.h b/mojo/public/cpp/bindings/native_struct.h deleted file mode 100644 index ac27250..0000000 --- a/mojo/public/cpp/bindings/native_struct.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ - -#include <vector> - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/struct_ptr.h" -#include "mojo/public/cpp/bindings/type_converter.h" - -namespace mojo { - -class NativeStruct; -using NativeStructPtr = StructPtr<NativeStruct>; - -// Native-only structs correspond to "[Native] struct Foo;" definitions in -// mojom. -class MOJO_CPP_BINDINGS_EXPORT NativeStruct { - public: - using Data_ = internal::NativeStruct_Data; - - static NativeStructPtr New(); - - template <typename U> - static NativeStructPtr From(const U& u) { - return TypeConverter<NativeStructPtr, U>::Convert(u); - } - - template <typename U> - U To() const { - return TypeConverter<U, NativeStruct>::Convert(*this); - } - - NativeStruct(); - ~NativeStruct(); - - NativeStructPtr Clone() const; - bool Equals(const NativeStruct& other) const; - size_t Hash(size_t seed) const; - - base::Optional<std::vector<uint8_t>> data; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ diff --git a/mojo/public/cpp/bindings/native_struct_data_view.h b/mojo/public/cpp/bindings/native_struct_data_view.h deleted file mode 100644 index 613bd7a..0000000 --- a/mojo/public/cpp/bindings/native_struct_data_view.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ - -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { - -class NativeStructDataView { - public: - using Data_ = internal::NativeStruct_Data; - - NativeStructDataView() {} - - NativeStructDataView(Data_* data, internal::SerializationContext* context) - : data_(data) {} - - bool is_null() const { return !data_; } - - size_t size() const { return data_->data.size(); } - - uint8_t operator[](size_t index) const { return data_->data.at(index); } - - const uint8_t* data() const { return data_->data.storage(); } - - private: - Data_* data_ = nullptr; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/pipe_control_message_handler.h b/mojo/public/cpp/bindings/pipe_control_message_handler.h deleted file mode 100644 index a5c04da..0000000 --- a/mojo/public/cpp/bindings/pipe_control_message_handler.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class PipeControlMessageHandlerDelegate; - -// Handler for messages defined in pipe_control_messages.mojom. -class MOJO_CPP_BINDINGS_EXPORT PipeControlMessageHandler - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - explicit PipeControlMessageHandler( - PipeControlMessageHandlerDelegate* delegate); - ~PipeControlMessageHandler() override; - - // Sets the description for this handler. Used only when reporting validation - // errors. - void SetDescription(const std::string& description); - - // NOTE: |message| must have passed message header validation. - static bool IsPipeControlMessage(const Message* message); - - // MessageReceiver implementation: - - // NOTE: |message| must: - // - have passed message header validation; and - // - be a pipe control message (i.e., IsPipeControlMessage() returns true). - // If the method returns false, the message pipe should be closed. - bool Accept(Message* message) override; - - private: - // |message| must have passed message header validation. - bool Validate(Message* message); - bool RunOrClosePipe(Message* message); - - std::string description_; - PipeControlMessageHandlerDelegate* const delegate_; - - DISALLOW_COPY_AND_ASSIGN(PipeControlMessageHandler); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_H_ diff --git a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h b/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h deleted file mode 100644 index 16fd918..0000000 --- a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_ - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_id.h" - -namespace mojo { - -class PipeControlMessageHandlerDelegate { - public: - // The implementation of the following methods should return false if the - // notification is unexpected. In that case, the user of this delegate is - // expected to close the message pipe. - virtual bool OnPeerAssociatedEndpointClosed( - InterfaceId id, - const base::Optional<DisconnectReason>& reason) = 0; - - protected: - virtual ~PipeControlMessageHandlerDelegate() {} -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_ diff --git a/mojo/public/cpp/bindings/pipe_control_message_proxy.h b/mojo/public/cpp/bindings/pipe_control_message_proxy.h deleted file mode 100644 index 52c408f..0000000 --- a/mojo/public/cpp/bindings/pipe_control_message_proxy.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_ - -#include "base/macros.h" -#include "base/optional.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class MessageReceiver; - -// Proxy for request messages defined in pipe_control_messages.mojom. -// -// NOTE: This object may be used from multiple threads. -class MOJO_CPP_BINDINGS_EXPORT PipeControlMessageProxy { - public: - // Doesn't take ownership of |receiver|. If This PipeControlMessageProxy will - // be used from multiple threads, |receiver| must be thread-safe. - explicit PipeControlMessageProxy(MessageReceiver* receiver); - - void NotifyPeerEndpointClosed(InterfaceId id, - const base::Optional<DisconnectReason>& reason); - - static Message ConstructPeerEndpointClosedMessage( - InterfaceId id, - const base::Optional<DisconnectReason>& reason); - - private: - // Not owned. - MessageReceiver* receiver_; - - DISALLOW_COPY_AND_ASSIGN(PipeControlMessageProxy); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_ diff --git a/mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h b/mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h deleted file mode 100644 index 4d40cdf..0000000 --- a/mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_RAW_PTR_IMPL_REF_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_RAW_PTR_IMPL_REF_TRAITS_H_ - -namespace mojo { - -// Default traits for a binding's implementation reference type. This -// corresponds to a raw pointer. -template <typename Interface> -struct RawPtrImplRefTraits { - using PointerType = Interface*; - - static bool IsNull(PointerType ptr) { return !ptr; } - static Interface* GetRawPointer(PointerType* ptr) { return *ptr; } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_RAW_PTR_IMPL_REF_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h b/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h deleted file mode 100644 index 16527cf..0000000 --- a/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ - -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_id.h" - -namespace mojo { - -class AssociatedGroupController; - -// ScopedInterfaceEndpointHandle refers to one end of an interface, either the -// implementation side or the client side. -// Threading: At any given time, a ScopedInterfaceEndpointHandle should only -// be accessed from a single thread. -class MOJO_CPP_BINDINGS_EXPORT ScopedInterfaceEndpointHandle { - public: - // Creates a pair of handles representing the two endpoints of an interface, - // which are not yet associated with a message pipe. - static void CreatePairPendingAssociation( - ScopedInterfaceEndpointHandle* handle0, - ScopedInterfaceEndpointHandle* handle1); - - // Creates an invalid endpoint handle. - ScopedInterfaceEndpointHandle(); - - ScopedInterfaceEndpointHandle(ScopedInterfaceEndpointHandle&& other); - - ~ScopedInterfaceEndpointHandle(); - - ScopedInterfaceEndpointHandle& operator=( - ScopedInterfaceEndpointHandle&& other); - - bool is_valid() const; - - // Returns true if the interface hasn't associated with a message pipe. - bool pending_association() const; - - // Returns kInvalidInterfaceId when in pending association state or the handle - // is invalid. - InterfaceId id() const; - - // Returns null when in pending association state or the handle is invalid. - AssociatedGroupController* group_controller() const; - - // Returns the disconnect reason if the peer handle is closed before - // association and specifies a custom disconnect reason. - const base::Optional<DisconnectReason>& disconnect_reason() const; - - enum AssociationEvent { - // The interface has been associated with a message pipe. - ASSOCIATED, - // The peer of this object has been closed before association. - PEER_CLOSED_BEFORE_ASSOCIATION - }; - - using AssociationEventCallback = base::OnceCallback<void(AssociationEvent)>; - // Note: - // - |handler| won't run if the handle is invalid. Otherwise, |handler| is run - // on the calling thread asynchronously, even if the interface has already - // been associated or the peer has been closed before association. - // - |handler| won't be called after this object is destroyed or reset. - // - A null |handler| can be used to cancel the previous callback. - void SetAssociationEventHandler(AssociationEventCallback handler); - - void reset(); - void ResetWithReason(uint32_t custom_reason, const std::string& description); - - private: - friend class AssociatedGroupController; - friend class AssociatedGroup; - - class State; - - // Used by AssociatedGroupController. - ScopedInterfaceEndpointHandle( - InterfaceId id, - scoped_refptr<AssociatedGroupController> group_controller); - - // Used by AssociatedGroupController. - // The peer of this handle will join |peer_group_controller|. - bool NotifyAssociation( - InterfaceId id, - scoped_refptr<AssociatedGroupController> peer_group_controller); - - void ResetInternal(const base::Optional<DisconnectReason>& reason); - - // Used by AssociatedGroup. - // It is safe to run the returned callback on any thread, or after this handle - // is destroyed. - // The return value of the getter: - // - If the getter is retrieved when the handle is invalid, the return value - // of the getter will always be null. - // - If the getter is retrieved when the handle is valid and non-pending, - // the return value of the getter will be non-null and remain unchanged - // even if the handle is later reset. - // - If the getter is retrieved when the handle is valid but pending - // asssociation, the return value of the getter will initially be null, - // change to non-null when the handle is associated, and remain unchanged - // ever since. - base::Callback<AssociatedGroupController*()> CreateGroupControllerGetter() - const; - - scoped_refptr<State> state_; - - DISALLOW_COPY_AND_ASSIGN(ScopedInterfaceEndpointHandle); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ diff --git a/mojo/public/cpp/bindings/string_data_view.h b/mojo/public/cpp/bindings/string_data_view.h deleted file mode 100644 index 2b091b4..0000000 --- a/mojo/public/cpp/bindings/string_data_view.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_ - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { - -// Access to the contents of a serialized string. -class StringDataView { - public: - StringDataView() {} - - StringDataView(internal::String_Data* data, - internal::SerializationContext* context) - : data_(data) {} - - bool is_null() const { return !data_; } - - const char* storage() const { return data_->storage(); } - - size_t size() const { return data_->size(); } - - private: - internal::String_Data* data_ = nullptr; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/string_traits.h b/mojo/public/cpp/bindings/string_traits.h deleted file mode 100644 index 7d3075a..0000000 --- a/mojo/public/cpp/bindings/string_traits.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ - -#include "mojo/public/cpp/bindings/string_data_view.h" - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom string. -// -// Imagine you want to specialize it for CustomString, usually you need to -// implement: -// -// template <T> -// struct StringTraits<CustomString> { -// // These two methods are optional. Please see comments in struct_traits.h -// static bool IsNull(const CustomString& input); -// static void SetToNull(CustomString* output); -// -// static size_t GetSize(const CustomString& input); -// static const char* GetData(const CustomString& input); -// -// // The caller guarantees that |!input.is_null()|. -// static bool Read(StringDataView input, CustomString* output); -// }; -// -// In some cases, you may need to do conversion before you can return the size -// and data as 8-bit characters for serialization. (For example, CustomString is -// UTF-16 string). In that case, you can add two optional methods: -// -// static void* SetUpContext(const CustomString& input); -// static void TearDownContext(const CustomString& input, void* context); -// -// And then you append a second parameter, void* context, to GetSize() and -// GetData(): -// -// static size_t GetSize(const CustomString& input, void* context); -// static const char* GetData(const CustomString& input, void* context); -// -// If a CustomString instance is not null, the serialization code will call -// SetUpContext() at the beginning, and pass the resulting context pointer to -// GetSize()/GetData(). After serialization is done, it calls TearDownContext() -// so that you can do any necessary cleanup. -// -template <typename T> -struct StringTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/string_traits_stl.h b/mojo/public/cpp/bindings/string_traits_stl.h deleted file mode 100644 index f6cc8ad..0000000 --- a/mojo/public/cpp/bindings/string_traits_stl.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ - -#include <string> - -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { - -template <> -struct StringTraits<std::string> { - static bool IsNull(const std::string& input) { - // std::string is always converted to non-null mojom string. - return false; - } - - static void SetToNull(std::string* output) { - // std::string doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const std::string& input) { return input.size(); } - - static const char* GetData(const std::string& input) { return input.data(); } - - static bool Read(StringDataView input, std::string* output) { - output->assign(input.storage(), input.size()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STL_H_ diff --git a/mojo/public/cpp/bindings/string_traits_string16.h b/mojo/public/cpp/bindings/string_traits_string16.h deleted file mode 100644 index f96973a..0000000 --- a/mojo/public/cpp/bindings/string_traits_string16.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ - -#include "base/strings/string16.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { - -template <> -struct MOJO_CPP_BINDINGS_EXPORT StringTraits<base::string16> { - static bool IsNull(const base::string16& input) { - // base::string16 is always converted to non-null mojom string. - return false; - } - - static void SetToNull(base::string16* output) { - // Convert null to an "empty" base::string16. - output->clear(); - } - - static void* SetUpContext(const base::string16& input); - static void TearDownContext(const base::string16& input, void* context); - - static size_t GetSize(const base::string16& input, void* context); - static const char* GetData(const base::string16& input, void* context); - - static bool Read(StringDataView input, base::string16* output); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_ diff --git a/mojo/public/cpp/bindings/string_traits_string_piece.h b/mojo/public/cpp/bindings/string_traits_string_piece.h deleted file mode 100644 index af6be89..0000000 --- a/mojo/public/cpp/bindings/string_traits_string_piece.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ - -#include "base/strings/string_piece.h" -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { - -template <> -struct StringTraits<base::StringPiece> { - static bool IsNull(const base::StringPiece& input) { - // base::StringPiece is always converted to non-null mojom string. We could - // have let StringPiece containing a null data pointer map to null mojom - // string, but StringPiece::empty() returns true in this case. It seems - // confusing to mix the concept of empty and null strings, especially - // because they mean different things in mojom. - return false; - } - - static void SetToNull(base::StringPiece* output) { - // Convert null to an "empty" base::StringPiece. - output->set(nullptr, 0); - } - - static size_t GetSize(const base::StringPiece& input) { return input.size(); } - - static const char* GetData(const base::StringPiece& input) { - return input.data(); - } - - static bool Read(StringDataView input, base::StringPiece* output) { - output->set(input.storage(), input.size()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING_PIECE_H_ diff --git a/mojo/public/cpp/bindings/string_traits_wtf.h b/mojo/public/cpp/bindings/string_traits_wtf.h deleted file mode 100644 index 238c2eb..0000000 --- a/mojo/public/cpp/bindings/string_traits_wtf.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ - -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/string_traits.h" -#include "third_party/WebKit/Source/wtf/text/WTFString.h" - -namespace mojo { - -template <> -struct StringTraits<WTF::String> { - static bool IsNull(const WTF::String& input) { return input.isNull(); } - static void SetToNull(WTF::String* output); - - static void* SetUpContext(const WTF::String& input); - static void TearDownContext(const WTF::String& input, void* context); - - static size_t GetSize(const WTF::String& input, void* context); - - static const char* GetData(const WTF::String& input, void* context); - - static bool Read(StringDataView input, WTF::String* output); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_WTF_H_ diff --git a/mojo/public/cpp/bindings/strong_associated_binding.h b/mojo/public/cpp/bindings/strong_associated_binding.h deleted file mode 100644 index a1e299b..0000000 --- a/mojo/public/cpp/bindings/strong_associated_binding.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_ - -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -template <typename Interface> -class StrongAssociatedBinding; - -template <typename Interface> -using StrongAssociatedBindingPtr = - base::WeakPtr<StrongAssociatedBinding<Interface>>; - -// This connects an interface implementation strongly to an associated pipe. -// When a connection error is detected the implementation is deleted. If the -// task runner that a StrongAssociatedBinding is bound on is stopped, the -// connection error handler will not be invoked and the implementation will not -// be deleted. -// -// To use, call StrongAssociatedBinding<T>::Create() (see below) or the helper -// MakeStrongAssociatedBinding function: -// -// mojo::MakeStrongAssociatedBinding(base::MakeUnique<FooImpl>(), -// std::move(foo_request)); -// -template <typename Interface> -class StrongAssociatedBinding { - public: - // Create a new StrongAssociatedBinding instance. The instance owns itself, - // cleaning up only in the event of a pipe connection error. Returns a WeakPtr - // to the new StrongAssociatedBinding instance. - static StrongAssociatedBindingPtr<Interface> Create( - std::unique_ptr<Interface> impl, - AssociatedInterfaceRequest<Interface> request) { - StrongAssociatedBinding* binding = - new StrongAssociatedBinding(std::move(impl), std::move(request)); - return binding->weak_factory_.GetWeakPtr(); - } - - // Note: The error handler must not delete the interface implementation. - // - // This method may only be called after this StrongAssociatedBinding has been - // bound to a message pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(binding_.is_bound()); - connection_error_handler_ = error_handler; - connection_error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(binding_.is_bound()); - connection_error_with_reason_handler_ = error_handler; - connection_error_handler_.Reset(); - } - - // Forces the binding to close. This destroys the StrongBinding instance. - void Close() { delete this; } - - Interface* impl() { return impl_.get(); } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { binding_.FlushForTesting(); } - - private: - StrongAssociatedBinding(std::unique_ptr<Interface> impl, - AssociatedInterfaceRequest<Interface> request) - : impl_(std::move(impl)), - binding_(impl_.get(), std::move(request)), - weak_factory_(this) { - binding_.set_connection_error_with_reason_handler(base::Bind( - &StrongAssociatedBinding::OnConnectionError, base::Unretained(this))); - } - - ~StrongAssociatedBinding() {} - - void OnConnectionError(uint32_t custom_reason, - const std::string& description) { - if (!connection_error_handler_.is_null()) - connection_error_handler_.Run(); - else if (!connection_error_with_reason_handler_.is_null()) - connection_error_with_reason_handler_.Run(custom_reason, description); - Close(); - } - - std::unique_ptr<Interface> impl_; - base::Closure connection_error_handler_; - ConnectionErrorWithReasonCallback connection_error_with_reason_handler_; - AssociatedBinding<Interface> binding_; - base::WeakPtrFactory<StrongAssociatedBinding> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(StrongAssociatedBinding); -}; - -template <typename Interface, typename Impl> -StrongAssociatedBindingPtr<Interface> MakeStrongAssociatedBinding( - std::unique_ptr<Impl> impl, - AssociatedInterfaceRequest<Interface> request) { - return StrongAssociatedBinding<Interface>::Create(std::move(impl), - std::move(request)); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_ diff --git a/mojo/public/cpp/bindings/strong_binding.h b/mojo/public/cpp/bindings/strong_binding.h deleted file mode 100644 index f4b4a06..0000000 --- a/mojo/public/cpp/bindings/strong_binding.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_ - -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -template <typename Interface> -class StrongBinding; - -template <typename Interface> -using StrongBindingPtr = base::WeakPtr<StrongBinding<Interface>>; - -// This connects an interface implementation strongly to a pipe. When a -// connection error is detected the implementation is deleted. If the task -// runner that a StrongBinding is bound on is stopped, the connection error -// handler will not be invoked and the implementation will not be deleted. -// -// To use, call StrongBinding<T>::Create() (see below) or the helper -// MakeStrongBinding function: -// -// mojo::MakeStrongBinding(base::MakeUnique<FooImpl>(), -// std::move(foo_request)); -// -template <typename Interface> -class StrongBinding { - public: - // Create a new StrongBinding instance. The instance owns itself, cleaning up - // only in the event of a pipe connection error. Returns a WeakPtr to the new - // StrongBinding instance. - static StrongBindingPtr<Interface> Create( - std::unique_ptr<Interface> impl, - InterfaceRequest<Interface> request) { - StrongBinding* binding = - new StrongBinding(std::move(impl), std::move(request)); - return binding->weak_factory_.GetWeakPtr(); - } - - // Note: The error handler must not delete the interface implementation. - // - // This method may only be called after this StrongBinding has been bound to a - // message pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(binding_.is_bound()); - connection_error_handler_ = error_handler; - connection_error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(binding_.is_bound()); - connection_error_with_reason_handler_ = error_handler; - connection_error_handler_.Reset(); - } - - // Forces the binding to close. This destroys the StrongBinding instance. - void Close() { delete this; } - - Interface* impl() { return impl_.get(); } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { binding_.FlushForTesting(); } - - private: - StrongBinding(std::unique_ptr<Interface> impl, - InterfaceRequest<Interface> request) - : impl_(std::move(impl)), - binding_(impl_.get(), std::move(request)), - weak_factory_(this) { - binding_.set_connection_error_with_reason_handler( - base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this))); - } - - ~StrongBinding() {} - - void OnConnectionError(uint32_t custom_reason, - const std::string& description) { - if (!connection_error_handler_.is_null()) - connection_error_handler_.Run(); - else if (!connection_error_with_reason_handler_.is_null()) - connection_error_with_reason_handler_.Run(custom_reason, description); - Close(); - } - - std::unique_ptr<Interface> impl_; - base::Closure connection_error_handler_; - ConnectionErrorWithReasonCallback connection_error_with_reason_handler_; - Binding<Interface> binding_; - base::WeakPtrFactory<StrongBinding> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(StrongBinding); -}; - -template <typename Interface, typename Impl> -StrongBindingPtr<Interface> MakeStrongBinding( - std::unique_ptr<Impl> impl, - InterfaceRequest<Interface> request) { - return StrongBinding<Interface>::Create(std::move(impl), std::move(request)); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_ diff --git a/mojo/public/cpp/bindings/strong_binding_set.h b/mojo/public/cpp/bindings/strong_binding_set.h deleted file mode 100644 index f6bcd52..0000000 --- a/mojo/public/cpp/bindings/strong_binding_set.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_SET_H_ - -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h" - -namespace mojo { - -// This class manages a set of bindings. When the pipe a binding is bound to is -// disconnected, the binding is automatically destroyed and removed from the -// set, and the interface implementation is deleted. When the StrongBindingSet -// is destructed, all outstanding bindings in the set are destroyed and all the -// bound interface implementations are automatically deleted. -template <typename Interface, typename ContextType = void> -using StrongBindingSet = - BindingSetBase<Interface, - Binding<Interface, UniquePtrImplRefTraits<Interface>>, - ContextType>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_SET_H_ diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h deleted file mode 100644 index b135312..0000000 --- a/mojo/public/cpp/bindings/struct_ptr.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ - -#include <functional> -#include <memory> -#include <new> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/hash_util.h" -#include "mojo/public/cpp/bindings/type_converter.h" - -namespace mojo { -namespace internal { - -constexpr size_t kHashSeed = 31; - -template <typename Struct> -class StructPtrWTFHelper; - -template <typename Struct> -class InlinedStructPtrWTFHelper; - -} // namespace internal - -// Smart pointer wrapping a mojom structure with move-only semantics. -template <typename S> -class StructPtr { - public: - using Struct = S; - - StructPtr() = default; - StructPtr(decltype(nullptr)) {} - - ~StructPtr() = default; - - StructPtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - StructPtr(StructPtr&& other) { Take(&other); } - StructPtr& operator=(StructPtr&& other) { - Take(&other); - return *this; - } - - template <typename... Args> - StructPtr(base::in_place_t, Args&&... args) - : ptr_(new Struct(std::forward<Args>(args)...)) {} - - template <typename U> - U To() const { - return TypeConverter<U, StructPtr>::Convert(*this); - } - - void reset() { ptr_.reset(); } - - bool is_null() const { return !ptr_; } - - Struct& operator*() const { - DCHECK(ptr_); - return *ptr_; - } - Struct* operator->() const { - DCHECK(ptr_); - return ptr_.get(); - } - Struct* get() const { return ptr_.get(); } - - void Swap(StructPtr* other) { std::swap(ptr_, other->ptr_); } - - // Please note that calling this method will fail compilation if the value - // type |Struct| doesn't have a Clone() method defined (which usually means - // that it contains Mojo handles). - StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); } - - // Compares the pointees (which might both be null). - // TODO(tibell): Get rid of Equals in favor of the operator. Same for Hash. - bool Equals(const StructPtr& other) const { - if (is_null() || other.is_null()) - return is_null() && other.is_null(); - return ptr_->Equals(*other.ptr_); - } - - // Hashes based on the pointee (which might be null). - size_t Hash(size_t seed) const { - if (is_null()) - return internal::HashCombine(seed, 0); - return ptr_->Hash(seed); - } - - explicit operator bool() const { return !is_null(); } - - private: - friend class internal::StructPtrWTFHelper<Struct>; - void Take(StructPtr* other) { - reset(); - Swap(other); - } - - std::unique_ptr<Struct> ptr_; - - DISALLOW_COPY_AND_ASSIGN(StructPtr); -}; - -template <typename T> -bool operator==(const StructPtr<T>& lhs, const StructPtr<T>& rhs) { - return lhs.Equals(rhs); -} -template <typename T> -bool operator!=(const StructPtr<T>& lhs, const StructPtr<T>& rhs) { - return !(lhs == rhs); -} - -// Designed to be used when Struct is small and copyable. -template <typename S> -class InlinedStructPtr { - public: - using Struct = S; - - InlinedStructPtr() : state_(NIL) {} - InlinedStructPtr(decltype(nullptr)) : state_(NIL) {} - - ~InlinedStructPtr() {} - - InlinedStructPtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - InlinedStructPtr(InlinedStructPtr&& other) : state_(NIL) { Take(&other); } - InlinedStructPtr& operator=(InlinedStructPtr&& other) { - Take(&other); - return *this; - } - - template <typename... Args> - InlinedStructPtr(base::in_place_t, Args&&... args) - : value_(std::forward<Args>(args)...), state_(VALID) {} - - template <typename U> - U To() const { - return TypeConverter<U, InlinedStructPtr>::Convert(*this); - } - - void reset() { - state_ = NIL; - value_. ~Struct(); - new (&value_) Struct(); - } - - bool is_null() const { return state_ == NIL; } - - Struct& operator*() const { - DCHECK(state_ == VALID); - return value_; - } - Struct* operator->() const { - DCHECK(state_ == VALID); - return &value_; - } - Struct* get() const { return &value_; } - - void Swap(InlinedStructPtr* other) { - std::swap(value_, other->value_); - std::swap(state_, other->state_); - } - - InlinedStructPtr Clone() const { - return is_null() ? InlinedStructPtr() : value_.Clone(); - } - - // Compares the pointees (which might both be null). - bool Equals(const InlinedStructPtr& other) const { - if (is_null() || other.is_null()) - return is_null() && other.is_null(); - return value_.Equals(other.value_); - } - - // Hashes based on the pointee (which might be null). - size_t Hash(size_t seed) const { - if (is_null()) - return internal::HashCombine(seed, 0); - return value_.Hash(seed); - } - - explicit operator bool() const { return !is_null(); } - - private: - friend class internal::InlinedStructPtrWTFHelper<Struct>; - void Take(InlinedStructPtr* other) { - reset(); - Swap(other); - } - - enum State { - VALID, - NIL, - DELETED, // For use in WTF::HashMap only - }; - - mutable Struct value_; - State state_; - - DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr); -}; - -template <typename T> -bool operator==(const InlinedStructPtr<T>& lhs, - const InlinedStructPtr<T>& rhs) { - return lhs.Equals(rhs); -} -template <typename T> -bool operator!=(const InlinedStructPtr<T>& lhs, - const InlinedStructPtr<T>& rhs) { - return !(lhs == rhs); -} - -namespace internal { - -template <typename Struct> -class StructPtrWTFHelper { - public: - static bool IsHashTableDeletedValue(const StructPtr<Struct>& value) { - return value.ptr_.get() == reinterpret_cast<Struct*>(1u); - } - - static void ConstructDeletedValue(mojo::StructPtr<Struct>& slot) { - // |slot| refers to a previous, real value that got deleted and had its - // destructor run, so this is the first time the "deleted value" has its - // constructor called. - // - // Dirty trick: implant an invalid pointer in |ptr_|. Destructor isn't - // called for deleted buckets, so this is okay. - new (&slot) StructPtr<Struct>(); - slot.ptr_.reset(reinterpret_cast<Struct*>(1u)); - } -}; - -template <typename Struct> -class InlinedStructPtrWTFHelper { - public: - static bool IsHashTableDeletedValue(const InlinedStructPtr<Struct>& value) { - return value.state_ == InlinedStructPtr<Struct>::DELETED; - } - - static void ConstructDeletedValue(mojo::InlinedStructPtr<Struct>& slot) { - // |slot| refers to a previous, real value that got deleted and had its - // destructor run, so this is the first time the "deleted value" has its - // constructor called. - new (&slot) InlinedStructPtr<Struct>(); - slot.state_ = InlinedStructPtr<Struct>::DELETED; - } -}; - -} // namespace internal -} // namespace mojo - -namespace std { - -template <typename T> -struct hash<mojo::StructPtr<T>> { - size_t operator()(const mojo::StructPtr<T>& value) const { - return value.Hash(mojo::internal::kHashSeed); - } -}; - -template <typename T> -struct hash<mojo::InlinedStructPtr<T>> { - size_t operator()(const mojo::InlinedStructPtr<T>& value) const { - return value.Hash(mojo::internal::kHashSeed); - } -}; - -} // namespace std - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ diff --git a/mojo/public/cpp/bindings/struct_traits.h b/mojo/public/cpp/bindings/struct_traits.h deleted file mode 100644 index 6cc070f..0000000 --- a/mojo/public/cpp/bindings/struct_traits.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom struct. |DataViewType| is the corresponding data view type of the -// mojom struct. For example, if the mojom struct is example.Foo, -// |DataViewType| will be example::FooDataView, which can also be referred to by -// example::Foo::DataView (in chromium) and example::blink::Foo::DataView (in -// blink). -// -// Each specialization needs to implement a few things: -// 1. Static getters for each field in the Mojom type. These should be -// of the form: -// -// static <return type> <field name>(const T& input); -// -// and should return a serializable form of the named field as extracted -// from |input|. -// -// Serializable form of a field: -// Value or reference of the same type used in the generated stuct -// wrapper type, or the following alternatives: -// - string: -// Value or reference of any type that has a StringTraits defined. -// Supported by default: base::StringPiece, std::string, -// WTF::String (in blink). -// -// - array: -// Value or reference of any type that has an ArrayTraits defined. -// Supported by default: std::vector, CArray, WTF::Vector (in blink) -// -// - map: -// Value or reference of any type that has a MapTraits defined. -// Supported by default: std::map, std::unordered_map, -// WTF::HashMap (in blink). -// -// - struct: -// Value or reference of any type that has a StructTraits defined. -// -// - enum: -// Value of any type that has an EnumTraits defined. -// -// For any nullable string/struct/array/map/union field you could also -// return value or reference of base::Optional<T>/WTF::Optional<T>, if T -// has the right *Traits defined. -// -// During serialization, getters for string/struct/array/map/union fields -// are called twice (one for size calculation and one for actual -// serialization). If you want to return a value (as opposed to a -// reference) from these getters, you have to be sure that constructing and -// copying the returned object is really cheap. -// -// Getters for fields of other types are called once. -// -// 2. A static Read() method to set the contents of a |T| instance from a -// DataViewType. -// -// static bool Read(DataViewType data, T* output); -// -// The generated DataViewType provides a convenient, inexpensive view of a -// serialized struct's field data. The caller guarantees that -// |!data.is_null()|. -// -// Returning false indicates invalid incoming data and causes the message -// pipe receiving it to be disconnected. Therefore, you can do custom -// validation for |T| in this method. -// -// 3. [Optional] A static IsNull() method indicating whether a given |T| -// instance is null: -// -// static bool IsNull(const T& input); -// -// If this method returns true, it is guaranteed that none of the getters -// (described in section 1) will be called for the same |input|. So you -// don't have to check whether |input| is null in those getters. -// -// If it is not defined, |T| instances are always considered non-null. -// -// [Optional] A static SetToNull() method to set the contents of a given -// |T| instance to null. -// -// static void SetToNull(T* output); -// -// When a null serialized struct is received, the deserialization code -// calls this method instead of Read(). -// -// NOTE: It is to set |*output|'s contents to a null state, not to set the -// |output| pointer itself to null. "Null state" means whatever state you -// think it makes sense to map a null serialized struct to. -// -// If it is not defined, null is not allowed to be converted to |T|. In -// that case, an incoming null value is considered invalid and causes the -// message pipe to be disconnected. -// -// 4. [Optional] As mentioned above, getters for string/struct/array/map/union -// fields are called multiple times (twice to be exact). If you need to do -// some expensive calculation/conversion, you probably want to cache the -// result across multiple calls. You can introduce an arbitrary context -// object by adding two optional methods: -// static void* SetUpContext(const T& input); -// static void TearDownContext(const T& input, void* context); -// -// And then you append a second parameter, void* context, to getters: -// static <return type> <field name>(const T& input, void* context); -// -// If a T instance is not null, the serialization code will call -// SetUpContext() at the beginning, and pass the resulting context pointer -// to getters. After serialization is done, it calls TearDownContext() so -// that you can do any necessary cleanup. -// -// In the description above, methods having an |input| parameter define it as -// const reference of T. Actually, it can be a non-const reference of T too. -// E.g., if T contains Mojo handles or interfaces whose ownership needs to be -// transferred. Correspondingly, it requies you to always give non-const T -// reference/value to the Mojo bindings for serialization: -// - if T is used in the "type_mappings" section of a typemap config file, -// you need to declare it as pass-by-value: -// type_mappings = [ "MojomType=T[move_only]" ] -// or -// type_mappings = [ "MojomType=T[copyable_pass_by_value]" ] -// -// - if another type U's StructTraits/UnionTraits has a getter for T, it -// needs to return non-const reference/value. -// -// EXAMPLE: -// -// Mojom definition: -// struct Bar {}; -// struct Foo { -// int32 f_integer; -// string f_string; -// array<string> f_string_array; -// Bar f_bar; -// }; -// -// StructTraits for Foo: -// template <> -// struct StructTraits<FooDataView, CustomFoo> { -// // Optional methods dealing with null: -// static bool IsNull(const CustomFoo& input); -// static void SetToNull(CustomFoo* output); -// -// // Field getters: -// static int32_t f_integer(const CustomFoo& input); -// static const std::string& f_string(const CustomFoo& input); -// static const std::vector<std::string>& f_string_array( -// const CustomFoo& input); -// // Assuming there is a StructTraits<Bar, CustomBar> defined. -// static const CustomBar& f_bar(const CustomFoo& input); -// -// static bool Read(FooDataView data, CustomFoo* output); -// }; -// -template <typename DataViewType, typename T> -struct StructTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h deleted file mode 100644 index 5529042..0000000 --- a/mojo/public/cpp/bindings/sync_call_restrictions.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ - -#include "base/macros.h" -#include "base/threading/thread_restrictions.h" -#include "mojo/public/cpp/bindings/bindings_export.h" - -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_SYNC_CALL_RESTRICTIONS 1 -#else -#define ENABLE_SYNC_CALL_RESTRICTIONS 0 -#endif - -namespace leveldb { -class LevelDBMojoProxy; -} - -namespace prefs { -class PersistentPrefStoreClient; -} - -namespace ui { -class Gpu; -} - -namespace views { -class ClipboardMus; -} - -namespace mojo { - -// In some processes, sync calls are disallowed. For example, in the browser -// process we don't want any sync calls to child processes for performance, -// security and stability reasons. SyncCallRestrictions helps to enforce such -// rules. -// -// Before processing a sync call, the bindings call -// SyncCallRestrictions::AssertSyncCallAllowed() to check whether sync calls are -// allowed. By default, it is determined by the mojo system property -// MOJO_PROPERTY_SYNC_CALL_ALLOWED. If the default setting says no but you have -// a very compelling reason to disregard that (which should be very very rare), -// you can override it by constructing a ScopedAllowSyncCall object, which -// allows making sync calls on the current thread during its lifetime. -class MOJO_CPP_BINDINGS_EXPORT SyncCallRestrictions { - public: -#if ENABLE_SYNC_CALL_RESTRICTIONS - // Checks whether the current thread is allowed to make sync calls, and causes - // a DCHECK if not. - static void AssertSyncCallAllowed(); -#else - // Inline the empty definitions of functions so that they can be compiled out. - static void AssertSyncCallAllowed() {} -#endif - - private: - // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first. - // BEGIN ALLOWED USAGE. - friend class ui::Gpu; // http://crbug.com/620058 - // LevelDBMojoProxy makes same-process sync calls from the DB thread. - friend class leveldb::LevelDBMojoProxy; - // Pref service connection is sync at startup. - friend class prefs::PersistentPrefStoreClient; - - // END ALLOWED USAGE. - - // BEGIN USAGE THAT NEEDS TO BE FIXED. - // In the non-mus case, we called blocking OS functions in the ui::Clipboard - // implementation which weren't caught by sync call restrictions. Our blocking - // calls to mus, however, are. - friend class views::ClipboardMus; - // END USAGE THAT NEEDS TO BE FIXED. - -#if ENABLE_SYNC_CALL_RESTRICTIONS - static void IncreaseScopedAllowCount(); - static void DecreaseScopedAllowCount(); -#else - static void IncreaseScopedAllowCount() {} - static void DecreaseScopedAllowCount() {} -#endif - - // If a process is configured to disallow sync calls in general, constructing - // a ScopedAllowSyncCall object temporarily allows making sync calls on the - // current thread. Doing this is almost always incorrect, which is why we - // limit who can use this through friend. If you find yourself needing to use - // this, talk to mojo/OWNERS. - class ScopedAllowSyncCall { - public: - ScopedAllowSyncCall() { IncreaseScopedAllowCount(); } - ~ScopedAllowSyncCall() { DecreaseScopedAllowCount(); } - - private: -#if ENABLE_SYNC_CALL_RESTRICTIONS - base::ThreadRestrictions::ScopedAllowWait allow_wait_; -#endif - - DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCall); - }; - - DISALLOW_IMPLICIT_CONSTRUCTORS(SyncCallRestrictions); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ diff --git a/mojo/public/cpp/bindings/sync_event_watcher.h b/mojo/public/cpp/bindings/sync_event_watcher.h deleted file mode 100644 index 6e25484..0000000 --- a/mojo/public/cpp/bindings/sync_event_watcher.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_EVENT_WATCHER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_EVENT_WATCHER_H_ - -#include <stddef.h> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/sync_handle_registry.h" - -namespace mojo { - -// SyncEventWatcher supports waiting on a base::WaitableEvent to signal while -// also allowing other SyncEventWatchers and SyncHandleWatchers on the same -// thread to wake up as needed. -// -// This class is not thread safe. -class MOJO_CPP_BINDINGS_EXPORT SyncEventWatcher { - public: - SyncEventWatcher(base::WaitableEvent* event, const base::Closure& callback); - - ~SyncEventWatcher(); - - // Registers |event_| with SyncHandleRegistry, so that when others perform - // sync watching on the same thread, |event_| will be watched along with them. - void AllowWokenUpBySyncWatchOnSameThread(); - - // Waits on |event_| plus all other events and handles registered with this - // thread's SyncHandleRegistry, running callbacks synchronously for any ready - // events and handles. - // This method: - // - returns true when |should_stop| is set to true; - // - return false when any error occurs, including this object being - // destroyed during a callback. - bool SyncWatch(const bool* should_stop); - - private: - void IncrementRegisterCount(); - void DecrementRegisterCount(); - - base::WaitableEvent* const event_; - const base::Closure callback_; - - // Whether |event_| has been registered with SyncHandleRegistry. - bool registered_ = false; - - // If non-zero, |event_| should be registered with SyncHandleRegistry. - size_t register_request_count_ = 0; - - scoped_refptr<SyncHandleRegistry> registry_; - - scoped_refptr<base::RefCountedData<bool>> destroyed_; - - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(SyncEventWatcher); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_EVENT_WATCHER_H_ diff --git a/mojo/public/cpp/bindings/sync_handle_registry.h b/mojo/public/cpp/bindings/sync_handle_registry.h deleted file mode 100644 index afb3b56..0000000 --- a/mojo/public/cpp/bindings/sync_handle_registry.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_ - -#include <map> -#include <unordered_map> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/wait_set.h" - -namespace mojo { - -// SyncHandleRegistry is a thread-local storage to register handles that want to -// be watched together. -// -// This class is not thread safe. -class MOJO_CPP_BINDINGS_EXPORT SyncHandleRegistry - : public base::RefCounted<SyncHandleRegistry> { - public: - // Returns a thread-local object. - static scoped_refptr<SyncHandleRegistry> current(); - - using HandleCallback = base::Callback<void(MojoResult)>; - bool RegisterHandle(const Handle& handle, - MojoHandleSignals handle_signals, - const HandleCallback& callback); - - void UnregisterHandle(const Handle& handle); - - // Registers a |base::WaitableEvent| which can be used to wake up - // Wait() before any handle signals. |event| is not owned, and if it signals - // during Wait(), |callback| is invoked. Returns |true| if registered - // successfully or |false| if |event| was already registered. - bool RegisterEvent(base::WaitableEvent* event, const base::Closure& callback); - - void UnregisterEvent(base::WaitableEvent* event); - - // Waits on all the registered handles and events and runs callbacks - // synchronously for any that become ready. - // The method: - // - returns true when any element of |should_stop| is set to true; - // - returns false when any error occurs. - bool Wait(const bool* should_stop[], size_t count); - - private: - friend class base::RefCounted<SyncHandleRegistry>; - - SyncHandleRegistry(); - ~SyncHandleRegistry(); - - WaitSet wait_set_; - std::map<Handle, HandleCallback> handles_; - std::map<base::WaitableEvent*, base::Closure> events_; - - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(SyncHandleRegistry); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_REGISTRY_H_ diff --git a/mojo/public/cpp/bindings/sync_handle_watcher.h b/mojo/public/cpp/bindings/sync_handle_watcher.h deleted file mode 100644 index eff73dd..0000000 --- a/mojo/public/cpp/bindings/sync_handle_watcher.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_WATCHER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_WATCHER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/sync_handle_registry.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -// SyncHandleWatcher supports watching a handle synchronously. It also supports -// registering the handle with a thread-local storage (SyncHandleRegistry), so -// that when other SyncHandleWatcher instances on the same thread perform sync -// handle watching, this handle will be watched together. -// -// SyncHandleWatcher is used for sync methods. While a sync call is waiting for -// response, we would like to block the thread. On the other hand, we need -// incoming sync method requests on the same thread to be able to reenter. We -// also need master interface endpoints to continue dispatching messages for -// associated endpoints on different threads. -// -// This class is not thread safe. -class MOJO_CPP_BINDINGS_EXPORT SyncHandleWatcher { - public: - // Note: |handle| must outlive this object. - SyncHandleWatcher(const Handle& handle, - MojoHandleSignals handle_signals, - const SyncHandleRegistry::HandleCallback& callback); - - ~SyncHandleWatcher(); - - // Registers |handle_| with SyncHandleRegistry, so that when others perform - // sync handle watching on the same thread, |handle_| will be watched - // together. - void AllowWokenUpBySyncWatchOnSameThread(); - - // Waits on |handle_| plus all handles registered with SyncHandleRegistry and - // runs callbacks synchronously for those ready handles. - // This method: - // - returns true when |should_stop| is set to true; - // - return false when any error occurs, including this object being - // destroyed during a callback. - bool SyncWatch(const bool* should_stop); - - private: - void IncrementRegisterCount(); - void DecrementRegisterCount(); - - const Handle handle_; - const MojoHandleSignals handle_signals_; - SyncHandleRegistry::HandleCallback callback_; - - // Whether |handle_| has been registered with SyncHandleRegistry. - bool registered_; - // If non-zero, |handle_| should be registered with SyncHandleRegistry. - size_t register_request_count_; - - scoped_refptr<SyncHandleRegistry> registry_; - - scoped_refptr<base::RefCountedData<bool>> destroyed_; - - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(SyncHandleWatcher); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_HANDLE_WATCHER_H_ diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn deleted file mode 100644 index 668ca6d..0000000 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("tests") { - testonly = true - - sources = [ - "associated_interface_unittest.cc", - "bind_task_runner_unittest.cc", - "binding_callback_unittest.cc", - "binding_set_unittest.cc", - "binding_unittest.cc", - "buffer_unittest.cc", - "connector_unittest.cc", - "constant_unittest.cc", - "container_test_util.cc", - "container_test_util.h", - "data_view_unittest.cc", - "equals_unittest.cc", - "handle_passing_unittest.cc", - "hash_unittest.cc", - "interface_ptr_unittest.cc", - "map_unittest.cc", - "message_queue.cc", - "message_queue.h", - "multiplex_router_unittest.cc", - "report_bad_message_unittest.cc", - "request_response_unittest.cc", - "router_test_util.cc", - "router_test_util.h", - "sample_service_unittest.cc", - "serialization_warning_unittest.cc", - "struct_unittest.cc", - "sync_method_unittest.cc", - "type_conversion_unittest.cc", - "union_unittest.cc", - "validation_context_unittest.cc", - "validation_unittest.cc", - "variant_test_util.h", - ] - - deps = [ - ":mojo_public_bindings_test_utils", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/cpp/test_support:test_utils", - "//mojo/public/interfaces/bindings/tests:test_associated_interfaces", - "//mojo/public/interfaces/bindings/tests:test_export_component", - "//mojo/public/interfaces/bindings/tests:test_export_component2", - "//mojo/public/interfaces/bindings/tests:test_exported_import", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/interfaces/bindings/tests:test_struct_traits_interfaces", - "//testing/gtest", - ] - - data = [ - "//mojo/public/interfaces/bindings/tests/data/validation/", - ] - - if (is_ios) { - assert_no_deps = [ "//third_party/WebKit/*" ] - } else { - sources += [ - "pickle_unittest.cc", - "struct_traits_unittest.cc", - ] - - deps += [ "//mojo/public/interfaces/bindings/tests:test_interfaces_blink" ] - } -} - -if (!is_ios) { - source_set("for_blink_tests") { - testonly = true - - sources = [ - "container_test_util.cc", - "container_test_util.h", - "variant_test_util.h", - "wtf_hash_unittest.cc", - "wtf_map_unittest.cc", - "wtf_types_unittest.cc", - ] - - deps = [ - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/bindings/tests:test_export_blink_component", - "//mojo/public/interfaces/bindings/tests:test_exported_import_blink", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/interfaces/bindings/tests:test_interfaces_blink", - "//mojo/public/interfaces/bindings/tests:test_wtf_types", - "//mojo/public/interfaces/bindings/tests:test_wtf_types_blink", - "//testing/gtest", - ] - } -} - -source_set("struct_with_traits_impl") { - sources = [ - "struct_with_traits_impl.cc", - "struct_with_traits_impl.h", - ] - - deps = [ - "//base", - "//mojo/public/cpp/system:system", - ] -} - -source_set("perftests") { - testonly = true - - sources = [ - "bindings_perftest.cc", - ] - - if (!is_ios) { - sources += [ "e2e_perftest.cc" ] - } - - deps = [ - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/cpp/test_support:test_utils", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//testing/gtest", - ] -} - -source_set("mojo_public_bindings_test_utils") { - sources = [ - "validation_test_input_parser.cc", - "validation_test_input_parser.h", - ] - - deps = [ - "//mojo/public/c/system", - ] -} diff --git a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc deleted file mode 100644 index be225e4..0000000 --- a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc +++ /dev/null @@ -1,1189 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <algorithm> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" -#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -using mojo::internal::MultiplexRouter; - -class IntegerSenderImpl : public IntegerSender { - public: - explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request) - : binding_(this, std::move(request)) {} - - ~IntegerSenderImpl() override {} - - void set_notify_send_method_called( - const base::Callback<void(int32_t)>& callback) { - notify_send_method_called_ = callback; - } - - void Echo(int32_t value, const EchoCallback& callback) override { - callback.Run(value); - } - void Send(int32_t value) override { notify_send_method_called_.Run(value); } - - AssociatedBinding<IntegerSender>* binding() { return &binding_; } - - void set_connection_error_handler(const base::Closure& handler) { - binding_.set_connection_error_handler(handler); - } - - private: - AssociatedBinding<IntegerSender> binding_; - base::Callback<void(int32_t)> notify_send_method_called_; -}; - -class IntegerSenderConnectionImpl : public IntegerSenderConnection { - public: - explicit IntegerSenderConnectionImpl( - InterfaceRequest<IntegerSenderConnection> request) - : binding_(this, std::move(request)) {} - - ~IntegerSenderConnectionImpl() override {} - - void GetSender(AssociatedInterfaceRequest<IntegerSender> sender) override { - IntegerSenderImpl* sender_impl = new IntegerSenderImpl(std::move(sender)); - sender_impl->set_connection_error_handler( - base::Bind(&DeleteSender, sender_impl)); - } - - void AsyncGetSender(const AsyncGetSenderCallback& callback) override { - IntegerSenderAssociatedPtrInfo ptr_info; - auto request = MakeRequest(&ptr_info); - GetSender(std::move(request)); - callback.Run(std::move(ptr_info)); - } - - Binding<IntegerSenderConnection>* binding() { return &binding_; } - - private: - static void DeleteSender(IntegerSenderImpl* sender) { delete sender; } - - Binding<IntegerSenderConnection> binding_; -}; - -class AssociatedInterfaceTest : public testing::Test { - public: - AssociatedInterfaceTest() {} - ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); } - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - template <typename T> - AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo( - AssociatedInterfacePtrInfo<T> ptr_info, - scoped_refptr<MultiplexRouter> source, - scoped_refptr<MultiplexRouter> target) { - ScopedInterfaceEndpointHandle handle = ptr_info.PassHandle(); - CHECK(handle.pending_association()); - auto id = source->AssociateInterface(std::move(handle)); - return AssociatedInterfacePtrInfo<T>(target->CreateLocalEndpointHandle(id), - ptr_info.version()); - } - - void CreateRouterPair(scoped_refptr<MultiplexRouter>* router0, - scoped_refptr<MultiplexRouter>* router1) { - MessagePipe pipe; - *router0 = new MultiplexRouter(std::move(pipe.handle0), - MultiplexRouter::MULTI_INTERFACE, true, - base::ThreadTaskRunnerHandle::Get()); - *router1 = new MultiplexRouter(std::move(pipe.handle1), - MultiplexRouter::MULTI_INTERFACE, false, - base::ThreadTaskRunnerHandle::Get()); - } - - void CreateIntegerSenderWithExistingRouters( - scoped_refptr<MultiplexRouter> router0, - IntegerSenderAssociatedPtrInfo* ptr_info0, - scoped_refptr<MultiplexRouter> router1, - IntegerSenderAssociatedRequest* request1) { - *request1 = MakeRequest(ptr_info0); - *ptr_info0 = EmulatePassingAssociatedPtrInfo(std::move(*ptr_info0), router1, - router0); - } - - void CreateIntegerSender(IntegerSenderAssociatedPtrInfo* ptr_info, - IntegerSenderAssociatedRequest* request) { - scoped_refptr<MultiplexRouter> router0; - scoped_refptr<MultiplexRouter> router1; - CreateRouterPair(&router0, &router1); - CreateIntegerSenderWithExistingRouters(router1, ptr_info, router0, request); - } - - // Okay to call from any thread. - void QuitRunLoop(base::RunLoop* run_loop) { - if (loop_.task_runner()->BelongsToCurrentThread()) { - run_loop->Quit(); - } else { - loop_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(run_loop))); - } - } - - private: - base::MessageLoop loop_; -}; - -void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) { - *flag = true; - closure.Run(); -} - -void DoExpectValueSetFlagAndRunClosure(int32_t expected_value, - bool* flag, - const base::Closure& closure, - int32_t value) { - EXPECT_EQ(expected_value, value); - DoSetFlagAndRunClosure(flag, closure); -} - -base::Closure SetFlagAndRunClosure(bool* flag, const base::Closure& closure) { - return base::Bind(&DoSetFlagAndRunClosure, flag, closure); -} - -base::Callback<void(int32_t)> ExpectValueSetFlagAndRunClosure( - int32_t expected_value, - bool* flag, - const base::Closure& closure) { - return base::Bind( - &DoExpectValueSetFlagAndRunClosure, expected_value, flag, closure); -} - -void Fail() { - FAIL() << "Unexpected connection error"; -} - -TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) { - // Bind to the same pipe two associated interfaces, whose implementation lives - // at different ends. Test that the two don't interfere with each other. - - scoped_refptr<MultiplexRouter> router0; - scoped_refptr<MultiplexRouter> router1; - CreateRouterPair(&router0, &router1); - - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0, &request); - - IntegerSenderImpl impl0(std::move(request)); - AssociatedInterfacePtr<IntegerSender> ptr0; - ptr0.Bind(std::move(ptr_info)); - - CreateIntegerSenderWithExistingRouters(router0, &ptr_info, router1, &request); - - IntegerSenderImpl impl1(std::move(request)); - AssociatedInterfacePtr<IntegerSender> ptr1; - ptr1.Bind(std::move(ptr_info)); - - base::RunLoop run_loop, run_loop2; - bool ptr0_callback_run = false; - ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run, - run_loop.QuitClosure())); - - bool ptr1_callback_run = false; - ptr1->Echo(456, ExpectValueSetFlagAndRunClosure(456, &ptr1_callback_run, - run_loop2.QuitClosure())); - - run_loop.Run(); - run_loop2.Run(); - EXPECT_TRUE(ptr0_callback_run); - EXPECT_TRUE(ptr1_callback_run); - - bool ptr0_error_callback_run = false; - base::RunLoop run_loop3; - ptr0.set_connection_error_handler( - SetFlagAndRunClosure(&ptr0_error_callback_run, run_loop3.QuitClosure())); - - impl0.binding()->Close(); - run_loop3.Run(); - EXPECT_TRUE(ptr0_error_callback_run); - - bool impl1_error_callback_run = false; - base::RunLoop run_loop4; - impl1.binding()->set_connection_error_handler( - SetFlagAndRunClosure(&impl1_error_callback_run, run_loop4.QuitClosure())); - - ptr1.reset(); - run_loop4.Run(); - EXPECT_TRUE(impl1_error_callback_run); -} - -class TestSender { - public: - TestSender() - : sender_thread_("TestSender"), - next_sender_(nullptr), - max_value_to_send_(-1) { - sender_thread_.Start(); - } - - // The following three methods are called on the corresponding sender thread. - void SetUp(IntegerSenderAssociatedPtrInfo ptr_info, - TestSender* next_sender, - int32_t max_value_to_send) { - CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); - - ptr_.Bind(std::move(ptr_info)); - next_sender_ = next_sender ? next_sender : this; - max_value_to_send_ = max_value_to_send; - } - - void Send(int32_t value) { - CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); - - if (value > max_value_to_send_) - return; - - ptr_->Send(value); - - next_sender_->sender_thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value)); - } - - void TearDown() { - CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); - - ptr_.reset(); - } - - base::Thread* sender_thread() { return &sender_thread_; } - - private: - base::Thread sender_thread_; - TestSender* next_sender_; - int32_t max_value_to_send_; - - AssociatedInterfacePtr<IntegerSender> ptr_; -}; - -class TestReceiver { - public: - TestReceiver() : receiver_thread_("TestReceiver"), expected_calls_(0) { - receiver_thread_.Start(); - } - - void SetUp(AssociatedInterfaceRequest<IntegerSender> request0, - AssociatedInterfaceRequest<IntegerSender> request1, - size_t expected_calls, - const base::Closure& notify_finish) { - CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread()); - - impl0_.reset(new IntegerSenderImpl(std::move(request0))); - impl0_->set_notify_send_method_called( - base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this))); - impl1_.reset(new IntegerSenderImpl(std::move(request1))); - impl1_->set_notify_send_method_called( - base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this))); - - expected_calls_ = expected_calls; - notify_finish_ = notify_finish; - } - - void TearDown() { - CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread()); - - impl0_.reset(); - impl1_.reset(); - } - - base::Thread* receiver_thread() { return &receiver_thread_; } - const std::vector<int32_t>& values() const { return values_; } - - private: - void SendMethodCalled(int32_t value) { - values_.push_back(value); - - if (values_.size() >= expected_calls_) - notify_finish_.Run(); - } - - base::Thread receiver_thread_; - size_t expected_calls_; - - std::unique_ptr<IntegerSenderImpl> impl0_; - std::unique_ptr<IntegerSenderImpl> impl1_; - - std::vector<int32_t> values_; - - base::Closure notify_finish_; -}; - -class NotificationCounter { - public: - NotificationCounter(size_t total_count, const base::Closure& notify_finish) - : total_count_(total_count), - current_count_(0), - notify_finish_(notify_finish) {} - - ~NotificationCounter() {} - - // Okay to call from any thread. - void OnGotNotification() { - bool finshed = false; - { - base::AutoLock locker(lock_); - CHECK_LT(current_count_, total_count_); - current_count_++; - finshed = current_count_ == total_count_; - } - - if (finshed) - notify_finish_.Run(); - } - - private: - base::Lock lock_; - const size_t total_count_; - size_t current_count_; - base::Closure notify_finish_; -}; - -TEST_F(AssociatedInterfaceTest, MultiThreadAccess) { - // Set up four associated interfaces on a message pipe. Use the inteface - // pointers on four threads in parallel; run the interface implementations on - // two threads. Test that multi-threaded access works. - - const int32_t kMaxValue = 1000; - MessagePipe pipe; - scoped_refptr<MultiplexRouter> router0; - scoped_refptr<MultiplexRouter> router1; - CreateRouterPair(&router0, &router1); - - AssociatedInterfaceRequest<IntegerSender> requests[4]; - IntegerSenderAssociatedPtrInfo ptr_infos[4]; - for (size_t i = 0; i < 4; ++i) { - CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0, - &requests[i]); - } - - TestSender senders[4]; - for (size_t i = 0; i < 4; ++i) { - senders[i].sender_thread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]), - base::Passed(&ptr_infos[i]), nullptr, - kMaxValue * (i + 1) / 4)); - } - - base::RunLoop run_loop; - TestReceiver receivers[2]; - NotificationCounter counter( - 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - for (size_t i = 0; i < 2; ++i) { - receivers[i].receiver_thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]), - base::Passed(&requests[2 * i]), - base::Passed(&requests[2 * i + 1]), - static_cast<size_t>(kMaxValue / 2), - base::Bind(&NotificationCounter::OnGotNotification, - base::Unretained(&counter)))); - } - - for (size_t i = 0; i < 4; ++i) { - senders[i].sender_thread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]), - kMaxValue * i / 4 + 1)); - } - - run_loop.Run(); - - for (size_t i = 0; i < 4; ++i) { - base::RunLoop run_loop; - senders[i].sender_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])), - base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - run_loop.Run(); - } - - for (size_t i = 0; i < 2; ++i) { - base::RunLoop run_loop; - receivers[i].receiver_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])), - base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - run_loop.Run(); - } - - EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size()); - EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size()); - - std::vector<int32_t> all_values; - all_values.insert(all_values.end(), receivers[0].values().begin(), - receivers[0].values().end()); - all_values.insert(all_values.end(), receivers[1].values().begin(), - receivers[1].values().end()); - - std::sort(all_values.begin(), all_values.end()); - for (size_t i = 0; i < all_values.size(); ++i) - ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]); -} - -TEST_F(AssociatedInterfaceTest, FIFO) { - // Set up four associated interfaces on a message pipe. Use the inteface - // pointers on four threads; run the interface implementations on two threads. - // Take turns to make calls using the four pointers. Test that FIFO-ness is - // preserved. - - const int32_t kMaxValue = 100; - MessagePipe pipe; - scoped_refptr<MultiplexRouter> router0; - scoped_refptr<MultiplexRouter> router1; - CreateRouterPair(&router0, &router1); - - AssociatedInterfaceRequest<IntegerSender> requests[4]; - IntegerSenderAssociatedPtrInfo ptr_infos[4]; - for (size_t i = 0; i < 4; ++i) { - CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0, - &requests[i]); - } - - TestSender senders[4]; - for (size_t i = 0; i < 4; ++i) { - senders[i].sender_thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]), - base::Passed(&ptr_infos[i]), - base::Unretained(&senders[(i + 1) % 4]), kMaxValue)); - } - - base::RunLoop run_loop; - TestReceiver receivers[2]; - NotificationCounter counter( - 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - for (size_t i = 0; i < 2; ++i) { - receivers[i].receiver_thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]), - base::Passed(&requests[2 * i]), - base::Passed(&requests[2 * i + 1]), - static_cast<size_t>(kMaxValue / 2), - base::Bind(&NotificationCounter::OnGotNotification, - base::Unretained(&counter)))); - } - - senders[0].sender_thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1)); - - run_loop.Run(); - - for (size_t i = 0; i < 4; ++i) { - base::RunLoop run_loop; - senders[i].sender_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])), - base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - run_loop.Run(); - } - - for (size_t i = 0; i < 2; ++i) { - base::RunLoop run_loop; - receivers[i].receiver_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])), - base::Bind(&AssociatedInterfaceTest::QuitRunLoop, - base::Unretained(this), base::Unretained(&run_loop))); - run_loop.Run(); - } - - EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size()); - EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size()); - - for (size_t i = 0; i < 2; ++i) { - for (size_t j = 1; j < receivers[i].values().size(); ++j) - EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]); - } -} - -void CaptureInt32(int32_t* storage, - const base::Closure& closure, - int32_t value) { - *storage = value; - closure.Run(); -} - -void CaptureSenderPtrInfo(IntegerSenderAssociatedPtr* storage, - const base::Closure& closure, - IntegerSenderAssociatedPtrInfo info) { - storage->Bind(std::move(info)); - closure.Run(); -} - -TEST_F(AssociatedInterfaceTest, PassAssociatedInterfaces) { - IntegerSenderConnectionPtr connection_ptr; - IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr)); - - IntegerSenderAssociatedPtr sender0; - connection_ptr->GetSender(MakeRequest(&sender0)); - - int32_t echoed_value = 0; - base::RunLoop run_loop; - sender0->Echo(123, base::Bind(&CaptureInt32, &echoed_value, - run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_EQ(123, echoed_value); - - IntegerSenderAssociatedPtr sender1; - base::RunLoop run_loop2; - connection_ptr->AsyncGetSender( - base::Bind(&CaptureSenderPtrInfo, &sender1, run_loop2.QuitClosure())); - run_loop2.Run(); - EXPECT_TRUE(sender1); - - base::RunLoop run_loop3; - sender1->Echo(456, base::Bind(&CaptureInt32, &echoed_value, - run_loop3.QuitClosure())); - run_loop3.Run(); - EXPECT_EQ(456, echoed_value); -} - -TEST_F(AssociatedInterfaceTest, BindingWaitAndPauseWhenNoAssociatedInterfaces) { - IntegerSenderConnectionPtr connection_ptr; - IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr)); - - IntegerSenderAssociatedPtr sender0; - connection_ptr->GetSender(MakeRequest(&sender0)); - - EXPECT_FALSE(connection.binding()->HasAssociatedInterfaces()); - // There are no associated interfaces running on the pipe yet. It is okay to - // pause. - connection.binding()->PauseIncomingMethodCallProcessing(); - connection.binding()->ResumeIncomingMethodCallProcessing(); - - // There are no associated interfaces running on the pipe yet. It is okay to - // wait. - EXPECT_TRUE(connection.binding()->WaitForIncomingMethodCall()); - - // The previous wait has dispatched the GetSender request message, therefore - // an associated interface has been set up on the pipe. It is not allowed to - // wait or pause. - EXPECT_TRUE(connection.binding()->HasAssociatedInterfaces()); -} - -class PingServiceImpl : public PingService { - public: - explicit PingServiceImpl(PingServiceAssociatedRequest request) - : binding_(this, std::move(request)) {} - ~PingServiceImpl() override {} - - AssociatedBinding<PingService>& binding() { return binding_; } - - void set_ping_handler(const base::Closure& handler) { - ping_handler_ = handler; - } - - // PingService: - void Ping(const PingCallback& callback) override { - if (!ping_handler_.is_null()) - ping_handler_.Run(); - callback.Run(); - } - - private: - AssociatedBinding<PingService> binding_; - base::Closure ping_handler_; -}; - -class PingProviderImpl : public AssociatedPingProvider { - public: - explicit PingProviderImpl(AssociatedPingProviderRequest request) - : binding_(this, std::move(request)) {} - ~PingProviderImpl() override {} - - // AssociatedPingProvider: - void GetPing(PingServiceAssociatedRequest request) override { - ping_services_.emplace_back(new PingServiceImpl(std::move(request))); - - if (expected_bindings_count_ > 0 && - ping_services_.size() == expected_bindings_count_ && - !quit_waiting_.is_null()) { - expected_bindings_count_ = 0; - base::ResetAndReturn(&quit_waiting_).Run(); - } - } - - std::vector<std::unique_ptr<PingServiceImpl>>& ping_services() { - return ping_services_; - } - - void WaitForBindings(size_t count) { - DCHECK(quit_waiting_.is_null()); - - expected_bindings_count_ = count; - base::RunLoop loop; - quit_waiting_ = loop.QuitClosure(); - loop.Run(); - } - - private: - Binding<AssociatedPingProvider> binding_; - std::vector<std::unique_ptr<PingServiceImpl>> ping_services_; - size_t expected_bindings_count_ = 0; - base::Closure quit_waiting_; -}; - -class CallbackFilter : public MessageReceiver { - public: - explicit CallbackFilter(const base::Closure& callback) - : callback_(callback) {} - ~CallbackFilter() override {} - - static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) { - return base::MakeUnique<CallbackFilter>(callback); - } - - // MessageReceiver: - bool Accept(Message* message) override { - callback_.Run(); - return true; - } - - private: - const base::Closure callback_; -}; - -// Verifies that filters work as expected on associated bindings, i.e. that -// they're notified in order, before dispatch; and that each associated -// binding in a group operates with its own set of filters. -TEST_F(AssociatedInterfaceTest, BindingWithFilters) { - AssociatedPingProviderPtr provider; - PingProviderImpl provider_impl(MakeRequest(&provider)); - - PingServiceAssociatedPtr ping_a, ping_b; - provider->GetPing(MakeRequest(&ping_a)); - provider->GetPing(MakeRequest(&ping_b)); - provider_impl.WaitForBindings(2); - - ASSERT_EQ(2u, provider_impl.ping_services().size()); - PingServiceImpl& ping_a_impl = *provider_impl.ping_services()[0]; - PingServiceImpl& ping_b_impl = *provider_impl.ping_services()[1]; - - int a_status, b_status; - auto handler_helper = [] (int* a_status, int* b_status, int expected_a_status, - int new_a_status, int expected_b_status, - int new_b_status) { - EXPECT_EQ(expected_a_status, *a_status); - EXPECT_EQ(expected_b_status, *b_status); - *a_status = new_a_status; - *b_status = new_b_status; - }; - auto create_handler = [&] (int expected_a_status, int new_a_status, - int expected_b_status, int new_b_status) { - return base::Bind(handler_helper, &a_status, &b_status, expected_a_status, - new_a_status, expected_b_status, new_b_status); - }; - - ping_a_impl.binding().AddFilter( - CallbackFilter::Wrap(create_handler(0, 1, 0, 0))); - ping_a_impl.binding().AddFilter( - CallbackFilter::Wrap(create_handler(1, 2, 0, 0))); - ping_a_impl.set_ping_handler(create_handler(2, 3, 0, 0)); - - ping_b_impl.binding().AddFilter( - CallbackFilter::Wrap(create_handler(3, 3, 0, 1))); - ping_b_impl.binding().AddFilter( - CallbackFilter::Wrap(create_handler(3, 3, 1, 2))); - ping_b_impl.set_ping_handler(create_handler(3, 3, 2, 3)); - - for (int i = 0; i < 10; ++i) { - a_status = 0; - b_status = 0; - - { - base::RunLoop loop; - ping_a->Ping(loop.QuitClosure()); - loop.Run(); - } - - EXPECT_EQ(3, a_status); - EXPECT_EQ(0, b_status); - - { - base::RunLoop loop; - ping_b->Ping(loop.QuitClosure()); - loop.Run(); - } - - EXPECT_EQ(3, a_status); - EXPECT_EQ(3, b_status); - } -} - -TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTesting) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - IntegerSenderImpl impl0(std::move(request)); - AssociatedInterfacePtr<IntegerSender> ptr0; - ptr0.Bind(std::move(ptr_info)); - ptr0.set_connection_error_handler(base::Bind(&Fail)); - - bool ptr0_callback_run = false; - ptr0->Echo(123, ExpectValueSetFlagAndRunClosure( - 123, &ptr0_callback_run, base::Bind(&base::DoNothing))); - ptr0.FlushForTesting(); - EXPECT_TRUE(ptr0_callback_run); -} - -void SetBool(bool* value) { - *value = true; -} - -template <typename T> -void SetBoolWithUnusedParameter(bool* value, T unused) { - *value = true; -} - -TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTestingWithClosedPeer) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - AssociatedInterfacePtr<IntegerSender> ptr0; - ptr0.Bind(std::move(ptr_info)); - bool called = false; - ptr0.set_connection_error_handler(base::Bind(&SetBool, &called)); - request = nullptr; - - ptr0.FlushForTesting(); - EXPECT_TRUE(called); - ptr0.FlushForTesting(); -} - -TEST_F(AssociatedInterfaceTest, AssociatedBindingFlushForTesting) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - IntegerSenderImpl impl0(std::move(request)); - impl0.set_connection_error_handler(base::Bind(&Fail)); - AssociatedInterfacePtr<IntegerSender> ptr0; - ptr0.Bind(std::move(ptr_info)); - - bool ptr0_callback_run = false; - ptr0->Echo(123, ExpectValueSetFlagAndRunClosure( - 123, &ptr0_callback_run, base::Bind(&base::DoNothing))); - // Because the flush is sent from the binding, it only guarantees that the - // request has been received, not the response. The second flush waits for the - // response to be received. - impl0.binding()->FlushForTesting(); - impl0.binding()->FlushForTesting(); - EXPECT_TRUE(ptr0_callback_run); -} - -TEST_F(AssociatedInterfaceTest, - AssociatedBindingFlushForTestingWithClosedPeer) { - scoped_refptr<MultiplexRouter> router0; - scoped_refptr<MultiplexRouter> router1; - CreateRouterPair(&router0, &router1); - - AssociatedInterfaceRequest<IntegerSender> request; - { - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0, - &request); - } - - IntegerSenderImpl impl(std::move(request)); - bool called = false; - impl.set_connection_error_handler(base::Bind(&SetBool, &called)); - impl.binding()->FlushForTesting(); - EXPECT_TRUE(called); - impl.binding()->FlushForTesting(); -} - -TEST_F(AssociatedInterfaceTest, BindingFlushForTesting) { - IntegerSenderConnectionPtr ptr; - IntegerSenderConnectionImpl impl(MakeRequest(&ptr)); - bool called = false; - ptr->AsyncGetSender(base::Bind( - &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called)); - EXPECT_FALSE(called); - impl.binding()->set_connection_error_handler(base::Bind(&Fail)); - // Because the flush is sent from the binding, it only guarantees that the - // request has been received, not the response. The second flush waits for the - // response to be received. - impl.binding()->FlushForTesting(); - impl.binding()->FlushForTesting(); - EXPECT_TRUE(called); -} - -TEST_F(AssociatedInterfaceTest, BindingFlushForTestingWithClosedPeer) { - IntegerSenderConnectionPtr ptr; - IntegerSenderConnectionImpl impl(MakeRequest(&ptr)); - bool called = false; - impl.binding()->set_connection_error_handler(base::Bind(&SetBool, &called)); - ptr.reset(); - EXPECT_FALSE(called); - impl.binding()->FlushForTesting(); - EXPECT_TRUE(called); - impl.binding()->FlushForTesting(); -} - -TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTesting) { - IntegerSenderConnectionPtr ptr; - auto binding = - MakeStrongBinding(base::MakeUnique<IntegerSenderConnectionImpl>( - IntegerSenderConnectionRequest{}), - MakeRequest(&ptr)); - bool called = false; - IntegerSenderAssociatedPtr sender_ptr; - ptr->GetSender(MakeRequest(&sender_ptr)); - sender_ptr->Echo(1, base::Bind(&SetBoolWithUnusedParameter<int>, &called)); - EXPECT_FALSE(called); - // Because the flush is sent from the binding, it only guarantees that the - // request has been received, not the response. The second flush waits for the - // response to be received. - ASSERT_TRUE(binding); - binding->FlushForTesting(); - ASSERT_TRUE(binding); - binding->FlushForTesting(); - EXPECT_TRUE(called); -} - -TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTestingWithClosedPeer) { - IntegerSenderConnectionPtr ptr; - bool called = false; - auto binding = - MakeStrongBinding(base::MakeUnique<IntegerSenderConnectionImpl>( - IntegerSenderConnectionRequest{}), - MakeRequest(&ptr)); - binding->set_connection_error_handler(base::Bind(&SetBool, &called)); - ptr.reset(); - EXPECT_FALSE(called); - ASSERT_TRUE(binding); - binding->FlushForTesting(); - EXPECT_TRUE(called); - ASSERT_FALSE(binding); -} - -TEST_F(AssociatedInterfaceTest, PtrFlushForTesting) { - IntegerSenderConnectionPtr ptr; - IntegerSenderConnectionImpl impl(MakeRequest(&ptr)); - bool called = false; - ptr.set_connection_error_handler(base::Bind(&Fail)); - ptr->AsyncGetSender(base::Bind( - &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called)); - EXPECT_FALSE(called); - ptr.FlushForTesting(); - EXPECT_TRUE(called); -} - -TEST_F(AssociatedInterfaceTest, PtrFlushForTestingWithClosedPeer) { - IntegerSenderConnectionPtr ptr; - MakeRequest(&ptr); - bool called = false; - ptr.set_connection_error_handler(base::Bind(&SetBool, &called)); - EXPECT_FALSE(called); - ptr.FlushForTesting(); - EXPECT_TRUE(called); - ptr.FlushForTesting(); -} - -TEST_F(AssociatedInterfaceTest, AssociatedBindingConnectionErrorWithReason) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - IntegerSenderImpl impl(std::move(request)); - AssociatedInterfacePtr<IntegerSender> ptr; - ptr.Bind(std::move(ptr_info)); - - base::RunLoop run_loop; - impl.binding()->set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(123u, custom_reason); - EXPECT_EQ("farewell", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - ptr.ResetWithReason(123u, "farewell"); - - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, - PendingAssociatedBindingConnectionErrorWithReason) { - // Test that AssociatedBinding is notified with connection error when the - // interface hasn't associated with a message pipe and the peer is closed. - - IntegerSenderAssociatedPtr ptr; - IntegerSenderImpl impl(MakeRequest(&ptr)); - - base::RunLoop run_loop; - impl.binding()->set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(123u, custom_reason); - EXPECT_EQ("farewell", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - ptr.ResetWithReason(123u, "farewell"); - - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, AssociatedPtrConnectionErrorWithReason) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - IntegerSenderImpl impl(std::move(request)); - AssociatedInterfacePtr<IntegerSender> ptr; - ptr.Bind(std::move(ptr_info)); - - base::RunLoop run_loop; - ptr.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(456u, custom_reason); - EXPECT_EQ("farewell", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - impl.binding()->CloseWithReason(456u, "farewell"); - - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, PendingAssociatedPtrConnectionErrorWithReason) { - // Test that AssociatedInterfacePtr is notified with connection error when the - // interface hasn't associated with a message pipe and the peer is closed. - - IntegerSenderAssociatedPtr ptr; - auto request = MakeRequest(&ptr); - - base::RunLoop run_loop; - ptr.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(456u, custom_reason); - EXPECT_EQ("farewell", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - request.ResetWithReason(456u, "farewell"); - - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, AssociatedRequestResetWithReason) { - AssociatedInterfaceRequest<IntegerSender> request; - IntegerSenderAssociatedPtrInfo ptr_info; - CreateIntegerSender(&ptr_info, &request); - - AssociatedInterfacePtr<IntegerSender> ptr; - ptr.Bind(std::move(ptr_info)); - - base::RunLoop run_loop; - ptr.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(789u, custom_reason); - EXPECT_EQ("long time no see", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - request.ResetWithReason(789u, "long time no see"); - - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, ThreadSafeAssociatedInterfacePtr) { - IntegerSenderConnectionPtr connection_ptr; - IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr)); - - IntegerSenderAssociatedPtr sender; - connection_ptr->GetSender(MakeRequest(&sender)); - - scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_sender = - ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender)); - - { - // Test the thread safe pointer can be used from the interface ptr thread. - int32_t echoed_value = 0; - base::RunLoop run_loop; - (*thread_safe_sender) - ->Echo(123, base::Bind(&CaptureInt32, &echoed_value, - run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_EQ(123, echoed_value); - } - - // Test the thread safe pointer can be used from another thread. - base::RunLoop run_loop; - base::Thread other_thread("service test thread"); - other_thread.Start(); - - auto run_method = base::Bind( - [](const scoped_refptr<base::TaskRunner>& main_task_runner, - const base::Closure& quit_closure, - const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>& - thread_safe_sender) { - auto done_callback = base::Bind( - [](const scoped_refptr<base::TaskRunner>& main_task_runner, - const base::Closure& quit_closure, - base::PlatformThreadId thread_id, int32_t result) { - EXPECT_EQ(123, result); - // Validate the callback is invoked on the calling thread. - EXPECT_EQ(thread_id, base::PlatformThread::CurrentId()); - // Notify the run_loop to quit. - main_task_runner->PostTask(FROM_HERE, quit_closure); - }); - (*thread_safe_sender) - ->Echo(123, - base::Bind(done_callback, main_task_runner, quit_closure, - base::PlatformThread::CurrentId())); - }, - base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(), - thread_safe_sender); - other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method); - - // Block until the method callback is called on the background thread. - run_loop.Run(); -} - -struct ForwarderTestContext { - IntegerSenderConnectionPtr connection_ptr; - std::unique_ptr<IntegerSenderConnectionImpl> interface_impl; - IntegerSenderAssociatedRequest sender_request; -}; - -TEST_F(AssociatedInterfaceTest, - ThreadSafeAssociatedInterfacePtrWithTaskRunner) { - // Start the thread from where we'll bind the interface pointer. - base::Thread other_thread("service test thread"); - other_thread.Start(); - const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner = - other_thread.message_loop()->task_runner(); - - ForwarderTestContext* context = new ForwarderTestContext(); - IntegerSenderAssociatedPtrInfo sender_info; - base::WaitableEvent sender_info_bound_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - auto setup = [](base::WaitableEvent* sender_info_bound_event, - IntegerSenderAssociatedPtrInfo* sender_info, - ForwarderTestContext* context) { - context->interface_impl = base::MakeUnique<IntegerSenderConnectionImpl>( - MakeRequest(&context->connection_ptr)); - - auto sender_request = MakeRequest(sender_info); - context->connection_ptr->GetSender(std::move(sender_request)); - - // Unblock the main thread as soon as |sender_info| is set. - sender_info_bound_event->Signal(); - }; - other_thread_task_runner->PostTask( - FROM_HERE, - base::Bind(setup, &sender_info_bound_event, &sender_info, context)); - sender_info_bound_event.Wait(); - - // Create a ThreadSafeAssociatedPtr that binds on the background thread and is - // associated with |connection_ptr| there. - scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr = - ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender_info), - other_thread_task_runner); - - // Issue a call on the thread-safe ptr immediately. Note that this may happen - // before the interface is bound on the background thread, and that must be - // OK. - { - auto echo_callback = - base::Bind([](const base::Closure& quit_closure, int32_t result) { - EXPECT_EQ(123, result); - quit_closure.Run(); - }); - base::RunLoop run_loop; - (*thread_safe_ptr) - ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure())); - - // Block until the method callback is called. - run_loop.Run(); - } - - other_thread_task_runner->DeleteSoon(FROM_HERE, context); - - // Reset the pointer now so the InterfacePtr associated resources can be - // deleted before the background thread's message loop is invalidated. - thread_safe_ptr = nullptr; -} - -class DiscardingAssociatedPingProviderProvider - : public AssociatedPingProviderProvider { - public: - void GetPingProvider( - AssociatedPingProviderAssociatedRequest request) override {} -}; - -TEST_F(AssociatedInterfaceTest, CloseWithoutBindingAssociatedRequest) { - DiscardingAssociatedPingProviderProvider ping_provider_provider; - mojo::Binding<AssociatedPingProviderProvider> binding( - &ping_provider_provider); - auto provider_provider = binding.CreateInterfacePtrAndBind(); - AssociatedPingProviderAssociatedPtr provider; - provider_provider->GetPingProvider(mojo::MakeRequest(&provider)); - PingServiceAssociatedPtr ping; - provider->GetPing(mojo::MakeRequest(&ping)); - base::RunLoop run_loop; - ping.set_connection_error_handler(run_loop.QuitClosure()); - run_loop.Run(); -} - -TEST_F(AssociatedInterfaceTest, GetIsolatedInterface) { - IntegerSenderAssociatedPtr sender; - GetIsolatedInterface(MakeRequest(&sender).PassHandle()); - sender->Send(42); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/bind_task_runner_unittest.cc b/mojo/public/cpp/bindings/tests/bind_task_runner_unittest.cc deleted file mode 100644 index 569eb51..0000000 --- a/mojo/public/cpp/bindings/tests/bind_task_runner_unittest.cc +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/platform_thread.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -class TestTaskRunner : public base::SingleThreadTaskRunner { - public: - TestTaskRunner() - : thread_id_(base::PlatformThread::CurrentRef()), - quit_called_(false), - task_ready_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} - - bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override { - NOTREACHED(); - return false; - } - - bool PostDelayedTask(const tracked_objects::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override { - { - base::AutoLock locker(lock_); - tasks_.push(std::move(task)); - } - task_ready_.Signal(); - return true; - } - bool RunsTasksOnCurrentThread() const override { - return base::PlatformThread::CurrentRef() == thread_id_; - } - - // Only quits when Quit() is called. - void Run() { - DCHECK(RunsTasksOnCurrentThread()); - quit_called_ = false; - - while (true) { - { - base::AutoLock locker(lock_); - while (!tasks_.empty()) { - auto task = std::move(tasks_.front()); - tasks_.pop(); - - { - base::AutoUnlock unlocker(lock_); - std::move(task).Run(); - if (quit_called_) - return; - } - } - } - task_ready_.Wait(); - } - } - - void Quit() { - DCHECK(RunsTasksOnCurrentThread()); - quit_called_ = true; - } - - // Waits until one task is ready and runs it. - void RunOneTask() { - DCHECK(RunsTasksOnCurrentThread()); - - while (true) { - { - base::AutoLock locker(lock_); - if (!tasks_.empty()) { - auto task = std::move(tasks_.front()); - tasks_.pop(); - - { - base::AutoUnlock unlocker(lock_); - std::move(task).Run(); - return; - } - } - } - task_ready_.Wait(); - } - } - - private: - ~TestTaskRunner() override {} - - const base::PlatformThreadRef thread_id_; - bool quit_called_; - base::WaitableEvent task_ready_; - - // Protect |tasks_|. - base::Lock lock_; - std::queue<base::OnceClosure> tasks_; - - DISALLOW_COPY_AND_ASSIGN(TestTaskRunner); -}; - -template <typename BindingType, typename RequestType> -class IntegerSenderImpl : public IntegerSender { - public: - IntegerSenderImpl(RequestType request, - scoped_refptr<base::SingleThreadTaskRunner> runner) - : binding_(this, std::move(request), std::move(runner)) {} - - ~IntegerSenderImpl() override {} - - using EchoHandler = base::Callback<void(int32_t, const EchoCallback&)>; - - void set_echo_handler(const EchoHandler& handler) { echo_handler_ = handler; } - - void Echo(int32_t value, const EchoCallback& callback) override { - if (echo_handler_.is_null()) - callback.Run(value); - else - echo_handler_.Run(value, callback); - } - void Send(int32_t value) override { NOTREACHED(); } - - BindingType* binding() { return &binding_; } - - private: - BindingType binding_; - EchoHandler echo_handler_; -}; - -class IntegerSenderConnectionImpl : public IntegerSenderConnection { - public: - using SenderType = IntegerSenderImpl<AssociatedBinding<IntegerSender>, - IntegerSenderAssociatedRequest>; - - explicit IntegerSenderConnectionImpl( - IntegerSenderConnectionRequest request, - scoped_refptr<base::SingleThreadTaskRunner> runner, - scoped_refptr<base::SingleThreadTaskRunner> sender_runner) - : binding_(this, std::move(request), std::move(runner)), - sender_runner_(std::move(sender_runner)) {} - - ~IntegerSenderConnectionImpl() override {} - - void set_get_sender_notification(const base::Closure& notification) { - get_sender_notification_ = notification; - } - void GetSender(IntegerSenderAssociatedRequest sender) override { - sender_impl_.reset(new SenderType(std::move(sender), sender_runner_)); - get_sender_notification_.Run(); - } - - void AsyncGetSender(const AsyncGetSenderCallback& callback) override { - NOTREACHED(); - } - - Binding<IntegerSenderConnection>* binding() { return &binding_; } - - SenderType* sender_impl() { return sender_impl_.get(); } - - private: - Binding<IntegerSenderConnection> binding_; - std::unique_ptr<SenderType> sender_impl_; - scoped_refptr<base::SingleThreadTaskRunner> sender_runner_; - base::Closure get_sender_notification_; -}; - -class BindTaskRunnerTest : public testing::Test { - protected: - void SetUp() override { - binding_task_runner_ = scoped_refptr<TestTaskRunner>(new TestTaskRunner); - ptr_task_runner_ = scoped_refptr<TestTaskRunner>(new TestTaskRunner); - - auto request = MakeRequest(&ptr_, ptr_task_runner_); - impl_.reset(new ImplType(std::move(request), binding_task_runner_)); - } - - base::MessageLoop loop_; - scoped_refptr<TestTaskRunner> binding_task_runner_; - scoped_refptr<TestTaskRunner> ptr_task_runner_; - - IntegerSenderPtr ptr_; - using ImplType = - IntegerSenderImpl<Binding<IntegerSender>, IntegerSenderRequest>; - std::unique_ptr<ImplType> impl_; -}; - -class AssociatedBindTaskRunnerTest : public testing::Test { - protected: - void SetUp() override { - connection_binding_task_runner_ = - scoped_refptr<TestTaskRunner>(new TestTaskRunner); - connection_ptr_task_runner_ = - scoped_refptr<TestTaskRunner>(new TestTaskRunner); - sender_binding_task_runner_ = - scoped_refptr<TestTaskRunner>(new TestTaskRunner); - sender_ptr_task_runner_ = scoped_refptr<TestTaskRunner>(new TestTaskRunner); - - auto connection_request = - MakeRequest(&connection_ptr_, connection_ptr_task_runner_); - connection_impl_.reset(new IntegerSenderConnectionImpl( - std::move(connection_request), connection_binding_task_runner_, - sender_binding_task_runner_)); - - connection_impl_->set_get_sender_notification( - base::Bind(&AssociatedBindTaskRunnerTest::QuitTaskRunner, - base::Unretained(this))); - - connection_ptr_->GetSender( - MakeRequest(&sender_ptr_, sender_ptr_task_runner_)); - connection_binding_task_runner_->Run(); - } - - void QuitTaskRunner() { - connection_binding_task_runner_->Quit(); - } - - base::MessageLoop loop_; - scoped_refptr<TestTaskRunner> connection_binding_task_runner_; - scoped_refptr<TestTaskRunner> connection_ptr_task_runner_; - scoped_refptr<TestTaskRunner> sender_binding_task_runner_; - scoped_refptr<TestTaskRunner> sender_ptr_task_runner_; - - IntegerSenderConnectionPtr connection_ptr_; - std::unique_ptr<IntegerSenderConnectionImpl> connection_impl_; - IntegerSenderAssociatedPtr sender_ptr_; -}; - -void DoSetFlagAndQuitTaskRunner(bool* flag, - scoped_refptr<TestTaskRunner> task_runner) { - *flag = true; - if (task_runner) - task_runner->Quit(); -} - -void DoExpectValueSetFlagAndQuitTaskRunner( - int32_t expected_value, - bool* flag, - scoped_refptr<TestTaskRunner> task_runner, - int32_t value) { - EXPECT_EQ(expected_value, value); - DoSetFlagAndQuitTaskRunner(flag, task_runner); -} - -void DoExpectValueSetFlagForwardValueAndQuitTaskRunner( - int32_t expected_value, - bool* flag, - scoped_refptr<TestTaskRunner> task_runner, - int32_t value, - const IntegerSender::EchoCallback& callback) { - EXPECT_EQ(expected_value, value); - *flag = true; - callback.Run(value); - task_runner->Quit(); -} - -base::Closure SetFlagAndQuitTaskRunner( - bool* flag, - scoped_refptr<TestTaskRunner> task_runner) { - return base::Bind(&DoSetFlagAndQuitTaskRunner, flag, task_runner); -} - -base::Callback<void(int32_t)> ExpectValueSetFlagAndQuitTaskRunner( - int32_t expected_value, - bool* flag, - scoped_refptr<TestTaskRunner> task_runner) { - return base::Bind(&DoExpectValueSetFlagAndQuitTaskRunner, expected_value, - flag, task_runner); -} - -TEST_F(BindTaskRunnerTest, MethodCall) { - bool echo_called = false; - impl_->set_echo_handler( - base::Bind(&DoExpectValueSetFlagForwardValueAndQuitTaskRunner, - 1024, &echo_called, binding_task_runner_)); - bool echo_replied = false; - ptr_->Echo(1024, ExpectValueSetFlagAndQuitTaskRunner(1024, &echo_replied, - ptr_task_runner_)); - binding_task_runner_->Run(); - EXPECT_TRUE(echo_called); - ptr_task_runner_->Run(); - EXPECT_TRUE(echo_replied); -} - -TEST_F(BindTaskRunnerTest, BindingConnectionError) { - bool connection_error_called = false; - impl_->binding()->set_connection_error_handler( - SetFlagAndQuitTaskRunner(&connection_error_called, binding_task_runner_)); - ptr_.reset(); - binding_task_runner_->Run(); - EXPECT_TRUE(connection_error_called); -} - -TEST_F(BindTaskRunnerTest, PtrConnectionError) { - bool connection_error_called = false; - ptr_.set_connection_error_handler( - SetFlagAndQuitTaskRunner(&connection_error_called, ptr_task_runner_)); - impl_->binding()->Close(); - ptr_task_runner_->Run(); - EXPECT_TRUE(connection_error_called); -} - -void ExpectValueSetFlagAndForward(int32_t expected_value, - bool* flag, - int32_t value, - const IntegerSender::EchoCallback& callback) { - EXPECT_EQ(expected_value, value); - *flag = true; - callback.Run(value); -} - -TEST_F(AssociatedBindTaskRunnerTest, MethodCall) { - bool echo_called = false; - connection_impl_->sender_impl()->set_echo_handler( - base::Bind(&ExpectValueSetFlagAndForward, 1024, &echo_called)); - - bool echo_replied = false; - sender_ptr_->Echo( - 1024, ExpectValueSetFlagAndQuitTaskRunner(1024, &echo_replied, nullptr)); - - // The Echo request first arrives at the master endpoint's task runner, and - // then is forwarded to the associated endpoint's task runner. - connection_binding_task_runner_->RunOneTask(); - sender_binding_task_runner_->RunOneTask(); - EXPECT_TRUE(echo_called); - - // Similarly, the Echo response arrives at the master endpoint's task runner - // and then is forwarded to the associated endpoint's task runner. - connection_ptr_task_runner_->RunOneTask(); - sender_ptr_task_runner_->RunOneTask(); - EXPECT_TRUE(echo_replied); -} - -TEST_F(AssociatedBindTaskRunnerTest, BindingConnectionError) { - bool sender_impl_error = false; - connection_impl_->sender_impl()->binding()->set_connection_error_handler( - SetFlagAndQuitTaskRunner(&sender_impl_error, - sender_binding_task_runner_)); - bool connection_impl_error = false; - connection_impl_->binding()->set_connection_error_handler( - SetFlagAndQuitTaskRunner(&connection_impl_error, - connection_binding_task_runner_)); - bool sender_ptr_error = false; - sender_ptr_.set_connection_error_handler( - SetFlagAndQuitTaskRunner(&sender_ptr_error, sender_ptr_task_runner_)); - connection_ptr_.reset(); - sender_ptr_task_runner_->Run(); - EXPECT_TRUE(sender_ptr_error); - connection_binding_task_runner_->Run(); - EXPECT_TRUE(connection_impl_error); - sender_binding_task_runner_->Run(); - EXPECT_TRUE(sender_impl_error); -} - -TEST_F(AssociatedBindTaskRunnerTest, PtrConnectionError) { - bool sender_impl_error = false; - connection_impl_->sender_impl()->binding()->set_connection_error_handler( - SetFlagAndQuitTaskRunner(&sender_impl_error, - sender_binding_task_runner_)); - bool connection_ptr_error = false; - connection_ptr_.set_connection_error_handler( - SetFlagAndQuitTaskRunner(&connection_ptr_error, - connection_ptr_task_runner_)); - bool sender_ptr_error = false; - sender_ptr_.set_connection_error_handler( - SetFlagAndQuitTaskRunner(&sender_ptr_error, sender_ptr_task_runner_)); - connection_impl_->binding()->Close(); - sender_binding_task_runner_->Run(); - EXPECT_TRUE(sender_impl_error); - connection_ptr_task_runner_->Run(); - EXPECT_TRUE(connection_ptr_error); - sender_ptr_task_runner_->Run(); - EXPECT_TRUE(sender_ptr_error); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc b/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc deleted file mode 100644 index 43122ce..0000000 --- a/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/test/gtest_util.h" -#include "build/build_config.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/public/cpp/test_support/test_support.h" -#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// The tests in this file are designed to test the interaction between a -// Callback and its associated Binding. If a Callback is deleted before -// being used we DCHECK fail--unless the associated Binding has already -// been closed or deleted. This contract must be explained to the Mojo -// application developer. For example it is the developer's responsibility to -// ensure that the Binding is destroyed before an unused Callback is destroyed. -// -/////////////////////////////////////////////////////////////////////////////// - -namespace mojo { -namespace test { -namespace { - -void SaveValue(int32_t* storage, const base::Closure& closure, int32_t value) { - *storage = value; - if (!closure.is_null()) - closure.Run(); -} - -base::Callback<void(int32_t)> BindValueSaver(int32_t* last_value_seen, - const base::Closure& closure) { - return base::Bind(&SaveValue, last_value_seen, closure); -} - -// An implementation of sample::Provider used on the server side. -// It only implements one of the methods: EchoInt(). -// All it does is save the values and Callbacks it sees. -class InterfaceImpl : public sample::Provider { - public: - InterfaceImpl() - : last_server_value_seen_(0), - callback_saved_(new EchoIntCallback) {} - - ~InterfaceImpl() override { - if (callback_saved_) { - delete callback_saved_; - } - } - - // Run's the callback previously saved from the last invocation - // of |EchoInt()|. - bool RunCallback() { - if (callback_saved_) { - callback_saved_->Run(last_server_value_seen_); - return true; - } - return false; - } - - // Delete's the previously saved callback. - void DeleteCallback() { - delete callback_saved_; - callback_saved_ = nullptr; - } - - // sample::Provider implementation - - // Saves its two input values in member variables and does nothing else. - void EchoInt(int32_t x, const EchoIntCallback& callback) override { - last_server_value_seen_ = x; - *callback_saved_ = callback; - if (!closure_.is_null()) { - closure_.Run(); - closure_.Reset(); - } - } - - void EchoString(const std::string& a, - const EchoStringCallback& callback) override { - CHECK(false) << "Not implemented."; - } - - void EchoStrings(const std::string& a, - const std::string& b, - const EchoStringsCallback& callback) override { - CHECK(false) << "Not implemented."; - } - - void EchoMessagePipeHandle( - ScopedMessagePipeHandle a, - const EchoMessagePipeHandleCallback& callback) override { - CHECK(false) << "Not implemented."; - } - - void EchoEnum(sample::Enum a, const EchoEnumCallback& callback) override { - CHECK(false) << "Not implemented."; - } - - void resetLastServerValueSeen() { last_server_value_seen_ = 0; } - - int32_t last_server_value_seen() const { return last_server_value_seen_; } - - void set_closure(const base::Closure& closure) { closure_ = closure; } - - private: - int32_t last_server_value_seen_; - EchoIntCallback* callback_saved_; - base::Closure closure_; -}; - -class BindingCallbackTest : public testing::Test { - public: - BindingCallbackTest() {} - ~BindingCallbackTest() override {} - - protected: - int32_t last_client_callback_value_seen_; - sample::ProviderPtr interface_ptr_; - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - private: - base::MessageLoop loop_; -}; - -// Tests that the InterfacePtr and the Binding can communicate with each -// other normally. -TEST_F(BindingCallbackTest, Basic) { - // Create the ServerImpl and the Binding. - InterfaceImpl server_impl; - Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_)); - - // Initialize the test values. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method. - base::RunLoop run_loop, run_loop2; - server_impl.set_closure(run_loop.QuitClosure()); - interface_ptr_->EchoInt( - 7, - BindValueSaver(&last_client_callback_value_seen_, - run_loop2.QuitClosure())); - run_loop.Run(); - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(7, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Now run the Callback. - server_impl.RunCallback(); - run_loop2.Run(); - - // Check that the client has now seen the correct value. - EXPECT_EQ(7, last_client_callback_value_seen_); - - // Initialize the test values again. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method again. - base::RunLoop run_loop3, run_loop4; - server_impl.set_closure(run_loop3.QuitClosure()); - interface_ptr_->EchoInt( - 13, - BindValueSaver(&last_client_callback_value_seen_, - run_loop4.QuitClosure())); - run_loop3.Run(); - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(13, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Now run the Callback again. - server_impl.RunCallback(); - run_loop4.Run(); - - // Check that the client has now seen the correct value again. - EXPECT_EQ(13, last_client_callback_value_seen_); -} - -// Tests that running the Callback after the Binding has been deleted -// results in a clean failure. -TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) { - // Create the ServerImpl. - InterfaceImpl server_impl; - base::RunLoop run_loop; - { - // Create the binding in an inner scope so it can be deleted first. - Binding<sample::Provider> binding(&server_impl, - MakeRequest(&interface_ptr_)); - interface_ptr_.set_connection_error_handler(run_loop.QuitClosure()); - - // Initialize the test values. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method. - base::RunLoop run_loop2; - server_impl.set_closure(run_loop2.QuitClosure()); - interface_ptr_->EchoInt( - 7, - BindValueSaver(&last_client_callback_value_seen_, base::Closure())); - run_loop2.Run(); - } - // The binding has now been destroyed and the pipe is closed. - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(7, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Now try to run the Callback. This should do nothing since the pipe - // is closed. - EXPECT_TRUE(server_impl.RunCallback()); - PumpMessages(); - - // Check that the client has still not seen the correct value. - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Attempt to invoke the method again and confirm that an error was - // encountered. - interface_ptr_->EchoInt( - 13, - BindValueSaver(&last_client_callback_value_seen_, base::Closure())); - run_loop.Run(); - EXPECT_TRUE(interface_ptr_.encountered_error()); -} - -// Tests that deleting a Callback without running it after the corresponding -// binding has already been deleted does not result in a crash. -TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) { - // Create the ServerImpl. - InterfaceImpl server_impl; - { - // Create the binding in an inner scope so it can be deleted first. - Binding<sample::Provider> binding(&server_impl, - MakeRequest(&interface_ptr_)); - - // Initialize the test values. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method. - base::RunLoop run_loop; - server_impl.set_closure(run_loop.QuitClosure()); - interface_ptr_->EchoInt( - 7, - BindValueSaver(&last_client_callback_value_seen_, base::Closure())); - run_loop.Run(); - } - // The binding has now been destroyed and the pipe is closed. - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(7, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Delete the callback without running it. This should not - // cause a problem because the insfrastructure can detect that the - // binding has already been destroyed and the pipe is closed. - server_impl.DeleteCallback(); -} - -// Tests that closing a Binding allows us to delete a callback -// without running it without encountering a crash. -TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) { - // Create the ServerImpl and the Binding. - InterfaceImpl server_impl; - Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_)); - - // Initialize the test values. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method. - base::RunLoop run_loop; - server_impl.set_closure(run_loop.QuitClosure()); - interface_ptr_->EchoInt( - 7, - BindValueSaver(&last_client_callback_value_seen_, base::Closure())); - run_loop.Run(); - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(7, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - // Now close the Binding. - binding.Close(); - - // Delete the callback without running it. This should not - // cause a crash because the insfrastructure can detect that the - // binding has already been closed. - server_impl.DeleteCallback(); - - // Check that the client has still not seen the correct value. - EXPECT_EQ(0, last_client_callback_value_seen_); -} - -// Tests that deleting a Callback without using it before the -// Binding has been destroyed or closed results in a DCHECK. -TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) { - // Create the ServerImpl and the Binding. - InterfaceImpl server_impl; - Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_)); - - // Initialize the test values. - server_impl.resetLastServerValueSeen(); - last_client_callback_value_seen_ = 0; - - // Invoke the Echo method. - base::RunLoop run_loop; - server_impl.set_closure(run_loop.QuitClosure()); - interface_ptr_->EchoInt( - 7, - BindValueSaver(&last_client_callback_value_seen_, base::Closure())); - run_loop.Run(); - - // Check that server saw the correct value, but the client has not yet. - EXPECT_EQ(7, server_impl.last_server_value_seen()); - EXPECT_EQ(0, last_client_callback_value_seen_); - - EXPECT_DCHECK_DEATH(server_impl.DeleteCallback()); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/binding_set_unittest.cc b/mojo/public/cpp/bindings/tests/binding_set_unittest.cc deleted file mode 100644 index 07acfbe..0000000 --- a/mojo/public/cpp/bindings/tests/binding_set_unittest.cc +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> -#include <utility> - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/associated_binding_set.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" -#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -class BindingSetTest : public testing::Test { - public: - BindingSetTest() {} - ~BindingSetTest() override {} - - base::MessageLoop& loop() { return loop_; } - - private: - base::MessageLoop loop_; - - DISALLOW_COPY_AND_ASSIGN(BindingSetTest); -}; - -template <typename BindingSetType, typename ContextType> -void ExpectContextHelper(BindingSetType* binding_set, - ContextType expected_context) { - EXPECT_EQ(expected_context, binding_set->dispatch_context()); -} - -template <typename BindingSetType, typename ContextType> -base::Closure ExpectContext(BindingSetType* binding_set, - ContextType expected_context) { - return base::Bind( - &ExpectContextHelper<BindingSetType, ContextType>, binding_set, - expected_context); -} - -base::Closure Sequence(const base::Closure& first, - const base::Closure& second) { - return base::Bind( - [] (const base::Closure& first, const base::Closure& second) { - first.Run(); - second.Run(); - }, first, second); -} - -class PingImpl : public PingService { - public: - PingImpl() {} - ~PingImpl() override {} - - void set_ping_handler(const base::Closure& handler) { - ping_handler_ = handler; - } - - private: - // PingService: - void Ping(const PingCallback& callback) override { - if (!ping_handler_.is_null()) - ping_handler_.Run(); - callback.Run(); - } - - base::Closure ping_handler_; -}; - -TEST_F(BindingSetTest, BindingSetContext) { - PingImpl impl; - - BindingSet<PingService, int> bindings; - PingServicePtr ping_a, ping_b; - bindings.AddBinding(&impl, MakeRequest(&ping_a), 1); - bindings.AddBinding(&impl, MakeRequest(&ping_b), 2); - - { - impl.set_ping_handler(ExpectContext(&bindings, 1)); - base::RunLoop loop; - ping_a->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - impl.set_ping_handler(ExpectContext(&bindings, 2)); - base::RunLoop loop; - ping_b->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_connection_error_handler( - Sequence(ExpectContext(&bindings, 1), loop.QuitClosure())); - ping_a.reset(); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_connection_error_handler( - Sequence(ExpectContext(&bindings, 2), loop.QuitClosure())); - ping_b.reset(); - loop.Run(); - } - - EXPECT_TRUE(bindings.empty()); -} - -TEST_F(BindingSetTest, BindingSetConnectionErrorWithReason) { - PingImpl impl; - PingServicePtr ptr; - BindingSet<PingService> bindings; - bindings.AddBinding(&impl, MakeRequest(&ptr)); - - base::RunLoop run_loop; - bindings.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(1024u, custom_reason); - EXPECT_EQ("bye", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - ptr.ResetWithReason(1024u, "bye"); -} - -class PingProviderImpl : public AssociatedPingProvider, public PingService { - public: - PingProviderImpl() {} - ~PingProviderImpl() override {} - - void set_new_ping_context(int context) { new_ping_context_ = context; } - - void set_new_ping_handler(const base::Closure& handler) { - new_ping_handler_ = handler; - } - - void set_ping_handler(const base::Closure& handler) { - ping_handler_ = handler; - } - - AssociatedBindingSet<PingService, int>& ping_bindings() { - return ping_bindings_; - } - - private: - // AssociatedPingProvider: - void GetPing(PingServiceAssociatedRequest request) override { - ping_bindings_.AddBinding(this, std::move(request), new_ping_context_); - if (!new_ping_handler_.is_null()) - new_ping_handler_.Run(); - } - - // PingService: - void Ping(const PingCallback& callback) override { - if (!ping_handler_.is_null()) - ping_handler_.Run(); - callback.Run(); - } - - AssociatedBindingSet<PingService, int> ping_bindings_; - int new_ping_context_ = -1; - base::Closure ping_handler_; - base::Closure new_ping_handler_; -}; - -TEST_F(BindingSetTest, AssociatedBindingSetContext) { - AssociatedPingProviderPtr provider; - PingProviderImpl impl; - Binding<AssociatedPingProvider> binding(&impl, MakeRequest(&provider)); - - PingServiceAssociatedPtr ping_a; - { - base::RunLoop loop; - impl.set_new_ping_context(1); - impl.set_new_ping_handler(loop.QuitClosure()); - provider->GetPing(MakeRequest(&ping_a)); - loop.Run(); - } - - PingServiceAssociatedPtr ping_b; - { - base::RunLoop loop; - impl.set_new_ping_context(2); - impl.set_new_ping_handler(loop.QuitClosure()); - provider->GetPing(MakeRequest(&ping_b)); - loop.Run(); - } - - { - impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 1)); - base::RunLoop loop; - ping_a->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 2)); - base::RunLoop loop; - ping_b->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - base::RunLoop loop; - impl.ping_bindings().set_connection_error_handler( - Sequence(ExpectContext(&impl.ping_bindings(), 1), loop.QuitClosure())); - ping_a.reset(); - loop.Run(); - } - - { - base::RunLoop loop; - impl.ping_bindings().set_connection_error_handler( - Sequence(ExpectContext(&impl.ping_bindings(), 2), loop.QuitClosure())); - ping_b.reset(); - loop.Run(); - } - - EXPECT_TRUE(impl.ping_bindings().empty()); -} - -TEST_F(BindingSetTest, MasterInterfaceBindingSetContext) { - AssociatedPingProviderPtr provider_a, provider_b; - PingProviderImpl impl; - BindingSet<AssociatedPingProvider, int> bindings; - - bindings.AddBinding(&impl, MakeRequest(&provider_a), 1); - bindings.AddBinding(&impl, MakeRequest(&provider_b), 2); - - { - PingServiceAssociatedPtr ping; - base::RunLoop loop; - impl.set_new_ping_handler( - Sequence(ExpectContext(&bindings, 1), loop.QuitClosure())); - provider_a->GetPing(MakeRequest(&ping)); - loop.Run(); - } - - { - PingServiceAssociatedPtr ping; - base::RunLoop loop; - impl.set_new_ping_handler( - Sequence(ExpectContext(&bindings, 2), loop.QuitClosure())); - provider_b->GetPing(MakeRequest(&ping)); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_connection_error_handler( - Sequence(ExpectContext(&bindings, 1), loop.QuitClosure())); - provider_a.reset(); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_connection_error_handler( - Sequence(ExpectContext(&bindings, 2), loop.QuitClosure())); - provider_b.reset(); - loop.Run(); - } - - EXPECT_TRUE(bindings.empty()); -} - -TEST_F(BindingSetTest, PreDispatchHandler) { - PingImpl impl; - - BindingSet<PingService, int> bindings; - PingServicePtr ping_a, ping_b; - bindings.AddBinding(&impl, MakeRequest(&ping_a), 1); - bindings.AddBinding(&impl, MakeRequest(&ping_b), 2); - - { - bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) { - EXPECT_EQ(1, context); - })); - base::RunLoop loop; - ping_a->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) { - EXPECT_EQ(2, context); - })); - base::RunLoop loop; - ping_b->Ping(loop.QuitClosure()); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_pre_dispatch_handler( - base::Bind([](base::RunLoop* loop, const int& context) { - EXPECT_EQ(1, context); - loop->Quit(); - }, &loop)); - ping_a.reset(); - loop.Run(); - } - - { - base::RunLoop loop; - bindings.set_pre_dispatch_handler( - base::Bind([](base::RunLoop* loop, const int& context) { - EXPECT_EQ(2, context); - loop->Quit(); - }, &loop)); - ping_b.reset(); - loop.Run(); - } - - EXPECT_TRUE(bindings.empty()); -} - -TEST_F(BindingSetTest, AssociatedBindingSetConnectionErrorWithReason) { - AssociatedPingProviderPtr master_ptr; - PingProviderImpl master_impl; - Binding<AssociatedPingProvider> master_binding(&master_impl, &master_ptr); - - base::RunLoop run_loop; - master_impl.ping_bindings().set_connection_error_with_reason_handler( - base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(2048u, custom_reason); - EXPECT_EQ("bye", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - PingServiceAssociatedPtr ptr; - master_ptr->GetPing(MakeRequest(&ptr)); - - ptr.ResetWithReason(2048u, "bye"); - - run_loop.Run(); -} - -class PingInstanceCounter : public PingService { - public: - PingInstanceCounter() { ++instance_count; } - ~PingInstanceCounter() override { --instance_count; } - - void Ping(const PingCallback& callback) override {} - - static int instance_count; -}; -int PingInstanceCounter::instance_count = 0; - -TEST_F(BindingSetTest, StrongBinding_Destructor) { - PingServicePtr ping_a, ping_b; - auto bindings = base::MakeUnique<StrongBindingSet<PingService>>(); - - bindings->AddBinding(base::MakeUnique<PingInstanceCounter>(), - mojo::MakeRequest(&ping_a)); - EXPECT_EQ(1, PingInstanceCounter::instance_count); - - bindings->AddBinding(base::MakeUnique<PingInstanceCounter>(), - mojo::MakeRequest(&ping_b)); - EXPECT_EQ(2, PingInstanceCounter::instance_count); - - bindings.reset(); - EXPECT_EQ(0, PingInstanceCounter::instance_count); -} - -TEST_F(BindingSetTest, StrongBinding_ConnectionError) { - PingServicePtr ping_a, ping_b; - StrongBindingSet<PingService> bindings; - bindings.AddBinding(base::MakeUnique<PingInstanceCounter>(), - mojo::MakeRequest(&ping_a)); - bindings.AddBinding(base::MakeUnique<PingInstanceCounter>(), - mojo::MakeRequest(&ping_b)); - EXPECT_EQ(2, PingInstanceCounter::instance_count); - - ping_a.reset(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, PingInstanceCounter::instance_count); - - ping_b.reset(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, PingInstanceCounter::instance_count); -} - -TEST_F(BindingSetTest, StrongBinding_RemoveBinding) { - PingServicePtr ping_a, ping_b; - StrongBindingSet<PingService> bindings; - BindingId binding_id_a = bindings.AddBinding( - base::MakeUnique<PingInstanceCounter>(), mojo::MakeRequest(&ping_a)); - BindingId binding_id_b = bindings.AddBinding( - base::MakeUnique<PingInstanceCounter>(), mojo::MakeRequest(&ping_b)); - EXPECT_EQ(2, PingInstanceCounter::instance_count); - - EXPECT_TRUE(bindings.RemoveBinding(binding_id_a)); - EXPECT_EQ(1, PingInstanceCounter::instance_count); - - EXPECT_TRUE(bindings.RemoveBinding(binding_id_b)); - EXPECT_EQ(0, PingInstanceCounter::instance_count); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/binding_unittest.cc b/mojo/public/cpp/bindings/tests/binding_unittest.cc deleted file mode 100644 index e76993b..0000000 --- a/mojo/public/cpp/bindings/tests/binding_unittest.cc +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Note: This file tests both binding.h (mojo::Binding) and strong_binding.h -// (mojo::StrongBinding). - -#include "mojo/public/cpp/bindings/binding.h" - -#include <stdint.h> -#include <utility> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" -#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" -#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -class BindingTestBase : public testing::Test { - public: - BindingTestBase() {} - ~BindingTestBase() override {} - - base::MessageLoop& loop() { return loop_; } - - private: - base::MessageLoop loop_; - - DISALLOW_COPY_AND_ASSIGN(BindingTestBase); -}; - -class ServiceImpl : public sample::Service { - public: - explicit ServiceImpl(bool* was_deleted = nullptr) - : was_deleted_(was_deleted) {} - ~ServiceImpl() override { - if (was_deleted_) - *was_deleted_ = true; - } - - private: - // sample::Service implementation - void Frobinate(sample::FooPtr foo, - BazOptions options, - sample::PortPtr port, - const FrobinateCallback& callback) override { - callback.Run(1); - } - void GetPort(InterfaceRequest<sample::Port> port) override {} - - bool* const was_deleted_; - - DISALLOW_COPY_AND_ASSIGN(ServiceImpl); -}; - -template <typename... Args> -void DoSetFlagAndRunClosure(bool* flag, - const base::Closure& closure, - Args... args) { - *flag = true; - if (!closure.is_null()) - closure.Run(); -} - -template <typename... Args> -base::Callback<void(Args...)> SetFlagAndRunClosure( - bool* flag, - const base::Closure& callback = base::Closure()) { - return base::Bind(&DoSetFlagAndRunClosure<Args...>, flag, callback); -} - -// BindingTest ----------------------------------------------------------------- - -using BindingTest = BindingTestBase; - -TEST_F(BindingTest, Close) { - bool called = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - base::RunLoop run_loop; - ptr.set_connection_error_handler( - SetFlagAndRunClosure(&called, run_loop.QuitClosure())); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - - binding.Close(); - EXPECT_FALSE(called); - run_loop.Run(); - EXPECT_TRUE(called); -} - -// Tests that destroying a mojo::Binding closes the bound message pipe handle. -TEST_F(BindingTest, DestroyClosesMessagePipe) { - bool encountered_error = false; - ServiceImpl impl; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - base::RunLoop run_loop; - ptr.set_connection_error_handler( - SetFlagAndRunClosure(&encountered_error, run_loop.QuitClosure())); - bool called = false; - base::RunLoop run_loop2; - { - Binding<sample::Service> binding(&impl, std::move(request)); - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop2.QuitClosure())); - run_loop2.Run(); - EXPECT_TRUE(called); - EXPECT_FALSE(encountered_error); - } - // Now that the Binding is out of scope we should detect an error on the other - // end of the pipe. - run_loop.Run(); - EXPECT_TRUE(encountered_error); - - // And calls should fail. - called = false; - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop2.QuitClosure())); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(called); -} - -// Tests that the binding's connection error handler gets called when the other -// end is closed. -TEST_F(BindingTest, ConnectionError) { - bool called = false; - { - ServiceImpl impl; - sample::ServicePtr ptr; - Binding<sample::Service> binding(&impl, MakeRequest(&ptr)); - base::RunLoop run_loop; - binding.set_connection_error_handler( - SetFlagAndRunClosure(&called, run_loop.QuitClosure())); - ptr.reset(); - EXPECT_FALSE(called); - run_loop.Run(); - EXPECT_TRUE(called); - // We want to make sure that it isn't called again during destruction. - called = false; - } - EXPECT_FALSE(called); -} - -// Tests that calling Close doesn't result in the connection error handler being -// called. -TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) { - ServiceImpl impl; - sample::ServicePtr ptr; - Binding<sample::Service> binding(&impl, MakeRequest(&ptr)); - bool called = false; - binding.set_connection_error_handler(SetFlagAndRunClosure(&called)); - binding.Close(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(called); - - // We can also close the other end, and the error handler still won't be - // called. - ptr.reset(); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(called); -} - -class ServiceImplWithBinding : public ServiceImpl { - public: - ServiceImplWithBinding(bool* was_deleted, - const base::Closure& closure, - InterfaceRequest<sample::Service> request) - : ServiceImpl(was_deleted), - binding_(this, std::move(request)), - closure_(closure) { - binding_.set_connection_error_handler( - base::Bind(&ServiceImplWithBinding::OnConnectionError, - base::Unretained(this))); - } - - private: - ~ServiceImplWithBinding() override{ - closure_.Run(); - } - - void OnConnectionError() { delete this; } - - Binding<sample::Service> binding_; - base::Closure closure_; - - DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); -}; - -// Tests that the binding may be deleted in the connection error handler. -TEST_F(BindingTest, SelfDeleteOnConnectionError) { - bool was_deleted = false; - sample::ServicePtr ptr; - // This should delete itself on connection error. - base::RunLoop run_loop; - new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), - MakeRequest(&ptr)); - ptr.reset(); - EXPECT_FALSE(was_deleted); - run_loop.Run(); - EXPECT_TRUE(was_deleted); -} - -// Tests that explicitly calling Unbind followed by rebinding works. -TEST_F(BindingTest, Unbind) { - ServiceImpl impl; - sample::ServicePtr ptr; - Binding<sample::Service> binding(&impl, MakeRequest(&ptr)); - - bool called = false; - base::RunLoop run_loop; - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop.QuitClosure())); - run_loop.Run(); - EXPECT_TRUE(called); - - called = false; - auto request = binding.Unbind(); - EXPECT_FALSE(binding.is_bound()); - // All calls should fail when not bound... - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop.QuitClosure())); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(called); - - called = false; - binding.Bind(std::move(request)); - EXPECT_TRUE(binding.is_bound()); - // ...and should succeed again when the rebound. - base::RunLoop run_loop2; - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop2.QuitClosure())); - run_loop2.Run(); - EXPECT_TRUE(called); -} - -class IntegerAccessorImpl : public sample::IntegerAccessor { - public: - IntegerAccessorImpl() {} - ~IntegerAccessorImpl() override {} - - private: - // sample::IntegerAccessor implementation. - void GetInteger(const GetIntegerCallback& callback) override { - callback.Run(1, sample::Enum::VALUE); - } - void SetInteger(int64_t data, sample::Enum type) override {} - - DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl); -}; - -TEST_F(BindingTest, SetInterfacePtrVersion) { - IntegerAccessorImpl impl; - sample::IntegerAccessorPtr ptr; - Binding<sample::IntegerAccessor> binding(&impl, &ptr); - EXPECT_EQ(3u, ptr.version()); -} - -TEST_F(BindingTest, PauseResume) { - bool called = false; - base::RunLoop run_loop; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - binding.PauseIncomingMethodCallProcessing(); - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, - run_loop.QuitClosure())); - EXPECT_FALSE(called); - base::RunLoop().RunUntilIdle(); - // Frobinate() should not be called as the binding is paused. - EXPECT_FALSE(called); - - // Resume the binding, which should trigger processing. - binding.ResumeIncomingMethodCallProcessing(); - run_loop.Run(); - EXPECT_TRUE(called); -} - -// Verifies the connection error handler is not run while a binding is paused. -TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { - bool called = false; - base::RunLoop run_loop; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - binding.set_connection_error_handler( - SetFlagAndRunClosure(&called, run_loop.QuitClosure())); - binding.PauseIncomingMethodCallProcessing(); - - ptr.reset(); - base::RunLoop().RunUntilIdle(); - // The connection error handle should not be called as the binding is paused. - EXPECT_FALSE(called); - - // Resume the binding, which should trigger the error handler. - binding.ResumeIncomingMethodCallProcessing(); - run_loop.Run(); - EXPECT_TRUE(called); -} - -class PingServiceImpl : public test::PingService { - public: - PingServiceImpl() {} - ~PingServiceImpl() override {} - - // test::PingService: - void Ping(const PingCallback& callback) override { - if (!ping_handler_.is_null()) - ping_handler_.Run(); - callback.Run(); - } - - void set_ping_handler(const base::Closure& handler) { - ping_handler_ = handler; - } - - private: - base::Closure ping_handler_; - - DISALLOW_COPY_AND_ASSIGN(PingServiceImpl); -}; - -class CallbackFilter : public MessageReceiver { - public: - explicit CallbackFilter(const base::Closure& callback) - : callback_(callback) {} - ~CallbackFilter() override {} - - static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) { - return base::MakeUnique<CallbackFilter>(callback); - } - - // MessageReceiver: - bool Accept(Message* message) override { - callback_.Run(); - return true; - } - - private: - const base::Closure callback_; -}; - -// Verifies that message filters are notified in the order they were added and -// are always notified before a message is dispatched. -TEST_F(BindingTest, MessageFilter) { - test::PingServicePtr ptr; - PingServiceImpl impl; - mojo::Binding<test::PingService> binding(&impl, MakeRequest(&ptr)); - - int status = 0; - auto handler_helper = [] (int* status, int expected_status, int new_status) { - EXPECT_EQ(expected_status, *status); - *status = new_status; - }; - auto create_handler = [&] (int expected_status, int new_status) { - return base::Bind(handler_helper, &status, expected_status, new_status); - }; - - binding.AddFilter(CallbackFilter::Wrap(create_handler(0, 1))); - binding.AddFilter(CallbackFilter::Wrap(create_handler(1, 2))); - impl.set_ping_handler(create_handler(2, 3)); - - for (int i = 0; i < 10; ++i) { - status = 0; - base::RunLoop loop; - ptr->Ping(loop.QuitClosure()); - loop.Run(); - EXPECT_EQ(3, status); - } -} - -void Fail() { - FAIL() << "Unexpected connection error"; -} - -TEST_F(BindingTest, FlushForTesting) { - bool called = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - binding.set_connection_error_handler(base::Bind(&Fail)); - - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called)); - EXPECT_FALSE(called); - // Because the flush is sent from the binding, it only guarantees that the - // request has been received, not the response. The second flush waits for the - // response to be received. - binding.FlushForTesting(); - binding.FlushForTesting(); - EXPECT_TRUE(called); -} - -TEST_F(BindingTest, FlushForTestingWithClosedPeer) { - bool called = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - binding.set_connection_error_handler(SetFlagAndRunClosure(&called)); - ptr.reset(); - - EXPECT_FALSE(called); - binding.FlushForTesting(); - EXPECT_TRUE(called); - binding.FlushForTesting(); -} - -TEST_F(BindingTest, ConnectionErrorWithReason) { - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ServiceImpl impl; - Binding<sample::Service> binding(&impl, std::move(request)); - - base::RunLoop run_loop; - binding.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(1234u, custom_reason); - EXPECT_EQ("hello", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - ptr.ResetWithReason(1234u, "hello"); - - run_loop.Run(); -} - -template <typename T> -struct WeakPtrImplRefTraits { - using PointerType = base::WeakPtr<T>; - - static bool IsNull(const base::WeakPtr<T>& ptr) { return !ptr; } - static T* GetRawPointer(base::WeakPtr<T>* ptr) { return ptr->get(); } -}; - -template <typename T> -using WeakBinding = Binding<T, WeakPtrImplRefTraits<T>>; - -TEST_F(BindingTest, CustomImplPointerType) { - PingServiceImpl impl; - base::WeakPtrFactory<test::PingService> weak_factory(&impl); - - test::PingServicePtr proxy; - WeakBinding<test::PingService> binding(weak_factory.GetWeakPtr(), - MakeRequest(&proxy)); - - { - // Ensure the binding is functioning. - base::RunLoop run_loop; - proxy->Ping(run_loop.QuitClosure()); - run_loop.Run(); - } - - { - // Attempt to dispatch another message after the WeakPtr is invalidated. - base::Closure assert_not_reached = base::Bind([] { NOTREACHED(); }); - impl.set_ping_handler(assert_not_reached); - proxy->Ping(assert_not_reached); - - // The binding will close its end of the pipe which will trigger a - // connection error on |proxy|. - base::RunLoop run_loop; - proxy.set_connection_error_handler(run_loop.QuitClosure()); - weak_factory.InvalidateWeakPtrs(); - run_loop.Run(); - } -} - -// StrongBindingTest ----------------------------------------------------------- - -using StrongBindingTest = BindingTestBase; - -// Tests that destroying a mojo::StrongBinding closes the bound message pipe -// handle but does *not* destroy the implementation object. -TEST_F(StrongBindingTest, DestroyClosesMessagePipe) { - base::RunLoop run_loop; - bool encountered_error = false; - bool was_deleted = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - ptr.set_connection_error_handler( - SetFlagAndRunClosure(&encountered_error, run_loop.QuitClosure())); - bool called = false; - base::RunLoop run_loop2; - - auto binding = MakeStrongBinding(base::MakeUnique<ServiceImpl>(&was_deleted), - std::move(request)); - ptr->Frobinate( - nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called, run_loop2.QuitClosure())); - run_loop2.Run(); - EXPECT_TRUE(called); - EXPECT_FALSE(encountered_error); - binding->Close(); - - // Now that the StrongBinding is closed we should detect an error on the other - // end of the pipe. - run_loop.Run(); - EXPECT_TRUE(encountered_error); - - // Destroying the StrongBinding also destroys the impl. - ASSERT_TRUE(was_deleted); -} - -// Tests the typical case, where the implementation object owns the -// StrongBinding (and should be destroyed on connection error). -TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) { - sample::ServicePtr ptr; - bool was_deleted = false; - // Will delete itself. - base::RunLoop run_loop; - new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), - MakeRequest(&ptr)); - - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(was_deleted); - - ptr.reset(); - EXPECT_FALSE(was_deleted); - run_loop.Run(); - EXPECT_TRUE(was_deleted); -} - -TEST_F(StrongBindingTest, FlushForTesting) { - bool called = false; - bool was_deleted = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - auto binding = MakeStrongBinding(base::MakeUnique<ServiceImpl>(&was_deleted), - std::move(request)); - binding->set_connection_error_handler(base::Bind(&Fail)); - - ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - SetFlagAndRunClosure<int32_t>(&called)); - EXPECT_FALSE(called); - // Because the flush is sent from the binding, it only guarantees that the - // request has been received, not the response. The second flush waits for the - // response to be received. - ASSERT_TRUE(binding); - binding->FlushForTesting(); - ASSERT_TRUE(binding); - binding->FlushForTesting(); - EXPECT_TRUE(called); - EXPECT_FALSE(was_deleted); - ptr.reset(); - ASSERT_TRUE(binding); - binding->set_connection_error_handler(base::Closure()); - binding->FlushForTesting(); - EXPECT_TRUE(was_deleted); -} - -TEST_F(StrongBindingTest, FlushForTestingWithClosedPeer) { - bool called = false; - bool was_deleted = false; - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - auto binding = MakeStrongBinding(base::MakeUnique<ServiceImpl>(&was_deleted), - std::move(request)); - binding->set_connection_error_handler(SetFlagAndRunClosure(&called)); - ptr.reset(); - - EXPECT_FALSE(called); - EXPECT_FALSE(was_deleted); - ASSERT_TRUE(binding); - binding->FlushForTesting(); - EXPECT_TRUE(called); - EXPECT_TRUE(was_deleted); - ASSERT_FALSE(binding); -} - -TEST_F(StrongBindingTest, ConnectionErrorWithReason) { - sample::ServicePtr ptr; - auto request = MakeRequest(&ptr); - auto binding = - MakeStrongBinding(base::MakeUnique<ServiceImpl>(), std::move(request)); - base::RunLoop run_loop; - binding->set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(5678u, custom_reason); - EXPECT_EQ("hello", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - ptr.ResetWithReason(5678u, "hello"); - - run_loop.Run(); -} - -} // namespace -} // mojo diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc deleted file mode 100644 index 65b3c8c..0000000 --- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <utility> - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/test_support/test_support.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -const double kMojoTicksPerSecond = 1000000.0; - -double MojoTicksToSeconds(MojoTimeTicks ticks) { - return ticks / kMojoTicksPerSecond; -} - -class PingServiceImpl : public test::PingService { - public: - PingServiceImpl() {} - ~PingServiceImpl() override {} - - // |PingService| methods: - void Ping(const PingCallback& callback) override; - - private: - DISALLOW_COPY_AND_ASSIGN(PingServiceImpl); -}; - -void PingServiceImpl::Ping(const PingCallback& callback) { - callback.Run(); -} - -class PingPongTest { - public: - explicit PingPongTest(test::PingServicePtr service); - - void Run(unsigned int iterations); - - private: - void OnPingDone(); - - test::PingServicePtr service_; - unsigned int iterations_to_run_; - unsigned int current_iterations_; - - base::Closure quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(PingPongTest); -}; - -PingPongTest::PingPongTest(test::PingServicePtr service) - : service_(std::move(service)) {} - -void PingPongTest::Run(unsigned int iterations) { - iterations_to_run_ = iterations; - current_iterations_ = 0; - - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - service_->Ping(base::Bind(&PingPongTest::OnPingDone, base::Unretained(this))); - run_loop.Run(); -} - -void PingPongTest::OnPingDone() { - current_iterations_++; - if (current_iterations_ >= iterations_to_run_) { - quit_closure_.Run(); - return; - } - - service_->Ping(base::Bind(&PingPongTest::OnPingDone, base::Unretained(this))); -} - -struct BoundPingService { - BoundPingService() : binding(&impl) { binding.Bind(MakeRequest(&service)); } - - PingServiceImpl impl; - test::PingServicePtr service; - Binding<test::PingService> binding; -}; - -class MojoBindingsPerftest : public testing::Test { - public: - MojoBindingsPerftest() {} - - protected: - base::MessageLoop loop_; -}; - -TEST_F(MojoBindingsPerftest, InProcessPingPong) { - test::PingServicePtr service; - PingServiceImpl impl; - Binding<test::PingService> binding(&impl, MakeRequest(&service)); - PingPongTest test(std::move(service)); - - { - const unsigned int kIterations = 100000; - const MojoTimeTicks start_time = MojoGetTimeTicksNow(); - test.Run(kIterations); - const MojoTimeTicks end_time = MojoGetTimeTicksNow(); - test::LogPerfResult( - "InProcessPingPong", "0_Inactive", - kIterations / MojoTicksToSeconds(end_time - start_time), - "pings/second"); - } - - { - const size_t kNumInactiveServices = 1000; - BoundPingService* inactive_services = - new BoundPingService[kNumInactiveServices]; - - const unsigned int kIterations = 10000; - const MojoTimeTicks start_time = MojoGetTimeTicksNow(); - test.Run(kIterations); - const MojoTimeTicks end_time = MojoGetTimeTicksNow(); - test::LogPerfResult( - "InProcessPingPong", "1000_Inactive", - kIterations / MojoTicksToSeconds(end_time - start_time), - "pings/second"); - - delete[] inactive_services; - } -} - -class PingPongPaddle : public MessageReceiverWithResponderStatus { - public: - PingPongPaddle(MessageReceiver* sender) : sender_(sender) {} - - void set_sender(MessageReceiver* sender) { sender_ = sender; } - - bool Accept(Message* message) override { - uint32_t count = message->header()->name; - if (!quit_closure_.is_null()) { - count++; - if (count >= expected_count_) { - end_time_ = base::TimeTicks::Now(); - quit_closure_.Run(); - return true; - } - } - - internal::MessageBuilder builder(count, 0, 8, 0); - bool result = sender_->Accept(builder.message()); - DCHECK(result); - return true; - } - - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) override { - NOTREACHED(); - return true; - } - - base::TimeDelta Serve(uint32_t expected_count) { - base::RunLoop run_loop; - - expected_count_ = expected_count; - quit_closure_ = run_loop.QuitClosure(); - - start_time_ = base::TimeTicks::Now(); - internal::MessageBuilder builder(0, 0, 8, 0); - bool result = sender_->Accept(builder.message()); - DCHECK(result); - - run_loop.Run(); - - return end_time_ - start_time_; - } - - private: - base::TimeTicks start_time_; - base::TimeTicks end_time_; - uint32_t expected_count_ = 0; - MessageReceiver* sender_; - base::Closure quit_closure_; -}; - -TEST_F(MojoBindingsPerftest, MultiplexRouterPingPong) { - MessagePipe pipe; - scoped_refptr<internal::MultiplexRouter> router0( - new internal::MultiplexRouter(std::move(pipe.handle0), - internal::MultiplexRouter::SINGLE_INTERFACE, - true, base::ThreadTaskRunnerHandle::Get())); - scoped_refptr<internal::MultiplexRouter> router1( - new internal::MultiplexRouter( - std::move(pipe.handle1), internal::MultiplexRouter::SINGLE_INTERFACE, - false, base::ThreadTaskRunnerHandle::Get())); - - PingPongPaddle paddle0(nullptr); - PingPongPaddle paddle1(nullptr); - - InterfaceEndpointClient client0( - router0->CreateLocalEndpointHandle(kMasterInterfaceId), &paddle0, nullptr, - false, base::ThreadTaskRunnerHandle::Get(), 0u); - InterfaceEndpointClient client1( - router1->CreateLocalEndpointHandle(kMasterInterfaceId), &paddle1, nullptr, - false, base::ThreadTaskRunnerHandle::Get(), 0u); - - paddle0.set_sender(&client0); - paddle1.set_sender(&client1); - - static const uint32_t kWarmUpIterations = 1000; - static const uint32_t kTestIterations = 1000000; - - paddle0.Serve(kWarmUpIterations); - - base::TimeDelta duration = paddle0.Serve(kTestIterations); - - test::LogPerfResult("MultiplexRouterPingPong", nullptr, - kTestIterations / duration.InSecondsF(), "pings/second"); -} - -class CounterReceiver : public MessageReceiverWithResponderStatus { - public: - bool Accept(Message* message) override { - counter_++; - return true; - } - - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) override { - NOTREACHED(); - return true; - } - - uint32_t counter() const { return counter_; } - - void Reset() { counter_ = 0; } - - private: - uint32_t counter_ = 0; -}; - -TEST_F(MojoBindingsPerftest, MultiplexRouterDispatchCost) { - MessagePipe pipe; - scoped_refptr<internal::MultiplexRouter> router(new internal::MultiplexRouter( - std::move(pipe.handle0), internal::MultiplexRouter::SINGLE_INTERFACE, - true, base::ThreadTaskRunnerHandle::Get())); - CounterReceiver receiver; - InterfaceEndpointClient client( - router->CreateLocalEndpointHandle(kMasterInterfaceId), &receiver, nullptr, - false, base::ThreadTaskRunnerHandle::Get(), 0u); - - static const uint32_t kIterations[] = {1000, 3000000}; - - for (size_t i = 0; i < 2; ++i) { - receiver.Reset(); - base::TimeTicks start_time = base::TimeTicks::Now(); - for (size_t j = 0; j < kIterations[i]; ++j) { - internal::MessageBuilder builder(0, 0, 8, 0); - bool result = - router->SimulateReceivingMessageForTesting(builder.message()); - DCHECK(result); - } - - base::TimeTicks end_time = base::TimeTicks::Now(); - base::TimeDelta duration = end_time - start_time; - CHECK_EQ(kIterations[i], receiver.counter()); - - if (i == 1) { - test::LogPerfResult("MultiplexRouterDispatchCost", nullptr, - kIterations[i] / duration.InSecondsF(), - "times/second"); - } - } -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/blink_typemaps.gni b/mojo/public/cpp/bindings/tests/blink_typemaps.gni deleted file mode 100644 index b71dcf8..0000000 --- a/mojo/public/cpp/bindings/tests/blink_typemaps.gni +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -typemaps = [ - "//mojo/public/cpp/bindings/tests/rect_blink.typemap", - "//mojo/public/cpp/bindings/tests/test_native_types_blink.typemap", -] diff --git a/mojo/public/cpp/bindings/tests/buffer_unittest.cc b/mojo/public/cpp/bindings/tests/buffer_unittest.cc deleted file mode 100644 index d75bdd0..0000000 --- a/mojo/public/cpp/bindings/tests/buffer_unittest.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include <limits> - -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -bool IsZero(void* p_buf, size_t size) { - char* buf = reinterpret_cast<char*>(p_buf); - for (size_t i = 0; i < size; ++i) { - if (buf[i] != 0) - return false; - } - return true; -} - -// Tests that FixedBuffer allocates memory aligned to 8 byte boundaries. -TEST(FixedBufferTest, Alignment) { - internal::FixedBufferForTesting buf(internal::Align(10) * 2); - ASSERT_EQ(buf.size(), 16u * 2); - - void* a = buf.Allocate(10); - ASSERT_TRUE(a); - EXPECT_TRUE(IsZero(a, 10)); - EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(a) % 8); - - void* b = buf.Allocate(10); - ASSERT_TRUE(b); - EXPECT_TRUE(IsZero(b, 10)); - EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(b) % 8); - - // Any more allocations would result in an assert, but we can't test that. -} - -// Tests that FixedBufferForTesting::Leak passes ownership to the caller. -TEST(FixedBufferTest, Leak) { - void* ptr = nullptr; - void* buf_ptr = nullptr; - { - internal::FixedBufferForTesting buf(8); - ASSERT_EQ(8u, buf.size()); - - ptr = buf.Allocate(8); - ASSERT_TRUE(ptr); - buf_ptr = buf.Leak(); - - // The buffer should point to the first element allocated. - // TODO(mpcomplete): Is this a reasonable expectation? - EXPECT_EQ(ptr, buf_ptr); - - // The FixedBufferForTesting should be empty now. - EXPECT_EQ(0u, buf.size()); - EXPECT_FALSE(buf.Leak()); - } - - // Since we called Leak, ptr is still writable after FixedBufferForTesting - // went out of scope. - memset(ptr, 1, 8); - free(buf_ptr); -} - -#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) -TEST(FixedBufferTest, TooBig) { - internal::FixedBufferForTesting buf(24); - - // A little bit too large. - EXPECT_EQ(reinterpret_cast<void*>(0), buf.Allocate(32)); - - // Move the cursor forward. - EXPECT_NE(reinterpret_cast<void*>(0), buf.Allocate(16)); - - // A lot too large. - EXPECT_EQ(reinterpret_cast<void*>(0), - buf.Allocate(std::numeric_limits<size_t>::max() - 1024u)); - - // A lot too large, leading to possible integer overflow. - EXPECT_EQ(reinterpret_cast<void*>(0), - buf.Allocate(std::numeric_limits<size_t>::max() - 8u)); -} -#endif - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/chromium_typemaps.gni b/mojo/public/cpp/bindings/tests/chromium_typemaps.gni deleted file mode 100644 index 1da7cbf..0000000 --- a/mojo/public/cpp/bindings/tests/chromium_typemaps.gni +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -typemaps = [ - "//mojo/public/cpp/bindings/tests/rect_chromium.typemap", - "//mojo/public/cpp/bindings/tests/struct_with_traits.typemap", - "//mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap", -] diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc deleted file mode 100644 index 74ecb7a..0000000 --- a/mojo/public/cpp/bindings/tests/connector_unittest.cc +++ /dev/null @@ -1,599 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/connector.h" - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/tests/message_queue.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -class MessageAccumulator : public MessageReceiver { - public: - MessageAccumulator() {} - explicit MessageAccumulator(const base::Closure& closure) - : closure_(closure) {} - - bool Accept(Message* message) override { - queue_.Push(message); - if (!closure_.is_null()) - base::ResetAndReturn(&closure_).Run(); - return true; - } - - bool IsEmpty() const { return queue_.IsEmpty(); } - - void Pop(Message* message) { queue_.Pop(message); } - - void set_closure(const base::Closure& closure) { closure_ = closure; } - - size_t size() const { return queue_.size(); } - - private: - MessageQueue queue_; - base::Closure closure_; -}; - -class ConnectorDeletingMessageAccumulator : public MessageAccumulator { - public: - ConnectorDeletingMessageAccumulator(Connector** connector) - : connector_(connector) {} - - bool Accept(Message* message) override { - delete *connector_; - *connector_ = nullptr; - return MessageAccumulator::Accept(message); - } - - private: - Connector** connector_; -}; - -class ReentrantMessageAccumulator : public MessageAccumulator { - public: - ReentrantMessageAccumulator(Connector* connector) - : connector_(connector), number_of_calls_(0) {} - - bool Accept(Message* message) override { - if (!MessageAccumulator::Accept(message)) - return false; - number_of_calls_++; - if (number_of_calls_ == 1) { - return connector_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - } - return true; - } - - int number_of_calls() { return number_of_calls_; } - - private: - Connector* connector_; - int number_of_calls_; -}; - -class ConnectorTest : public testing::Test { - public: - ConnectorTest() {} - - void SetUp() override { - CreateMessagePipe(nullptr, &handle0_, &handle1_); - } - - void TearDown() override {} - - void AllocMessage(const char* text, Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(1, 0, payload_size, 0); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - - *message = std::move(*builder.message()); - } - - protected: - ScopedMessagePipeHandle handle0_; - ScopedMessagePipeHandle handle1_; - - private: - base::MessageLoop loop_; -}; - -TEST_F(ConnectorTest, Basic) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - connector0.Accept(&message); - - base::RunLoop run_loop; - MessageAccumulator accumulator(run_loop.QuitClosure()); - connector1.set_incoming_receiver(&accumulator); - - run_loop.Run(); - - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); -} - -TEST_F(ConnectorTest, Basic_Synchronous) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - connector0.Accept(&message); - - MessageAccumulator accumulator; - connector1.set_incoming_receiver(&accumulator); - - connector1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); -} - -TEST_F(ConnectorTest, Basic_EarlyIncomingReceiver) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - base::RunLoop run_loop; - MessageAccumulator accumulator(run_loop.QuitClosure()); - connector1.set_incoming_receiver(&accumulator); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - connector0.Accept(&message); - - run_loop.Run(); - - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); -} - -TEST_F(ConnectorTest, Basic_TwoMessages) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char* kText[] = {"hello", "world"}; - - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - - connector0.Accept(&message); - } - - MessageAccumulator accumulator; - connector1.set_incoming_receiver(&accumulator); - - for (size_t i = 0; i < arraysize(kText); ++i) { - if (accumulator.IsEmpty()) { - base::RunLoop run_loop; - accumulator.set_closure(run_loop.QuitClosure()); - run_loop.Run(); - } - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText[i]), - std::string(reinterpret_cast<const char*>(message_received.payload()))); - } -} - -TEST_F(ConnectorTest, Basic_TwoMessages_Synchronous) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char* kText[] = {"hello", "world"}; - - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - - connector0.Accept(&message); - } - - MessageAccumulator accumulator; - connector1.set_incoming_receiver(&accumulator); - - connector1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText[0]), - std::string(reinterpret_cast<const char*>(message_received.payload()))); - - ASSERT_TRUE(accumulator.IsEmpty()); -} - -TEST_F(ConnectorTest, WriteToClosedPipe) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - // Close the other end of the pipe. - handle1_.reset(); - - // Not observed yet because we haven't spun the message loop yet. - EXPECT_FALSE(connector0.encountered_error()); - - // Write failures are not reported. - bool ok = connector0.Accept(&message); - EXPECT_TRUE(ok); - - // Still not observed. - EXPECT_FALSE(connector0.encountered_error()); - - // Spin the message loop, and then we should start observing the closed pipe. - base::RunLoop run_loop; - connector0.set_connection_error_handler(run_loop.QuitClosure()); - run_loop.Run(); - - EXPECT_TRUE(connector0.encountered_error()); -} - -TEST_F(ConnectorTest, MessageWithHandles) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - Message message1; - AllocMessage(kText, &message1); - - MessagePipe pipe; - message1.mutable_handles()->push_back(pipe.handle0.release()); - - connector0.Accept(&message1); - - // The message should have been transferred, releasing the handles. - EXPECT_TRUE(message1.handles()->empty()); - - base::RunLoop run_loop; - MessageAccumulator accumulator(run_loop.QuitClosure()); - connector1.set_incoming_receiver(&accumulator); - - run_loop.Run(); - - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); - ASSERT_EQ(1U, message_received.handles()->size()); - - // Now send a message to the transferred handle and confirm it's sent through - // to the orginal pipe. - // TODO(vtl): Do we need a better way of "downcasting" the handle types? - ScopedMessagePipeHandle smph; - smph.reset(MessagePipeHandle(message_received.handles()->front().value())); - message_received.mutable_handles()->front() = Handle(); - // |smph| now owns this handle. - - Connector connector_received(std::move(smph), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector_original(std::move(pipe.handle1), - Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - Message message2; - AllocMessage(kText, &message2); - - connector_received.Accept(&message2); - base::RunLoop run_loop2; - MessageAccumulator accumulator2(run_loop2.QuitClosure()); - connector_original.set_incoming_receiver(&accumulator2); - run_loop2.Run(); - - ASSERT_FALSE(accumulator2.IsEmpty()); - - accumulator2.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); -} - -TEST_F(ConnectorTest, WaitForIncomingMessageWithError) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - // Close the other end of the pipe. - handle1_.reset(); - ASSERT_FALSE(connector0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE)); -} - -TEST_F(ConnectorTest, WaitForIncomingMessageWithDeletion) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector* connector1 = - new Connector(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - connector0.Accept(&message); - - ConnectorDeletingMessageAccumulator accumulator(&connector1); - connector1->set_incoming_receiver(&accumulator); - - connector1->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - - ASSERT_FALSE(connector1); - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); -} - -TEST_F(ConnectorTest, WaitForIncomingMessageWithReentrancy) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char* kText[] = {"hello", "world"}; - - for (size_t i = 0; i < arraysize(kText); ++i) { - Message message; - AllocMessage(kText[i], &message); - - connector0.Accept(&message); - } - - ReentrantMessageAccumulator accumulator(&connector1); - connector1.set_incoming_receiver(&accumulator); - - for (size_t i = 0; i < arraysize(kText); ++i) { - if (accumulator.IsEmpty()) { - base::RunLoop run_loop; - accumulator.set_closure(run_loop.QuitClosure()); - run_loop.Run(); - } - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText[i]), - std::string(reinterpret_cast<const char*>(message_received.payload()))); - } - - ASSERT_EQ(2, accumulator.number_of_calls()); -} - -void ForwardErrorHandler(bool* called, const base::Closure& callback) { - *called = true; - callback.Run(); -} - -TEST_F(ConnectorTest, RaiseError) { - base::RunLoop run_loop, run_loop2; - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - bool error_handler_called0 = false; - connector0.set_connection_error_handler( - base::Bind(&ForwardErrorHandler, &error_handler_called0, - run_loop.QuitClosure())); - - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - bool error_handler_called1 = false; - connector1.set_connection_error_handler( - base::Bind(&ForwardErrorHandler, &error_handler_called1, - run_loop2.QuitClosure())); - - const char kText[] = "hello world"; - - Message message; - AllocMessage(kText, &message); - - connector0.Accept(&message); - connector0.RaiseError(); - - base::RunLoop run_loop3; - MessageAccumulator accumulator(run_loop3.QuitClosure()); - connector1.set_incoming_receiver(&accumulator); - - run_loop3.Run(); - - // Messages sent prior to RaiseError() still arrive at the other end. - ASSERT_FALSE(accumulator.IsEmpty()); - - Message message_received; - accumulator.Pop(&message_received); - - EXPECT_EQ( - std::string(kText), - std::string(reinterpret_cast<const char*>(message_received.payload()))); - - run_loop.Run(); - run_loop2.Run(); - - // Connection error handler is called at both sides. - EXPECT_TRUE(error_handler_called0); - EXPECT_TRUE(error_handler_called1); - - // The error flag is set at both sides. - EXPECT_TRUE(connector0.encountered_error()); - EXPECT_TRUE(connector1.encountered_error()); - - // The message pipe handle is valid at both sides. - EXPECT_TRUE(connector0.is_valid()); - EXPECT_TRUE(connector1.is_valid()); -} - -void PauseConnectorAndRunClosure(Connector* connector, - const base::Closure& closure) { - connector->PauseIncomingMethodCallProcessing(); - closure.Run(); -} - -TEST_F(ConnectorTest, PauseWithQueuedMessages) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - // Queue up two messages. - Message message; - AllocMessage(kText, &message); - connector0.Accept(&message); - AllocMessage(kText, &message); - connector0.Accept(&message); - - base::RunLoop run_loop; - // Configure the accumulator such that it pauses after the first message is - // received. - MessageAccumulator accumulator( - base::Bind(&PauseConnectorAndRunClosure, &connector1, - run_loop.QuitClosure())); - connector1.set_incoming_receiver(&accumulator); - - run_loop.Run(); - - // As we paused after the first message we should only have gotten one - // message. - ASSERT_EQ(1u, accumulator.size()); -} - -void AccumulateWithNestedLoop(MessageAccumulator* accumulator, - const base::Closure& closure) { - base::RunLoop nested_run_loop; - base::MessageLoop::ScopedNestableTaskAllower allow( - base::MessageLoop::current()); - accumulator->set_closure(nested_run_loop.QuitClosure()); - nested_run_loop.Run(); - closure.Run(); -} - -TEST_F(ConnectorTest, ProcessWhenNested) { - Connector connector0(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - Connector connector1(std::move(handle1_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()); - - const char kText[] = "hello world"; - - // Queue up two messages. - Message message; - AllocMessage(kText, &message); - connector0.Accept(&message); - AllocMessage(kText, &message); - connector0.Accept(&message); - - base::RunLoop run_loop; - MessageAccumulator accumulator; - // When the accumulator gets the first message it spins a nested message - // loop. The loop is quit when another message is received. - accumulator.set_closure(base::Bind(&AccumulateWithNestedLoop, &accumulator, - run_loop.QuitClosure())); - connector1.set_incoming_receiver(&accumulator); - - run_loop.Run(); - - ASSERT_EQ(2u, accumulator.size()); -} - -TEST_F(ConnectorTest, DestroyOnDifferentThreadAfterClose) { - std::unique_ptr<Connector> connector( - new Connector(std::move(handle0_), Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get())); - - connector->CloseMessagePipe(); - - base::Thread another_thread("ThreadForDestroyingConnector"); - another_thread.Start(); - - base::RunLoop run_loop; - another_thread.task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind( - [](std::unique_ptr<Connector> connector) { connector.reset(); }, - base::Passed(std::move(connector))), - run_loop.QuitClosure()); - - run_loop.Run(); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/constant_unittest.cc b/mojo/public/cpp/bindings/tests/constant_unittest.cc deleted file mode 100644 index caa6464..0000000 --- a/mojo/public/cpp/bindings/tests/constant_unittest.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <cmath> - -#include "base/strings/string_piece.h" -#include "mojo/public/interfaces/bindings/tests/test_constants.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { - -TEST(ConstantTest, GlobalConstants) { - // Compile-time constants. - static_assert(kBoolValue == true, ""); - static_assert(kInt8Value == -2, ""); - static_assert(kUint8Value == 128U, ""); - static_assert(kInt16Value == -233, ""); - static_assert(kUint16Value == 44204U, ""); - static_assert(kInt32Value == -44204, ""); - static_assert(kUint32Value == 4294967295U, ""); - static_assert(kInt64Value == -9223372036854775807, ""); - static_assert(kUint64Value == 9999999999999999999ULL, ""); - static_assert(kDoubleValue == 3.14159, ""); - static_assert(kFloatValue == 2.71828f, ""); - - EXPECT_EQ(base::StringPiece(kStringValue), "test string contents"); - EXPECT_TRUE(std::isnan(kDoubleNaN)); - EXPECT_TRUE(std::isinf(kDoubleInfinity)); - EXPECT_TRUE(std::isinf(kDoubleNegativeInfinity)); - EXPECT_NE(kDoubleInfinity, kDoubleNegativeInfinity); - EXPECT_TRUE(std::isnan(kFloatNaN)); - EXPECT_TRUE(std::isinf(kFloatInfinity)); - EXPECT_TRUE(std::isinf(kFloatNegativeInfinity)); - EXPECT_NE(kFloatInfinity, kFloatNegativeInfinity); -} - -TEST(ConstantTest, StructConstants) { - // Compile-time constants. - static_assert(StructWithConstants::kInt8Value == 5U, ""); - static_assert(StructWithConstants::kFloatValue == 765.432f, ""); - - EXPECT_EQ(base::StringPiece(StructWithConstants::kStringValue), - "struct test string contents"); -} - -TEST(ConstantTest, InterfaceConstants) { - // Compile-time constants. - static_assert(InterfaceWithConstants::kUint32Value == 20100722, ""); - static_assert(InterfaceWithConstants::kDoubleValue == 12.34567, ""); - - EXPECT_EQ(base::StringPiece(InterfaceWithConstants::kStringValue), - "interface test string contents"); - EXPECT_EQ(base::StringPiece(InterfaceWithConstants::Name_), - "mojo::test::InterfaceWithConstants"); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/container_test_util.cc b/mojo/public/cpp/bindings/tests/container_test_util.cc deleted file mode 100644 index a53d351..0000000 --- a/mojo/public/cpp/bindings/tests/container_test_util.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include "mojo/public/cpp/bindings/tests/container_test_util.h" - -namespace mojo { - -size_t CopyableType::num_instances_ = 0; -size_t MoveOnlyType::num_instances_ = 0; - -CopyableType::CopyableType() : copied_(false), ptr_(this) { - num_instances_++; -} - -CopyableType::CopyableType(const CopyableType& other) - : copied_(true), ptr_(other.ptr()) { - num_instances_++; -} - -CopyableType& CopyableType::operator=(const CopyableType& other) { - copied_ = true; - ptr_ = other.ptr(); - return *this; -} - -CopyableType::~CopyableType() { - num_instances_--; -} - -MoveOnlyType::MoveOnlyType() : moved_(false), ptr_(this) { - num_instances_++; -} - -MoveOnlyType::MoveOnlyType(MoveOnlyType&& other) - : moved_(true), ptr_(other.ptr()) { - num_instances_++; -} - -MoveOnlyType& MoveOnlyType::operator=(MoveOnlyType&& other) { - moved_ = true; - ptr_ = other.ptr(); - return *this; -} - -MoveOnlyType::~MoveOnlyType() { - num_instances_--; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/container_test_util.h b/mojo/public/cpp/bindings/tests/container_test_util.h deleted file mode 100644 index f709c15..0000000 --- a/mojo/public/cpp/bindings/tests/container_test_util.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_CONTAINER_TEST_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_CONTAINER_TEST_UTIL_H_ - -#include <stddef.h> - -#include "base/macros.h" - -namespace mojo { - -class CopyableType { - public: - CopyableType(); - CopyableType(const CopyableType& other); - CopyableType& operator=(const CopyableType& other); - ~CopyableType(); - - bool copied() const { return copied_; } - static size_t num_instances() { return num_instances_; } - CopyableType* ptr() const { return ptr_; } - void ResetCopied() { copied_ = false; } - - private: - bool copied_; - static size_t num_instances_; - CopyableType* ptr_; -}; - -class MoveOnlyType { - public: - typedef MoveOnlyType Data_; - MoveOnlyType(); - MoveOnlyType(MoveOnlyType&& other); - MoveOnlyType& operator=(MoveOnlyType&& other); - ~MoveOnlyType(); - - bool moved() const { return moved_; } - static size_t num_instances() { return num_instances_; } - MoveOnlyType* ptr() const { return ptr_; } - void ResetMoved() { moved_ = false; } - - private: - bool moved_; - static size_t num_instances_; - MoveOnlyType* ptr_; - - DISALLOW_COPY_AND_ASSIGN(MoveOnlyType); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_CONTAINER_TEST_UTIL_H_ diff --git a/mojo/public/cpp/bindings/tests/data_view_unittest.cc b/mojo/public/cpp/bindings/tests/data_view_unittest.cc deleted file mode 100644 index 0ebfda5..0000000 --- a/mojo/public/cpp/bindings/tests/data_view_unittest.cc +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> -#include <string> -#include <unordered_map> -#include <vector> - -#include "base/message_loop/message_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/interfaces/bindings/tests/test_data_view.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace data_view { -namespace { - -class DataViewTest : public testing::Test { - private: - base::MessageLoop message_loop_; -}; - -struct DataViewHolder { - std::unique_ptr<TestStructDataView> data_view; - std::unique_ptr<mojo::internal::FixedBufferForTesting> buf; - mojo::internal::SerializationContext context; -}; - -std::unique_ptr<DataViewHolder> SerializeTestStruct(TestStructPtr input) { - std::unique_ptr<DataViewHolder> result(new DataViewHolder); - - size_t size = mojo::internal::PrepareToSerialize<TestStructDataView>( - input, &result->context); - - result->buf.reset(new mojo::internal::FixedBufferForTesting(size)); - internal::TestStruct_Data* data = nullptr; - mojo::internal::Serialize<TestStructDataView>(input, result->buf.get(), &data, - &result->context); - - result->data_view.reset(new TestStructDataView(data, &result->context)); - return result; -} - -class TestInterfaceImpl : public TestInterface { - public: - explicit TestInterfaceImpl(TestInterfaceRequest request) - : binding_(this, std::move(request)) {} - ~TestInterfaceImpl() override {} - - // TestInterface implementation: - void Echo(int32_t value, const EchoCallback& callback) override { - callback.Run(value); - } - - private: - Binding<TestInterface> binding_; -}; - -} // namespace - -TEST_F(DataViewTest, String) { - TestStructPtr obj(TestStruct::New()); - obj->f_string = "hello"; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - StringDataView string_data_view; - data_view.GetFStringDataView(&string_data_view); - - ASSERT_FALSE(string_data_view.is_null()); - EXPECT_EQ(std::string("hello"), - std::string(string_data_view.storage(), string_data_view.size())); -} - -TEST_F(DataViewTest, NestedStruct) { - TestStructPtr obj(TestStruct::New()); - obj->f_struct = NestedStruct::New(); - obj->f_struct->f_int32 = 42; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - NestedStructDataView struct_data_view; - data_view.GetFStructDataView(&struct_data_view); - - ASSERT_FALSE(struct_data_view.is_null()); - EXPECT_EQ(42, struct_data_view.f_int32()); -} - -TEST_F(DataViewTest, NativeStruct) { - TestStructPtr obj(TestStruct::New()); - obj->f_native_struct = NativeStruct::New(); - obj->f_native_struct->data = std::vector<uint8_t>({3, 2, 1}); - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - NativeStructDataView struct_data_view; - data_view.GetFNativeStructDataView(&struct_data_view); - - ASSERT_FALSE(struct_data_view.is_null()); - ASSERT_EQ(3u, struct_data_view.size()); - EXPECT_EQ(3, struct_data_view[0]); - EXPECT_EQ(2, struct_data_view[1]); - EXPECT_EQ(1, struct_data_view[2]); - EXPECT_EQ(3, *struct_data_view.data()); -} - -TEST_F(DataViewTest, BoolArray) { - TestStructPtr obj(TestStruct::New()); - obj->f_bool_array = {true, false}; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<bool> array_data_view; - data_view.GetFBoolArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(2u, array_data_view.size()); - EXPECT_TRUE(array_data_view[0]); - EXPECT_FALSE(array_data_view[1]); -} - -TEST_F(DataViewTest, IntegerArray) { - TestStructPtr obj(TestStruct::New()); - obj->f_int32_array = {1024, 128}; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<int32_t> array_data_view; - data_view.GetFInt32ArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(2u, array_data_view.size()); - EXPECT_EQ(1024, array_data_view[0]); - EXPECT_EQ(128, array_data_view[1]); - EXPECT_EQ(1024, *array_data_view.data()); -} - -TEST_F(DataViewTest, EnumArray) { - TestStructPtr obj(TestStruct::New()); - obj->f_enum_array = {TestEnum::VALUE_1, TestEnum::VALUE_0}; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<TestEnum> array_data_view; - data_view.GetFEnumArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(2u, array_data_view.size()); - EXPECT_EQ(TestEnum::VALUE_1, array_data_view[0]); - EXPECT_EQ(TestEnum::VALUE_0, array_data_view[1]); - EXPECT_EQ(TestEnum::VALUE_0, *(array_data_view.data() + 1)); - - TestEnum output; - ASSERT_TRUE(array_data_view.Read(0, &output)); - EXPECT_EQ(TestEnum::VALUE_1, output); -} - -TEST_F(DataViewTest, InterfaceArray) { - TestInterfacePtr ptr; - TestInterfaceImpl impl(MakeRequest(&ptr)); - - TestStructPtr obj(TestStruct::New()); - obj->f_interface_array.push_back(std::move(ptr)); - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<TestInterfacePtrDataView> array_data_view; - data_view.GetFInterfaceArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(1u, array_data_view.size()); - - TestInterfacePtr ptr2 = array_data_view.Take<TestInterfacePtr>(0); - ASSERT_TRUE(ptr2); - int32_t result = 0; - ASSERT_TRUE(ptr2->Echo(42, &result)); - EXPECT_EQ(42, result); -} - -TEST_F(DataViewTest, NestedArray) { - TestStructPtr obj(TestStruct::New()); - obj->f_nested_array = {{3, 4}, {2}}; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<ArrayDataView<int32_t>> array_data_view; - data_view.GetFNestedArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(2u, array_data_view.size()); - - ArrayDataView<int32_t> nested_array_data_view; - array_data_view.GetDataView(0, &nested_array_data_view); - ASSERT_FALSE(nested_array_data_view.is_null()); - ASSERT_EQ(2u, nested_array_data_view.size()); - EXPECT_EQ(4, nested_array_data_view[1]); - - std::vector<int32_t> vec; - ASSERT_TRUE(array_data_view.Read(1, &vec)); - ASSERT_EQ(1u, vec.size()); - EXPECT_EQ(2, vec[0]); -} - -TEST_F(DataViewTest, StructArray) { - NestedStructPtr nested_struct(NestedStruct::New()); - nested_struct->f_int32 = 42; - - TestStructPtr obj(TestStruct::New()); - obj->f_struct_array.push_back(std::move(nested_struct)); - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<NestedStructDataView> array_data_view; - data_view.GetFStructArrayDataView(&array_data_view); - - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(1u, array_data_view.size()); - - NestedStructDataView struct_data_view; - array_data_view.GetDataView(0, &struct_data_view); - ASSERT_FALSE(struct_data_view.is_null()); - EXPECT_EQ(42, struct_data_view.f_int32()); - - NestedStructPtr nested_struct2; - ASSERT_TRUE(array_data_view.Read(0, &nested_struct2)); - ASSERT_TRUE(nested_struct2); - EXPECT_EQ(42, nested_struct2->f_int32); -} - -TEST_F(DataViewTest, Map) { - TestStructPtr obj(TestStruct::New()); - obj->f_map["1"] = 1; - obj->f_map["2"] = 2; - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - MapDataView<StringDataView, int32_t> map_data_view; - data_view.GetFMapDataView(&map_data_view); - - ASSERT_FALSE(map_data_view.is_null()); - ASSERT_EQ(2u, map_data_view.size()); - - ASSERT_FALSE(map_data_view.keys().is_null()); - ASSERT_EQ(2u, map_data_view.keys().size()); - - ASSERT_FALSE(map_data_view.values().is_null()); - ASSERT_EQ(2u, map_data_view.values().size()); - - std::vector<std::string> keys; - ASSERT_TRUE(map_data_view.ReadKeys(&keys)); - std::vector<int32_t> values; - ASSERT_TRUE(map_data_view.ReadValues(&values)); - - std::unordered_map<std::string, int32_t> map; - for (size_t i = 0; i < 2; ++i) - map[keys[i]] = values[i]; - - EXPECT_EQ(1, map["1"]); - EXPECT_EQ(2, map["2"]); -} - -TEST_F(DataViewTest, UnionArray) { - TestUnionPtr union_ptr(TestUnion::New()); - union_ptr->set_f_int32(1024); - - TestStructPtr obj(TestStruct::New()); - obj->f_union_array.push_back(std::move(union_ptr)); - - auto data_view_holder = SerializeTestStruct(std::move(obj)); - auto& data_view = *data_view_holder->data_view; - - ArrayDataView<TestUnionDataView> array_data_view; - data_view.GetFUnionArrayDataView(&array_data_view); - ASSERT_FALSE(array_data_view.is_null()); - ASSERT_EQ(1u, array_data_view.size()); - - TestUnionDataView union_data_view; - array_data_view.GetDataView(0, &union_data_view); - ASSERT_FALSE(union_data_view.is_null()); - - TestUnionPtr union_ptr2; - ASSERT_TRUE(array_data_view.Read(0, &union_ptr2)); - ASSERT_TRUE(union_ptr2->is_f_int32()); - EXPECT_EQ(1024, union_ptr2->get_f_int32()); -} - -} // namespace data_view -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/e2e_perftest.cc b/mojo/public/cpp/bindings/tests/e2e_perftest.cc deleted file mode 100644 index bc69e0f..0000000 --- a/mojo/public/cpp/bindings/tests/e2e_perftest.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "base/test/perf_time_logger.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -class EchoServiceImpl : public test::EchoService { - public: - explicit EchoServiceImpl(const base::Closure& quit_closure); - ~EchoServiceImpl() override; - - // |EchoService| methods: - void Echo(const std::string& test_data, - const EchoCallback& callback) override; - - private: - const base::Closure quit_closure_; -}; - -EchoServiceImpl::EchoServiceImpl(const base::Closure& quit_closure) - : quit_closure_(quit_closure) {} - -EchoServiceImpl::~EchoServiceImpl() { - quit_closure_.Run(); -} - -void EchoServiceImpl::Echo(const std::string& test_data, - const EchoCallback& callback) { - callback.Run(test_data); -} - -class PingPongTest { - public: - explicit PingPongTest(test::EchoServicePtr service); - - void RunTest(int iterations, int batch_size, int message_size); - - private: - void DoPing(); - void OnPingDone(const std::string& reply); - - test::EchoServicePtr service_; - const base::Callback<void(const std::string&)> ping_done_callback_; - - int iterations_; - int batch_size_; - std::string message_; - - int current_iterations_; - int calls_outstanding_; - - base::Closure quit_closure_; -}; - -PingPongTest::PingPongTest(test::EchoServicePtr service) - : service_(std::move(service)), - ping_done_callback_( - base::Bind(&PingPongTest::OnPingDone, base::Unretained(this))) {} - -void PingPongTest::RunTest(int iterations, int batch_size, int message_size) { - iterations_ = iterations; - batch_size_ = batch_size; - message_ = std::string(message_size, 'a'); - current_iterations_ = 0; - calls_outstanding_ = 0; - - base::MessageLoop::current()->SetNestableTasksAllowed(true); - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&PingPongTest::DoPing, base::Unretained(this))); - run_loop.Run(); -} - -void PingPongTest::DoPing() { - DCHECK_EQ(0, calls_outstanding_); - current_iterations_++; - if (current_iterations_ > iterations_) { - quit_closure_.Run(); - return; - } - - calls_outstanding_ = batch_size_; - for (int i = 0; i < batch_size_; i++) { - service_->Echo(message_, ping_done_callback_); - } -} - -void PingPongTest::OnPingDone(const std::string& reply) { - DCHECK_GT(calls_outstanding_, 0); - calls_outstanding_--; - - if (!calls_outstanding_) - DoPing(); -} - -class MojoE2EPerftest : public edk::test::MojoTestBase { - public: - void RunTestOnTaskRunner(base::TaskRunner* runner, - MojoHandle client_mp, - const std::string& test_name) { - if (runner == base::ThreadTaskRunnerHandle::Get().get()) { - RunTests(client_mp, test_name); - } else { - base::RunLoop run_loop; - runner->PostTaskAndReply( - FROM_HERE, base::Bind(&MojoE2EPerftest::RunTests, - base::Unretained(this), client_mp, test_name), - run_loop.QuitClosure()); - run_loop.Run(); - } - } - - protected: - base::MessageLoop message_loop_; - - private: - void RunTests(MojoHandle client_mp, const std::string& test_name) { - const int kMessages = 10000; - const int kBatchSizes[] = {1, 10, 100}; - const int kMessageSizes[] = {8, 64, 512, 4096, 65536}; - - test::EchoServicePtr service; - service.Bind(InterfacePtrInfo<test::EchoService>( - ScopedMessagePipeHandle(MessagePipeHandle(client_mp)), - service.version())); - PingPongTest test(std::move(service)); - - for (int batch_size : kBatchSizes) { - for (int message_size : kMessageSizes) { - int num_messages = kMessages; - if (message_size == 65536) - num_messages /= 10; - std::string sub_test_name = base::StringPrintf( - "%s/%dx%d/%dbytes", test_name.c_str(), num_messages / batch_size, - batch_size, message_size); - base::PerfTimeLogger timer(sub_test_name.c_str()); - test.RunTest(num_messages / batch_size, batch_size, message_size); - } - } - } -}; - -void CreateAndRunService(InterfaceRequest<test::EchoService> request, - const base::Closure& cb) { - MakeStrongBinding(base::MakeUnique<EchoServiceImpl>(cb), std::move(request)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingService, MojoE2EPerftest, mp) { - MojoHandle service_mp; - EXPECT_EQ("hello", ReadMessageWithHandles(mp, &service_mp, 1)); - - InterfaceRequest<test::EchoService> request; - request.Bind(ScopedMessagePipeHandle(MessagePipeHandle(service_mp))); - base::RunLoop run_loop; - edk::GetIOTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&CreateAndRunService, base::Passed(&request), - base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), - message_loop_.task_runner(), FROM_HERE, - run_loop.QuitClosure()))); - run_loop.Run(); -} - -TEST_F(MojoE2EPerftest, MultiProcessEchoMainThread) { - RUN_CHILD_ON_PIPE(PingService, mp) - MojoHandle client_mp, service_mp; - CreateMessagePipe(&client_mp, &service_mp); - WriteMessageWithHandles(mp, "hello", &service_mp, 1); - RunTestOnTaskRunner(message_loop_.task_runner().get(), client_mp, - "MultiProcessEchoMainThread"); - END_CHILD() -} - -TEST_F(MojoE2EPerftest, MultiProcessEchoIoThread) { - RUN_CHILD_ON_PIPE(PingService, mp) - MojoHandle client_mp, service_mp; - CreateMessagePipe(&client_mp, &service_mp); - WriteMessageWithHandles(mp, "hello", &service_mp, 1); - RunTestOnTaskRunner(edk::GetIOTaskRunner().get(), client_mp, - "MultiProcessEchoIoThread"); - END_CHILD() -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/equals_unittest.cc b/mojo/public/cpp/bindings/tests/equals_unittest.cc deleted file mode 100644 index 6483baf..0000000 --- a/mojo/public/cpp/bindings/tests/equals_unittest.cc +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/message_loop/message_loop.h" -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { - -namespace { - -RectPtr CreateRect() { - return Rect::New(1, 2, 3, 4); -} - -using EqualsTest = testing::Test; - -} // namespace - -TEST_F(EqualsTest, NullStruct) { - RectPtr r1; - RectPtr r2; - EXPECT_TRUE(r1.Equals(r2)); - EXPECT_TRUE(r2.Equals(r1)); - - r1 = CreateRect(); - EXPECT_FALSE(r1.Equals(r2)); - EXPECT_FALSE(r2.Equals(r1)); -} - -TEST_F(EqualsTest, Struct) { - RectPtr r1(CreateRect()); - RectPtr r2(r1.Clone()); - EXPECT_TRUE(r1.Equals(r2)); - r2->y = 1; - EXPECT_FALSE(r1.Equals(r2)); - r2.reset(); - EXPECT_FALSE(r1.Equals(r2)); -} - -TEST_F(EqualsTest, StructNested) { - RectPairPtr p1(RectPair::New(CreateRect(), CreateRect())); - RectPairPtr p2(p1.Clone()); - EXPECT_TRUE(p1.Equals(p2)); - p2->second->width = 0; - EXPECT_FALSE(p1.Equals(p2)); - p2->second.reset(); - EXPECT_FALSE(p1.Equals(p2)); -} - -TEST_F(EqualsTest, Array) { - std::vector<RectPtr> rects; - rects.push_back(CreateRect()); - NamedRegionPtr n1(NamedRegion::New(std::string("n1"), std::move(rects))); - NamedRegionPtr n2(n1.Clone()); - EXPECT_TRUE(n1.Equals(n2)); - - n2->rects = base::nullopt; - EXPECT_FALSE(n1.Equals(n2)); - n2->rects.emplace(); - EXPECT_FALSE(n1.Equals(n2)); - - n2->rects->push_back(CreateRect()); - n2->rects->push_back(CreateRect()); - EXPECT_FALSE(n1.Equals(n2)); - - n2->rects->resize(1); - (*n2->rects)[0]->width = 0; - EXPECT_FALSE(n1.Equals(n2)); - - (*n2->rects)[0] = CreateRect(); - EXPECT_TRUE(n1.Equals(n2)); -} - -TEST_F(EqualsTest, InterfacePtr) { - base::MessageLoop message_loop; - - SomeInterfacePtr inf1; - SomeInterfacePtr inf2; - - EXPECT_TRUE(inf1.Equals(inf1)); - EXPECT_TRUE(inf1.Equals(inf2)); - - auto inf1_request = MakeRequest(&inf1); - ALLOW_UNUSED_LOCAL(inf1_request); - - EXPECT_TRUE(inf1.Equals(inf1)); - EXPECT_FALSE(inf1.Equals(inf2)); - - auto inf2_request = MakeRequest(&inf2); - ALLOW_UNUSED_LOCAL(inf2_request); - - EXPECT_FALSE(inf1.Equals(inf2)); -} - -TEST_F(EqualsTest, InterfaceRequest) { - base::MessageLoop message_loop; - - InterfaceRequest<SomeInterface> req1; - InterfaceRequest<SomeInterface> req2; - - EXPECT_TRUE(req1.Equals(req1)); - EXPECT_TRUE(req1.Equals(req2)); - - SomeInterfacePtr inf1; - req1 = MakeRequest(&inf1); - - EXPECT_TRUE(req1.Equals(req1)); - EXPECT_FALSE(req1.Equals(req2)); - - SomeInterfacePtr inf2; - req2 = MakeRequest(&inf2); - - EXPECT_FALSE(req1.Equals(req2)); -} - -} // test -} // mojo diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc deleted file mode 100644 index ef977af..0000000 --- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc +++ /dev/null @@ -1,356 +0,0 @@ -// 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. - -#include <stdint.h> -#include <utility> - -#include "base/memory/ptr_util.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/strong_binding.h" -#include "mojo/public/cpp/system/wait.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "mojo/public/interfaces/bindings/tests/sample_factory.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -const char kText1[] = "hello"; -const char kText2[] = "world"; - -void RecordString(std::string* storage, - const base::Closure& closure, - const std::string& str) { - *storage = str; - closure.Run(); -} - -base::Callback<void(const std::string&)> MakeStringRecorder( - std::string* storage, - const base::Closure& closure) { - return base::Bind(&RecordString, storage, closure); -} - -class ImportedInterfaceImpl : public imported::ImportedInterface { - public: - ImportedInterfaceImpl( - InterfaceRequest<imported::ImportedInterface> request, - const base::Closure& closure) - : binding_(this, std::move(request)), closure_(closure) {} - - void DoSomething() override { - do_something_count_++; - closure_.Run(); - } - - static int do_something_count() { return do_something_count_; } - - private: - static int do_something_count_; - Binding<ImportedInterface> binding_; - base::Closure closure_; -}; -int ImportedInterfaceImpl::do_something_count_ = 0; - -class SampleNamedObjectImpl : public sample::NamedObject { - public: - SampleNamedObjectImpl() {} - - void SetName(const std::string& name) override { name_ = name; } - - void GetName(const GetNameCallback& callback) override { - callback.Run(name_); - } - - private: - std::string name_; -}; - -class SampleFactoryImpl : public sample::Factory { - public: - explicit SampleFactoryImpl(InterfaceRequest<sample::Factory> request) - : binding_(this, std::move(request)) {} - - void DoStuff(sample::RequestPtr request, - ScopedMessagePipeHandle pipe, - const DoStuffCallback& callback) override { - std::string text1; - if (pipe.is_valid()) - EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1)); - - std::string text2; - if (request->pipe.is_valid()) { - EXPECT_TRUE(ReadTextMessage(request->pipe.get(), &text2)); - - // Ensure that simply accessing request->pipe does not close it. - EXPECT_TRUE(request->pipe.is_valid()); - } - - ScopedMessagePipeHandle pipe0; - if (!text2.empty()) { - CreateMessagePipe(nullptr, &pipe0, &pipe1_); - EXPECT_TRUE(WriteTextMessage(pipe1_.get(), text2)); - } - - sample::ResponsePtr response(sample::Response::New(2, std::move(pipe0))); - callback.Run(std::move(response), text1); - - if (request->obj) - request->obj->DoSomething(); - } - - void DoStuff2(ScopedDataPipeConsumerHandle pipe, - const DoStuff2Callback& callback) override { - // Read the data from the pipe, writing the response (as a string) to - // DidStuff2(). - ASSERT_TRUE(pipe.is_valid()); - uint32_t data_size = 0; - - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE, &state)); - ASSERT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); - ASSERT_EQ(MOJO_RESULT_OK, - ReadDataRaw( - pipe.get(), nullptr, &data_size, MOJO_READ_DATA_FLAG_QUERY)); - ASSERT_NE(0, static_cast<int>(data_size)); - char data[64]; - ASSERT_LT(static_cast<int>(data_size), 64); - ASSERT_EQ( - MOJO_RESULT_OK, - ReadDataRaw( - pipe.get(), data, &data_size, MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - callback.Run(data); - } - - void CreateNamedObject( - InterfaceRequest<sample::NamedObject> object_request) override { - EXPECT_TRUE(object_request.is_pending()); - MakeStrongBinding(base::MakeUnique<SampleNamedObjectImpl>(), - std::move(object_request)); - } - - // These aren't called or implemented, but exist here to test that the - // methods are generated with the correct argument types for imported - // interfaces. - void RequestImportedInterface( - InterfaceRequest<imported::ImportedInterface> imported, - const RequestImportedInterfaceCallback& callback) override {} - void TakeImportedInterface( - imported::ImportedInterfacePtr imported, - const TakeImportedInterfaceCallback& callback) override {} - - private: - ScopedMessagePipeHandle pipe1_; - Binding<sample::Factory> binding_; -}; - -class HandlePassingTest : public testing::Test { - public: - HandlePassingTest() {} - - void TearDown() override { PumpMessages(); } - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - private: - base::MessageLoop loop_; -}; - -void DoStuff(bool* got_response, - std::string* got_text_reply, - const base::Closure& closure, - sample::ResponsePtr response, - const std::string& text_reply) { - *got_text_reply = text_reply; - - if (response->pipe.is_valid()) { - std::string text2; - EXPECT_TRUE(ReadTextMessage(response->pipe.get(), &text2)); - - // Ensure that simply accessing response.pipe does not close it. - EXPECT_TRUE(response->pipe.is_valid()); - - EXPECT_EQ(std::string(kText2), text2); - - // Do some more tests of handle passing: - ScopedMessagePipeHandle p = std::move(response->pipe); - EXPECT_TRUE(p.is_valid()); - EXPECT_FALSE(response->pipe.is_valid()); - } - - *got_response = true; - closure.Run(); -} - -void DoStuff2(bool* got_response, - std::string* got_text_reply, - const base::Closure& closure, - const std::string& text_reply) { - *got_response = true; - *got_text_reply = text_reply; - closure.Run(); -} - -TEST_F(HandlePassingTest, Basic) { - sample::FactoryPtr factory; - SampleFactoryImpl factory_impl(MakeRequest(&factory)); - - MessagePipe pipe0; - EXPECT_TRUE(WriteTextMessage(pipe0.handle1.get(), kText1)); - - MessagePipe pipe1; - EXPECT_TRUE(WriteTextMessage(pipe1.handle1.get(), kText2)); - - imported::ImportedInterfacePtr imported; - base::RunLoop run_loop; - ImportedInterfaceImpl imported_impl(MakeRequest(&imported), - run_loop.QuitClosure()); - - sample::RequestPtr request(sample::Request::New( - 1, std::move(pipe1.handle0), base::nullopt, std::move(imported))); - bool got_response = false; - std::string got_text_reply; - base::RunLoop run_loop2; - factory->DoStuff(std::move(request), std::move(pipe0.handle0), - base::Bind(&DoStuff, &got_response, &got_text_reply, - run_loop2.QuitClosure())); - - EXPECT_FALSE(got_response); - int count_before = ImportedInterfaceImpl::do_something_count(); - - run_loop.Run(); - run_loop2.Run(); - - EXPECT_TRUE(got_response); - EXPECT_EQ(kText1, got_text_reply); - EXPECT_EQ(1, ImportedInterfaceImpl::do_something_count() - count_before); -} - -TEST_F(HandlePassingTest, PassInvalid) { - sample::FactoryPtr factory; - SampleFactoryImpl factory_impl(MakeRequest(&factory)); - - sample::RequestPtr request( - sample::Request::New(1, ScopedMessagePipeHandle(), base::nullopt, - imported::ImportedInterfacePtr())); - bool got_response = false; - std::string got_text_reply; - base::RunLoop run_loop; - factory->DoStuff(std::move(request), ScopedMessagePipeHandle(), - base::Bind(&DoStuff, &got_response, &got_text_reply, - run_loop.QuitClosure())); - - EXPECT_FALSE(got_response); - - run_loop.Run(); - - EXPECT_TRUE(got_response); -} - -// Verifies DataPipeConsumer can be passed and read from. -TEST_F(HandlePassingTest, DataPipe) { - sample::FactoryPtr factory; - SampleFactoryImpl factory_impl(MakeRequest(&factory)); - - // Writes a string to a data pipe and passes the data pipe (consumer) to the - // factory. - ScopedDataPipeProducerHandle producer_handle; - ScopedDataPipeConsumerHandle consumer_handle; - MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions), - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - 1, - 1024}; - ASSERT_EQ(MOJO_RESULT_OK, - CreateDataPipe(&options, &producer_handle, &consumer_handle)); - std::string expected_text_reply = "got it"; - // +1 for \0. - uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1); - ASSERT_EQ(MOJO_RESULT_OK, - WriteDataRaw(producer_handle.get(), - expected_text_reply.c_str(), - &data_size, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - - bool got_response = false; - std::string got_text_reply; - base::RunLoop run_loop; - factory->DoStuff2(std::move(consumer_handle), - base::Bind(&DoStuff2, &got_response, &got_text_reply, - run_loop.QuitClosure())); - - EXPECT_FALSE(got_response); - - run_loop.Run(); - - EXPECT_TRUE(got_response); - EXPECT_EQ(expected_text_reply, got_text_reply); -} - -TEST_F(HandlePassingTest, PipesAreClosed) { - sample::FactoryPtr factory; - SampleFactoryImpl factory_impl(MakeRequest(&factory)); - - MessagePipe extra_pipe; - - MojoHandle handle0_value = extra_pipe.handle0.get().value(); - MojoHandle handle1_value = extra_pipe.handle1.get().value(); - - { - std::vector<ScopedMessagePipeHandle> pipes(2); - pipes[0] = std::move(extra_pipe.handle0); - pipes[1] = std::move(extra_pipe.handle1); - - sample::RequestPtr request(sample::Request::New()); - request->more_pipes = std::move(pipes); - - factory->DoStuff(std::move(request), ScopedMessagePipeHandle(), - sample::Factory::DoStuffCallback()); - } - - // We expect the pipes to have been closed. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value)); -} - -TEST_F(HandlePassingTest, CreateNamedObject) { - sample::FactoryPtr factory; - SampleFactoryImpl factory_impl(MakeRequest(&factory)); - - sample::NamedObjectPtr object1; - EXPECT_FALSE(object1); - - InterfaceRequest<sample::NamedObject> object1_request(&object1); - EXPECT_TRUE(object1_request.is_pending()); - factory->CreateNamedObject(std::move(object1_request)); - EXPECT_FALSE(object1_request.is_pending()); // We've passed the request. - - ASSERT_TRUE(object1); - object1->SetName("object1"); - - sample::NamedObjectPtr object2; - factory->CreateNamedObject(MakeRequest(&object2)); - object2->SetName("object2"); - - base::RunLoop run_loop, run_loop2; - std::string name1; - object1->GetName(MakeStringRecorder(&name1, run_loop.QuitClosure())); - - std::string name2; - object2->GetName(MakeStringRecorder(&name2, run_loop2.QuitClosure())); - - run_loop.Run(); - run_loop2.Run(); - - EXPECT_EQ(std::string("object1"), name1); - EXPECT_EQ(std::string("object2"), name2); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/hash_unittest.cc b/mojo/public/cpp/bindings/tests/hash_unittest.cc deleted file mode 100644 index 9ce1f5b..0000000 --- a/mojo/public/cpp/bindings/tests/hash_unittest.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/hash_util.h" - -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -using HashTest = testing::Test; - -TEST_F(HashTest, NestedStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ( - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - SimpleNestedStruct::New(ContainsOther::New(1))), - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - SimpleNestedStruct::New(ContainsOther::New(1)))); -} - -TEST_F(HashTest, UnmappedNativeStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ(::mojo::internal::Hash(::mojo::internal::kHashSeed, - UnmappedNativeStruct::New()), - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - UnmappedNativeStruct::New())); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc deleted file mode 100644 index 431a844..0000000 --- a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc +++ /dev/null @@ -1,937 +0,0 @@ -// 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. - -#include <stdint.h> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/threading/thread.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" -#include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h" -#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" -#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" -#include "mojo/public/interfaces/bindings/tests/scoping.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -typedef base::Callback<void(double)> CalcCallback; - -class MathCalculatorImpl : public math::Calculator { - public: - explicit MathCalculatorImpl(InterfaceRequest<math::Calculator> request) - : total_(0.0), binding_(this, std::move(request)) {} - ~MathCalculatorImpl() override {} - - void Clear(const CalcCallback& callback) override { - total_ = 0.0; - callback.Run(total_); - } - - void Add(double value, const CalcCallback& callback) override { - total_ += value; - callback.Run(total_); - } - - void Multiply(double value, const CalcCallback& callback) override { - total_ *= value; - callback.Run(total_); - } - - Binding<math::Calculator>* binding() { return &binding_; } - - private: - double total_; - Binding<math::Calculator> binding_; -}; - -class MathCalculatorUI { - public: - explicit MathCalculatorUI(math::CalculatorPtr calculator) - : calculator_(std::move(calculator)), - output_(0.0) {} - - bool encountered_error() const { return calculator_.encountered_error(); } - void set_connection_error_handler(const base::Closure& closure) { - calculator_.set_connection_error_handler(closure); - } - - void Add(double value, const base::Closure& closure) { - calculator_->Add( - value, - base::Bind(&MathCalculatorUI::Output, base::Unretained(this), closure)); - } - - void Multiply(double value, const base::Closure& closure) { - calculator_->Multiply( - value, - base::Bind(&MathCalculatorUI::Output, base::Unretained(this), closure)); - } - - double GetOutput() const { return output_; } - - math::CalculatorPtr& GetInterfacePtr() { return calculator_; } - - private: - void Output(const base::Closure& closure, double output) { - output_ = output; - if (!closure.is_null()) - closure.Run(); - } - - math::CalculatorPtr calculator_; - double output_; - base::Closure closure_; -}; - -class SelfDestructingMathCalculatorUI { - public: - explicit SelfDestructingMathCalculatorUI(math::CalculatorPtr calculator) - : calculator_(std::move(calculator)), nesting_level_(0) { - ++num_instances_; - } - - void BeginTest(bool nested, const base::Closure& closure) { - nesting_level_ = nested ? 2 : 1; - calculator_->Add( - 1.0, - base::Bind(&SelfDestructingMathCalculatorUI::Output, - base::Unretained(this), closure)); - } - - static int num_instances() { return num_instances_; } - - void Output(const base::Closure& closure, double value) { - if (--nesting_level_ > 0) { - // Add some more and wait for re-entrant call to Output! - calculator_->Add( - 1.0, - base::Bind(&SelfDestructingMathCalculatorUI::Output, - base::Unretained(this), closure)); - } else { - closure.Run(); - delete this; - } - } - - private: - ~SelfDestructingMathCalculatorUI() { --num_instances_; } - - math::CalculatorPtr calculator_; - int nesting_level_; - static int num_instances_; -}; - -// static -int SelfDestructingMathCalculatorUI::num_instances_ = 0; - -class ReentrantServiceImpl : public sample::Service { - public: - ~ReentrantServiceImpl() override {} - - explicit ReentrantServiceImpl(InterfaceRequest<sample::Service> request) - : call_depth_(0), - max_call_depth_(0), - binding_(this, std::move(request)) {} - - int max_call_depth() { return max_call_depth_; } - - void Frobinate(sample::FooPtr foo, - sample::Service::BazOptions baz, - sample::PortPtr port, - const sample::Service::FrobinateCallback& callback) override { - max_call_depth_ = std::max(++call_depth_, max_call_depth_); - if (call_depth_ == 1) { - EXPECT_TRUE(binding_.WaitForIncomingMethodCall()); - } - call_depth_--; - callback.Run(5); - } - - void GetPort(mojo::InterfaceRequest<sample::Port> port) override {} - - private: - int call_depth_; - int max_call_depth_; - Binding<sample::Service> binding_; -}; - -class IntegerAccessorImpl : public sample::IntegerAccessor { - public: - IntegerAccessorImpl() : integer_(0) {} - ~IntegerAccessorImpl() override {} - - int64_t integer() const { return integer_; } - - void set_closure(const base::Closure& closure) { closure_ = closure; } - - private: - // sample::IntegerAccessor implementation. - void GetInteger(const GetIntegerCallback& callback) override { - callback.Run(integer_, sample::Enum::VALUE); - } - void SetInteger(int64_t data, sample::Enum type) override { - integer_ = data; - if (!closure_.is_null()) { - closure_.Run(); - closure_.Reset(); - } - } - - int64_t integer_; - base::Closure closure_; -}; - -class InterfacePtrTest : public testing::Test { - public: - InterfacePtrTest() {} - ~InterfacePtrTest() override { base::RunLoop().RunUntilIdle(); } - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - private: - base::MessageLoop loop_; -}; - -void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) { - *flag = true; - closure.Run(); -} - -void IgnoreValueAndRunClosure(const base::Closure& closure, int32_t value) { - closure.Run(); -} - -void ExpectValueAndRunClosure(uint32_t expected_value, - const base::Closure& closure, - uint32_t value) { - EXPECT_EQ(expected_value, value); - closure.Run(); -} - -TEST_F(InterfacePtrTest, IsBound) { - math::CalculatorPtr calc; - EXPECT_FALSE(calc.is_bound()); - MathCalculatorImpl calc_impl(MakeRequest(&calc)); - EXPECT_TRUE(calc.is_bound()); -} - -TEST_F(InterfacePtrTest, EndToEnd) { - math::CalculatorPtr calc; - MathCalculatorImpl calc_impl(MakeRequest(&calc)); - - // Suppose this is instantiated in a process that has pipe1_. - MathCalculatorUI calculator_ui(std::move(calc)); - - base::RunLoop run_loop, run_loop2; - calculator_ui.Add(2.0, run_loop.QuitClosure()); - calculator_ui.Multiply(5.0, run_loop2.QuitClosure()); - run_loop.Run(); - run_loop2.Run(); - - EXPECT_EQ(10.0, calculator_ui.GetOutput()); -} - -TEST_F(InterfacePtrTest, EndToEnd_Synchronous) { - math::CalculatorPtr calc; - MathCalculatorImpl calc_impl(MakeRequest(&calc)); - - // Suppose this is instantiated in a process that has pipe1_. - MathCalculatorUI calculator_ui(std::move(calc)); - - EXPECT_EQ(0.0, calculator_ui.GetOutput()); - - base::RunLoop run_loop; - calculator_ui.Add(2.0, run_loop.QuitClosure()); - EXPECT_EQ(0.0, calculator_ui.GetOutput()); - calc_impl.binding()->WaitForIncomingMethodCall(); - run_loop.Run(); - EXPECT_EQ(2.0, calculator_ui.GetOutput()); - - base::RunLoop run_loop2; - calculator_ui.Multiply(5.0, run_loop2.QuitClosure()); - EXPECT_EQ(2.0, calculator_ui.GetOutput()); - calc_impl.binding()->WaitForIncomingMethodCall(); - run_loop2.Run(); - EXPECT_EQ(10.0, calculator_ui.GetOutput()); -} - -TEST_F(InterfacePtrTest, Movable) { - math::CalculatorPtr a; - math::CalculatorPtr b; - MathCalculatorImpl calc_impl(MakeRequest(&b)); - - EXPECT_TRUE(!a); - EXPECT_FALSE(!b); - - a = std::move(b); - - EXPECT_FALSE(!a); - EXPECT_TRUE(!b); -} - -TEST_F(InterfacePtrTest, Resettable) { - math::CalculatorPtr a; - - EXPECT_TRUE(!a); - - MessagePipe pipe; - - // Save this so we can test it later. - Handle handle = pipe.handle0.get(); - - a = MakeProxy( - InterfacePtrInfo<math::Calculator>(std::move(pipe.handle0), 0u)); - - EXPECT_FALSE(!a); - - a.reset(); - - EXPECT_TRUE(!a); - EXPECT_FALSE(a.internal_state()->is_bound()); - - // Test that handle was closed. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, CloseRaw(handle)); -} - -TEST_F(InterfacePtrTest, BindInvalidHandle) { - math::CalculatorPtr ptr; - EXPECT_FALSE(ptr.get()); - EXPECT_FALSE(ptr); - - ptr.Bind(InterfacePtrInfo<math::Calculator>()); - EXPECT_FALSE(ptr.get()); - EXPECT_FALSE(ptr); -} - -TEST_F(InterfacePtrTest, EncounteredError) { - math::CalculatorPtr proxy; - MathCalculatorImpl calc_impl(MakeRequest(&proxy)); - - MathCalculatorUI calculator_ui(std::move(proxy)); - - base::RunLoop run_loop; - calculator_ui.Add(2.0, run_loop.QuitClosure()); - run_loop.Run(); - EXPECT_EQ(2.0, calculator_ui.GetOutput()); - EXPECT_FALSE(calculator_ui.encountered_error()); - - calculator_ui.Multiply(5.0, base::Closure()); - EXPECT_FALSE(calculator_ui.encountered_error()); - - // Close the server. - calc_impl.binding()->Close(); - - // The state change isn't picked up locally yet. - base::RunLoop run_loop2; - calculator_ui.set_connection_error_handler(run_loop2.QuitClosure()); - EXPECT_FALSE(calculator_ui.encountered_error()); - - run_loop2.Run(); - - // OK, now we see the error. - EXPECT_TRUE(calculator_ui.encountered_error()); -} - -TEST_F(InterfacePtrTest, EncounteredErrorCallback) { - math::CalculatorPtr proxy; - MathCalculatorImpl calc_impl(MakeRequest(&proxy)); - - bool encountered_error = false; - base::RunLoop run_loop; - proxy.set_connection_error_handler( - base::Bind(&SetFlagAndRunClosure, &encountered_error, - run_loop.QuitClosure())); - - MathCalculatorUI calculator_ui(std::move(proxy)); - - base::RunLoop run_loop2; - calculator_ui.Add(2.0, run_loop2.QuitClosure()); - run_loop2.Run(); - EXPECT_EQ(2.0, calculator_ui.GetOutput()); - EXPECT_FALSE(calculator_ui.encountered_error()); - - calculator_ui.Multiply(5.0, base::Closure()); - EXPECT_FALSE(calculator_ui.encountered_error()); - - // Close the server. - calc_impl.binding()->Close(); - - // The state change isn't picked up locally yet. - EXPECT_FALSE(calculator_ui.encountered_error()); - - run_loop.Run(); - - // OK, now we see the error. - EXPECT_TRUE(calculator_ui.encountered_error()); - - // We should have also been able to observe the error through the error - // handler. - EXPECT_TRUE(encountered_error); -} - -TEST_F(InterfacePtrTest, DestroyInterfacePtrOnMethodResponse) { - math::CalculatorPtr proxy; - MathCalculatorImpl calc_impl(MakeRequest(&proxy)); - - EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances()); - - SelfDestructingMathCalculatorUI* impl = - new SelfDestructingMathCalculatorUI(std::move(proxy)); - base::RunLoop run_loop; - impl->BeginTest(false, run_loop.QuitClosure()); - run_loop.Run(); - - EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances()); -} - -TEST_F(InterfacePtrTest, NestedDestroyInterfacePtrOnMethodResponse) { - math::CalculatorPtr proxy; - MathCalculatorImpl calc_impl(MakeRequest(&proxy)); - - EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances()); - - SelfDestructingMathCalculatorUI* impl = - new SelfDestructingMathCalculatorUI(std::move(proxy)); - base::RunLoop run_loop; - impl->BeginTest(true, run_loop.QuitClosure()); - run_loop.Run(); - - EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances()); -} - -TEST_F(InterfacePtrTest, ReentrantWaitForIncomingMethodCall) { - sample::ServicePtr proxy; - ReentrantServiceImpl impl(MakeRequest(&proxy)); - - base::RunLoop run_loop, run_loop2; - proxy->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - base::Bind(&IgnoreValueAndRunClosure, - run_loop.QuitClosure())); - proxy->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr, - base::Bind(&IgnoreValueAndRunClosure, - run_loop2.QuitClosure())); - - run_loop.Run(); - run_loop2.Run(); - - EXPECT_EQ(2, impl.max_call_depth()); -} - -TEST_F(InterfacePtrTest, QueryVersion) { - IntegerAccessorImpl impl; - sample::IntegerAccessorPtr ptr; - Binding<sample::IntegerAccessor> binding(&impl, MakeRequest(&ptr)); - - EXPECT_EQ(0u, ptr.version()); - - base::RunLoop run_loop; - ptr.QueryVersion(base::Bind(&ExpectValueAndRunClosure, 3u, - run_loop.QuitClosure())); - run_loop.Run(); - - EXPECT_EQ(3u, ptr.version()); -} - -TEST_F(InterfacePtrTest, RequireVersion) { - IntegerAccessorImpl impl; - sample::IntegerAccessorPtr ptr; - Binding<sample::IntegerAccessor> binding(&impl, MakeRequest(&ptr)); - - EXPECT_EQ(0u, ptr.version()); - - ptr.RequireVersion(1u); - EXPECT_EQ(1u, ptr.version()); - base::RunLoop run_loop; - impl.set_closure(run_loop.QuitClosure()); - ptr->SetInteger(123, sample::Enum::VALUE); - run_loop.Run(); - EXPECT_FALSE(ptr.encountered_error()); - EXPECT_EQ(123, impl.integer()); - - ptr.RequireVersion(3u); - EXPECT_EQ(3u, ptr.version()); - base::RunLoop run_loop2; - impl.set_closure(run_loop2.QuitClosure()); - ptr->SetInteger(456, sample::Enum::VALUE); - run_loop2.Run(); - EXPECT_FALSE(ptr.encountered_error()); - EXPECT_EQ(456, impl.integer()); - - // Require a version that is not supported by the impl side. - ptr.RequireVersion(4u); - // This value is set to the input of RequireVersion() synchronously. - EXPECT_EQ(4u, ptr.version()); - base::RunLoop run_loop3; - ptr.set_connection_error_handler(run_loop3.QuitClosure()); - ptr->SetInteger(789, sample::Enum::VALUE); - run_loop3.Run(); - EXPECT_TRUE(ptr.encountered_error()); - // The call to SetInteger() after RequireVersion(4u) is ignored. - EXPECT_EQ(456, impl.integer()); -} - -class StrongMathCalculatorImpl : public math::Calculator { - public: - StrongMathCalculatorImpl(bool* destroyed) : destroyed_(destroyed) {} - ~StrongMathCalculatorImpl() override { *destroyed_ = true; } - - // math::Calculator implementation. - void Clear(const CalcCallback& callback) override { callback.Run(total_); } - - void Add(double value, const CalcCallback& callback) override { - total_ += value; - callback.Run(total_); - } - - void Multiply(double value, const CalcCallback& callback) override { - total_ *= value; - callback.Run(total_); - } - - private: - double total_ = 0.0; - bool* destroyed_; -}; - -TEST(StrongConnectorTest, Math) { - base::MessageLoop loop; - - bool error_received = false; - bool destroyed = false; - math::CalculatorPtr calc; - base::RunLoop run_loop; - - auto binding = - MakeStrongBinding(base::MakeUnique<StrongMathCalculatorImpl>(&destroyed), - MakeRequest(&calc)); - binding->set_connection_error_handler(base::Bind( - &SetFlagAndRunClosure, &error_received, run_loop.QuitClosure())); - - { - // Suppose this is instantiated in a process that has the other end of the - // message pipe. - MathCalculatorUI calculator_ui(std::move(calc)); - - base::RunLoop run_loop, run_loop2; - calculator_ui.Add(2.0, run_loop.QuitClosure()); - calculator_ui.Multiply(5.0, run_loop2.QuitClosure()); - run_loop.Run(); - run_loop2.Run(); - - EXPECT_EQ(10.0, calculator_ui.GetOutput()); - EXPECT_FALSE(error_received); - EXPECT_FALSE(destroyed); - } - // Destroying calculator_ui should close the pipe and generate an error on the - // other - // end which will destroy the instance since it is strongly bound. - - run_loop.Run(); - EXPECT_TRUE(error_received); - EXPECT_TRUE(destroyed); -} - -class WeakMathCalculatorImpl : public math::Calculator { - public: - WeakMathCalculatorImpl(ScopedMessagePipeHandle handle, - bool* error_received, - bool* destroyed, - const base::Closure& closure) - : error_received_(error_received), - destroyed_(destroyed), - closure_(closure), - binding_(this, std::move(handle)) { - binding_.set_connection_error_handler( - base::Bind(&SetFlagAndRunClosure, error_received_, closure_)); - } - ~WeakMathCalculatorImpl() override { *destroyed_ = true; } - - void Clear(const CalcCallback& callback) override { callback.Run(total_); } - - void Add(double value, const CalcCallback& callback) override { - total_ += value; - callback.Run(total_); - } - - void Multiply(double value, const CalcCallback& callback) override { - total_ *= value; - callback.Run(total_); - } - - private: - double total_ = 0.0; - bool* error_received_; - bool* destroyed_; - base::Closure closure_; - - Binding<math::Calculator> binding_; -}; - -TEST(WeakConnectorTest, Math) { - base::MessageLoop loop; - - bool error_received = false; - bool destroyed = false; - MessagePipe pipe; - base::RunLoop run_loop; - WeakMathCalculatorImpl impl(std::move(pipe.handle0), &error_received, - &destroyed, run_loop.QuitClosure()); - - math::CalculatorPtr calc; - calc.Bind(InterfacePtrInfo<math::Calculator>(std::move(pipe.handle1), 0u)); - - { - // Suppose this is instantiated in a process that has the other end of the - // message pipe. - MathCalculatorUI calculator_ui(std::move(calc)); - - base::RunLoop run_loop, run_loop2; - calculator_ui.Add(2.0, run_loop.QuitClosure()); - calculator_ui.Multiply(5.0, run_loop2.QuitClosure()); - run_loop.Run(); - run_loop2.Run(); - - EXPECT_EQ(10.0, calculator_ui.GetOutput()); - EXPECT_FALSE(error_received); - EXPECT_FALSE(destroyed); - // Destroying calculator_ui should close the pipe and generate an error on - // the other - // end which will destroy the instance since it is strongly bound. - } - - run_loop.Run(); - EXPECT_TRUE(error_received); - EXPECT_FALSE(destroyed); -} - -class CImpl : public C { - public: - CImpl(bool* d_called, const base::Closure& closure) - : d_called_(d_called), closure_(closure) {} - ~CImpl() override {} - - private: - void D() override { - *d_called_ = true; - closure_.Run(); - } - - bool* d_called_; - base::Closure closure_; -}; - -class BImpl : public B { - public: - BImpl(bool* d_called, const base::Closure& closure) - : d_called_(d_called), closure_(closure) {} - ~BImpl() override {} - - private: - void GetC(InterfaceRequest<C> c) override { - MakeStrongBinding(base::MakeUnique<CImpl>(d_called_, closure_), - std::move(c)); - } - - bool* d_called_; - base::Closure closure_; -}; - -class AImpl : public A { - public: - AImpl(InterfaceRequest<A> request, const base::Closure& closure) - : d_called_(false), binding_(this, std::move(request)), - closure_(closure) {} - ~AImpl() override {} - - bool d_called() const { return d_called_; } - - private: - void GetB(InterfaceRequest<B> b) override { - MakeStrongBinding(base::MakeUnique<BImpl>(&d_called_, closure_), - std::move(b)); - } - - bool d_called_; - Binding<A> binding_; - base::Closure closure_; -}; - -TEST_F(InterfacePtrTest, Scoping) { - APtr a; - base::RunLoop run_loop; - AImpl a_impl(MakeRequest(&a), run_loop.QuitClosure()); - - EXPECT_FALSE(a_impl.d_called()); - - { - BPtr b; - a->GetB(MakeRequest(&b)); - CPtr c; - b->GetC(MakeRequest(&c)); - c->D(); - } - - // While B & C have fallen out of scope, the pipes will remain until they are - // flushed. - EXPECT_FALSE(a_impl.d_called()); - run_loop.Run(); - EXPECT_TRUE(a_impl.d_called()); -} - -class PingTestImpl : public sample::PingTest { - public: - explicit PingTestImpl(InterfaceRequest<sample::PingTest> request) - : binding_(this, std::move(request)) {} - ~PingTestImpl() override {} - - private: - // sample::PingTest: - void Ping(const PingCallback& callback) override { callback.Run(); } - - Binding<sample::PingTest> binding_; -}; - -// Tests that FuseProxy does what it's supposed to do. -TEST_F(InterfacePtrTest, Fusion) { - sample::PingTestPtr proxy; - PingTestImpl impl(MakeRequest(&proxy)); - - // Create another PingTest pipe. - sample::PingTestPtr ptr; - sample::PingTestRequest request(&ptr); - - // Fuse the new pipe to the one hanging off |impl|. - EXPECT_TRUE(FuseInterface(std::move(request), proxy.PassInterface())); - - // Ping! - bool called = false; - base::RunLoop loop; - ptr->Ping(base::Bind(&SetFlagAndRunClosure, &called, loop.QuitClosure())); - loop.Run(); - EXPECT_TRUE(called); -} - -void Fail() { - FAIL() << "Unexpected connection error"; -} - -TEST_F(InterfacePtrTest, FlushForTesting) { - math::CalculatorPtr calc; - MathCalculatorImpl calc_impl(MakeRequest(&calc)); - calc.set_connection_error_handler(base::Bind(&Fail)); - - MathCalculatorUI calculator_ui(std::move(calc)); - - calculator_ui.Add(2.0, base::Bind(&base::DoNothing)); - calculator_ui.GetInterfacePtr().FlushForTesting(); - EXPECT_EQ(2.0, calculator_ui.GetOutput()); - - calculator_ui.Multiply(5.0, base::Bind(&base::DoNothing)); - calculator_ui.GetInterfacePtr().FlushForTesting(); - - EXPECT_EQ(10.0, calculator_ui.GetOutput()); -} - -void SetBool(bool* value) { - *value = true; -} - -TEST_F(InterfacePtrTest, FlushForTestingWithClosedPeer) { - math::CalculatorPtr calc; - MakeRequest(&calc); - bool called = false; - calc.set_connection_error_handler(base::Bind(&SetBool, &called)); - calc.FlushForTesting(); - EXPECT_TRUE(called); - calc.FlushForTesting(); -} - -TEST_F(InterfacePtrTest, ConnectionErrorWithReason) { - math::CalculatorPtr calc; - MathCalculatorImpl calc_impl(MakeRequest(&calc)); - - base::RunLoop run_loop; - calc.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(42u, custom_reason); - EXPECT_EQ("hey", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - calc_impl.binding()->CloseWithReason(42u, "hey"); - - run_loop.Run(); -} - -TEST_F(InterfacePtrTest, InterfaceRequestResetWithReason) { - math::CalculatorPtr calc; - auto request = MakeRequest(&calc); - - base::RunLoop run_loop; - calc.set_connection_error_with_reason_handler(base::Bind( - [](const base::Closure& quit_closure, uint32_t custom_reason, - const std::string& description) { - EXPECT_EQ(88u, custom_reason); - EXPECT_EQ("greetings", description); - quit_closure.Run(); - }, - run_loop.QuitClosure())); - - request.ResetWithReason(88u, "greetings"); - - run_loop.Run(); -} - -TEST_F(InterfacePtrTest, CallbackIsPassedInterfacePtr) { - sample::PingTestPtr ptr; - sample::PingTestRequest request(&ptr); - - base::RunLoop run_loop; - - // Make a call with the proxy's lifetime bound to the response callback. - sample::PingTest* raw_proxy = ptr.get(); - ptr.set_connection_error_handler(run_loop.QuitClosure()); - raw_proxy->Ping( - base::Bind([](sample::PingTestPtr ptr) {}, base::Passed(&ptr))); - - // Trigger an error on |ptr|. This will ultimately lead to the proxy's - // response callbacks being destroyed, which will in turn lead to the proxy - // being destroyed. This should not crash. - request.PassMessagePipe(); - run_loop.Run(); -} - -TEST_F(InterfacePtrTest, ConnectionErrorHandlerOwnsInterfacePtr) { - sample::PingTestPtr* ptr = new sample::PingTestPtr; - sample::PingTestRequest request(ptr); - - base::RunLoop run_loop; - - // Make a call with |ptr|'s lifetime bound to the connection error handler - // callback. - ptr->set_connection_error_handler(base::Bind( - [](const base::Closure& quit, sample::PingTestPtr* ptr) { - ptr->reset(); - quit.Run(); - }, - run_loop.QuitClosure(), base::Owned(ptr))); - - // Trigger an error on |ptr|. In the error handler |ptr| is reset. This - // shouldn't immediately destroy the callback (and |ptr| that it owns), before - // the callback is completed. - request.PassMessagePipe(); - run_loop.Run(); -} - -TEST_F(InterfacePtrTest, ThreadSafeInterfacePointer) { - math::CalculatorPtr ptr; - MathCalculatorImpl calc_impl(MakeRequest(&ptr)); - scoped_refptr<math::ThreadSafeCalculatorPtr> thread_safe_ptr = - math::ThreadSafeCalculatorPtr::Create(std::move(ptr)); - - base::RunLoop run_loop; - - // Create and start the thread from where we'll call the interface pointer. - base::Thread other_thread("service test thread"); - other_thread.Start(); - - auto run_method = base::Bind( - [](const scoped_refptr<base::TaskRunner>& main_task_runner, - const base::Closure& quit_closure, - const scoped_refptr<math::ThreadSafeCalculatorPtr>& thread_safe_ptr) { - auto calc_callback = base::Bind( - [](const scoped_refptr<base::TaskRunner>& main_task_runner, - const base::Closure& quit_closure, - base::PlatformThreadId thread_id, - double result) { - EXPECT_EQ(123, result); - // Validate the callback is invoked on the calling thread. - EXPECT_EQ(thread_id, base::PlatformThread::CurrentId()); - // Notify the run_loop to quit. - main_task_runner->PostTask(FROM_HERE, quit_closure); - }); - (*thread_safe_ptr)->Add( - 123, base::Bind(calc_callback, main_task_runner, quit_closure, - base::PlatformThread::CurrentId())); - }, - base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(), - thread_safe_ptr); - other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method); - - // Block until the method callback is called on the background thread. - run_loop.Run(); -} - -TEST_F(InterfacePtrTest, ThreadSafeInterfacePointerWithTaskRunner) { - // Create and start the thread from where we'll bind the interface pointer. - base::Thread other_thread("service test thread"); - other_thread.Start(); - const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner = - other_thread.message_loop()->task_runner(); - - math::CalculatorPtr ptr; - math::CalculatorRequest request(&ptr); - - // Create a ThreadSafeInterfacePtr that we'll bind from a different thread. - scoped_refptr<math::ThreadSafeCalculatorPtr> thread_safe_ptr = - math::ThreadSafeCalculatorPtr::Create(ptr.PassInterface(), - other_thread_task_runner); - ASSERT_TRUE(thread_safe_ptr); - - MathCalculatorImpl* math_calc_impl = nullptr; - { - base::RunLoop run_loop; - auto run_method = base::Bind( - [](const scoped_refptr<base::TaskRunner>& main_task_runner, - const base::Closure& quit_closure, - const scoped_refptr<math::ThreadSafeCalculatorPtr>& thread_safe_ptr, - math::CalculatorRequest request, - MathCalculatorImpl** math_calc_impl) { - math::CalculatorPtr ptr; - // In real life, the implementation would have a legitimate owner. - *math_calc_impl = new MathCalculatorImpl(std::move(request)); - main_task_runner->PostTask(FROM_HERE, quit_closure); - }, - base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(), - thread_safe_ptr, base::Passed(&request), &math_calc_impl); - other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method); - run_loop.Run(); - } - - { - // The interface ptr is bound, we can call methods on it. - auto calc_callback = - base::Bind([](const base::Closure& quit_closure, double result) { - EXPECT_EQ(123, result); - quit_closure.Run(); - }); - base::RunLoop run_loop; - (*thread_safe_ptr) - ->Add(123, base::Bind(calc_callback, run_loop.QuitClosure())); - // Block until the method callback is called. - run_loop.Run(); - } - - other_thread_task_runner->DeleteSoon(FROM_HERE, math_calc_impl); - - // Reset the pointer now so the InterfacePtr associated resources can be - // deleted before the background thread's message loop is invalidated. - thread_safe_ptr = nullptr; -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/map_unittest.cc b/mojo/public/cpp/bindings/tests/map_unittest.cc deleted file mode 100644 index 8d630a5..0000000 --- a/mojo/public/cpp/bindings/tests/map_unittest.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <unordered_map> -#include <utility> - -#include "mojo/public/cpp/bindings/tests/rect_chromium.h" -#include "mojo/public/interfaces/bindings/tests/rect.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -TEST(MapTest, StructKey) { - std::unordered_map<RectPtr, int32_t> map; - map.insert(std::make_pair(Rect::New(1, 2, 3, 4), 123)); - - RectPtr key = Rect::New(1, 2, 3, 4); - ASSERT_NE(map.end(), map.find(key)); - ASSERT_EQ(123, map.find(key)->second); - - map.erase(key); - ASSERT_EQ(0u, map.size()); -} - -TEST(MapTest, TypemappedStructKey) { - std::unordered_map<ContainsHashablePtr, int32_t> map; - map.insert( - std::make_pair(ContainsHashable::New(RectChromium(1, 2, 3, 4)), 123)); - - ContainsHashablePtr key = ContainsHashable::New(RectChromium(1, 2, 3, 4)); - ASSERT_NE(map.end(), map.find(key)); - ASSERT_EQ(123, map.find(key)->second); - - map.erase(key); - ASSERT_EQ(0u, map.size()); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/message_queue.cc b/mojo/public/cpp/bindings/tests/message_queue.cc deleted file mode 100644 index 32ed763..0000000 --- a/mojo/public/cpp/bindings/tests/message_queue.cc +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/tests/message_queue.h" - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace test { - -MessageQueue::MessageQueue() { -} - -MessageQueue::~MessageQueue() { -} - -bool MessageQueue::IsEmpty() const { - return queue_.empty(); -} - -void MessageQueue::Push(Message* message) { - queue_.emplace(std::move(*message)); -} - -void MessageQueue::Pop(Message* message) { - DCHECK(!queue_.empty()); - *message = std::move(queue_.front()); - Pop(); -} - -void MessageQueue::Pop() { - DCHECK(!queue_.empty()); - queue_.pop(); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/message_queue.h b/mojo/public/cpp/bindings/tests/message_queue.h deleted file mode 100644 index 8f13f7a..0000000 --- a/mojo/public/cpp/bindings/tests/message_queue.h +++ /dev/null @@ -1,44 +0,0 @@ -// 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_PUBLIC_CPP_BINDINGS_TESTS_MESSAGE_QUEUE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_MESSAGE_QUEUE_H_ - -#include <queue> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace test { - -// A queue for Message objects. -class MessageQueue { - public: - MessageQueue(); - ~MessageQueue(); - - bool IsEmpty() const; - - // This method copies the message data and steals ownership of its handles. - void Push(Message* message); - - // Removes the next message from the queue, copying its data and transferring - // ownership of its handles to the given |message|. - void Pop(Message* message); - - size_t size() const { return queue_.size(); } - - private: - void Pop(); - - std::queue<Message> queue_; - - DISALLOW_COPY_AND_ASSIGN(MessageQueue); -}; - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_MESSAGE_QUEUE_H_ diff --git a/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h b/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h deleted file mode 100644 index b3bbe27..0000000 --- a/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_BLINK_EXPORT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_BLINK_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_TEST_BLINK_IMPLEMENTATION) -#define MOJO_TEST_BLINK_EXPORT __declspec(dllexport) -#else -#define MOJO_TEST_BLINK_EXPORT __declspec(dllimport) -#endif // defined(MOJO_TEST_BLINK_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(MOJO_TEST_BLINK_IMPLEMENTATION) -#define MOJO_TEST_BLINK_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_TEST_BLINK_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define MOJO_TEST_BLINK_EXPORT -#endif - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_BLINK_EXPORT_H_ diff --git a/mojo/public/cpp/bindings/tests/mojo_test_export.h b/mojo/public/cpp/bindings/tests/mojo_test_export.h deleted file mode 100644 index a48a1ba..0000000 --- a/mojo/public/cpp/bindings/tests/mojo_test_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_EXPORT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_TEST_IMPLEMENTATION) -#define MOJO_TEST_EXPORT __declspec(dllexport) -#else -#define MOJO_TEST_EXPORT __declspec(dllimport) -#endif // defined(MOJO_TEST_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(MOJO_TEST_IMPLEMENTATION) -#define MOJO_TEST_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_TEST_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define MOJO_TEST_EXPORT -#endif - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_MOJO_TEST_EXPORT_H_ diff --git a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc deleted file mode 100644 index 8950928..0000000 --- a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" - -#include <utility> - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/bindings/tests/message_queue.h" -#include "mojo/public/cpp/bindings/tests/router_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -using mojo::internal::MultiplexRouter; - -class MultiplexRouterTest : public testing::Test { - public: - MultiplexRouterTest() {} - - void SetUp() override { - MessagePipe pipe; - router0_ = new MultiplexRouter(std::move(pipe.handle0), - MultiplexRouter::MULTI_INTERFACE, false, - base::ThreadTaskRunnerHandle::Get()); - router1_ = new MultiplexRouter(std::move(pipe.handle1), - MultiplexRouter::MULTI_INTERFACE, true, - base::ThreadTaskRunnerHandle::Get()); - ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&endpoint0_, - &endpoint1_); - auto id = router0_->AssociateInterface(std::move(endpoint1_)); - endpoint1_ = router1_->CreateLocalEndpointHandle(id); - } - - void TearDown() override {} - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - protected: - scoped_refptr<MultiplexRouter> router0_; - scoped_refptr<MultiplexRouter> router1_; - ScopedInterfaceEndpointHandle endpoint0_; - ScopedInterfaceEndpointHandle endpoint1_; - - private: - base::MessageLoop loop_; -}; - -TEST_F(MultiplexRouterTest, BasicRequestResponse) { - InterfaceEndpointClient client0(std::move(endpoint0_), nullptr, - base::MakeUnique<PassThroughFilter>(), false, - base::ThreadTaskRunnerHandle::Get(), 0u); - ResponseGenerator generator; - InterfaceEndpointClient client1(std::move(endpoint1_), &generator, - base::MakeUnique<PassThroughFilter>(), false, - base::ThreadTaskRunnerHandle::Get(), 0u); - - Message request; - AllocRequestMessage(1, "hello", &request); - - MessageQueue message_queue; - base::RunLoop run_loop; - client0.AcceptWithResponder( - &request, base::MakeUnique<MessageAccumulator>(&message_queue, - run_loop.QuitClosure())); - - run_loop.Run(); - - EXPECT_FALSE(message_queue.IsEmpty()); - - Message response; - message_queue.Pop(&response); - - EXPECT_EQ(std::string("hello world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); - - // Send a second message on the pipe. - Message request2; - AllocRequestMessage(1, "hello again", &request2); - - base::RunLoop run_loop2; - client0.AcceptWithResponder( - &request2, base::MakeUnique<MessageAccumulator>(&message_queue, - run_loop2.QuitClosure())); - - run_loop2.Run(); - - EXPECT_FALSE(message_queue.IsEmpty()); - - message_queue.Pop(&response); - - EXPECT_EQ(std::string("hello again world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); -} - -TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) { - InterfaceEndpointClient client0(std::move(endpoint0_), nullptr, - base::MakeUnique<PassThroughFilter>(), false, - base::ThreadTaskRunnerHandle::Get(), 0u); - ResponseGenerator generator; - InterfaceEndpointClient client1(std::move(endpoint1_), &generator, - base::MakeUnique<PassThroughFilter>(), false, - base::ThreadTaskRunnerHandle::Get(), 0u); - - Message request; - AllocRequestMessage(1, "hello", &request); - - MessageQueue message_queue; - client0.AcceptWithResponder( - &request, base::MakeUnique<MessageAccumulator>(&message_queue)); - - router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - - EXPECT_FALSE(message_queue.IsEmpty()); - - Message response; - message_queue.Pop(&response); - - EXPECT_EQ(std::string("hello world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); - - // Send a second message on the pipe. - Message request2; - AllocRequestMessage(1, "hello again", &request2); - - client0.AcceptWithResponder( - &request2, base::MakeUnique<MessageAccumulator>(&message_queue)); - - router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); - - EXPECT_FALSE(message_queue.IsEmpty()); - - message_queue.Pop(&response); - - EXPECT_EQ(std::string("hello again world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); -} - -// Tests MultiplexRouter using the LazyResponseGenerator. The responses will not -// be sent until after the requests have been accepted. -TEST_F(MultiplexRouterTest, LazyResponses) { - InterfaceEndpointClient client0( - std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()), - false, base::ThreadTaskRunnerHandle::Get(), 0u); - base::RunLoop run_loop; - LazyResponseGenerator generator(run_loop.QuitClosure()); - InterfaceEndpointClient client1(std::move(endpoint1_), &generator, - base::WrapUnique(new PassThroughFilter()), - false, base::ThreadTaskRunnerHandle::Get(), - 0u); - - Message request; - AllocRequestMessage(1, "hello", &request); - - MessageQueue message_queue; - base::RunLoop run_loop2; - client0.AcceptWithResponder( - &request, base::MakeUnique<MessageAccumulator>(&message_queue, - run_loop2.QuitClosure())); - run_loop.Run(); - - // The request has been received but the response has not been sent yet. - EXPECT_TRUE(message_queue.IsEmpty()); - - // Send the response. - EXPECT_TRUE(generator.responder_is_valid()); - generator.CompleteWithResponse(); - run_loop2.Run(); - - // Check the response. - EXPECT_FALSE(message_queue.IsEmpty()); - Message response; - message_queue.Pop(&response); - EXPECT_EQ(std::string("hello world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); - - // Send a second message on the pipe. - base::RunLoop run_loop3; - generator.set_closure(run_loop3.QuitClosure()); - Message request2; - AllocRequestMessage(1, "hello again", &request2); - - base::RunLoop run_loop4; - client0.AcceptWithResponder( - &request2, base::MakeUnique<MessageAccumulator>(&message_queue, - run_loop4.QuitClosure())); - run_loop3.Run(); - - // The request has been received but the response has not been sent yet. - EXPECT_TRUE(message_queue.IsEmpty()); - - // Send the second response. - EXPECT_TRUE(generator.responder_is_valid()); - generator.CompleteWithResponse(); - run_loop4.Run(); - - // Check the second response. - EXPECT_FALSE(message_queue.IsEmpty()); - message_queue.Pop(&response); - EXPECT_EQ(std::string("hello again world!"), - std::string(reinterpret_cast<const char*>(response.payload()))); -} - -void ForwardErrorHandler(bool* called, const base::Closure& callback) { - *called = true; - callback.Run(); -} - -// Tests that if the receiving application destroys the responder_ without -// sending a response, then we trigger connection error at both sides. Moreover, -// both sides still appear to have a valid message pipe handle bound. -TEST_F(MultiplexRouterTest, MissingResponses) { - base::RunLoop run_loop0, run_loop1; - InterfaceEndpointClient client0( - std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()), - false, base::ThreadTaskRunnerHandle::Get(), 0u); - bool error_handler_called0 = false; - client0.set_connection_error_handler( - base::Bind(&ForwardErrorHandler, &error_handler_called0, - run_loop0.QuitClosure())); - - base::RunLoop run_loop3; - LazyResponseGenerator generator(run_loop3.QuitClosure()); - InterfaceEndpointClient client1(std::move(endpoint1_), &generator, - base::WrapUnique(new PassThroughFilter()), - false, base::ThreadTaskRunnerHandle::Get(), - 0u); - bool error_handler_called1 = false; - client1.set_connection_error_handler( - base::Bind(&ForwardErrorHandler, &error_handler_called1, - run_loop1.QuitClosure())); - - Message request; - AllocRequestMessage(1, "hello", &request); - - MessageQueue message_queue; - client0.AcceptWithResponder( - &request, base::MakeUnique<MessageAccumulator>(&message_queue)); - run_loop3.Run(); - - // The request has been received but no response has been sent. - EXPECT_TRUE(message_queue.IsEmpty()); - - // Destroy the responder MessagerReceiver but don't send any response. - generator.CompleteWithoutResponse(); - run_loop0.Run(); - run_loop1.Run(); - - // Check that no response was received. - EXPECT_TRUE(message_queue.IsEmpty()); - - // Connection error handler is called at both sides. - EXPECT_TRUE(error_handler_called0); - EXPECT_TRUE(error_handler_called1); - - // The error flag is set at both sides. - EXPECT_TRUE(client0.encountered_error()); - EXPECT_TRUE(client1.encountered_error()); - - // The message pipe handle is valid at both sides. - EXPECT_TRUE(router0_->is_valid()); - EXPECT_TRUE(router1_->is_valid()); -} - -TEST_F(MultiplexRouterTest, LateResponse) { - // Test that things won't blow up if we try to send a message to a - // MessageReceiver, which was given to us via AcceptWithResponder, - // after the router has gone away. - - base::RunLoop run_loop; - LazyResponseGenerator generator(run_loop.QuitClosure()); - { - InterfaceEndpointClient client0( - std::move(endpoint0_), nullptr, base::MakeUnique<PassThroughFilter>(), - false, base::ThreadTaskRunnerHandle::Get(), 0u); - InterfaceEndpointClient client1(std::move(endpoint1_), &generator, - base::MakeUnique<PassThroughFilter>(), - false, base::ThreadTaskRunnerHandle::Get(), - 0u); - - Message request; - AllocRequestMessage(1, "hello", &request); - - MessageQueue message_queue; - client0.AcceptWithResponder( - &request, base::MakeUnique<MessageAccumulator>(&message_queue)); - - run_loop.Run(); - - EXPECT_TRUE(generator.has_responder()); - } - - EXPECT_FALSE(generator.responder_is_valid()); - generator.CompleteWithResponse(); // This should end up doing nothing. -} - -// TODO(yzshen): add more tests. - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc deleted file mode 100644 index a5947ce..0000000 --- a/mojo/public/cpp/bindings/tests/pickle_unittest.cc +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/tests/pickled_types_blink.h" -#include "mojo/public/cpp/bindings/tests/pickled_types_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.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -template <typename T> -void DoExpectResult(int foo, int bar, const base::Closure& callback, T actual) { - EXPECT_EQ(foo, actual.foo()); - EXPECT_EQ(bar, actual.bar()); - callback.Run(); -} - -template <typename T> -base::Callback<void(T)> ExpectResult(const T& t, - const base::Closure& callback) { - return base::Bind(&DoExpectResult<T>, t.foo(), t.bar(), callback); -} - -template <typename T> -void DoFail(const std::string& reason, T) { - EXPECT_TRUE(false) << reason; -} - -template <typename T> -base::Callback<void(T)> Fail(const std::string& reason) { - return base::Bind(&DoFail<T>, reason); -} - -template <typename T> -void DoExpectEnumResult(T expected, const base::Closure& callback, T actual) { - EXPECT_EQ(expected, actual); - callback.Run(); -} - -template <typename T> -base::Callback<void(T)> ExpectEnumResult(T t, const base::Closure& callback) { - return base::Bind(&DoExpectEnumResult<T>, t, callback); -} - -template <typename T> -void DoEnumFail(const std::string& reason, T) { - EXPECT_TRUE(false) << reason; -} - -template <typename T> -base::Callback<void(T)> EnumFail(const std::string& reason) { - return base::Bind(&DoEnumFail<T>, reason); -} - -template <typename T> -void ExpectError(InterfacePtr<T>* proxy, const base::Closure& callback) { - proxy->set_connection_error_handler(callback); -} - -template <typename Func, typename Arg> -void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); } - -template <typename Arg, typename Func> -base::Callback<void(Arg)> BindSimpleLambda(Func func) { - return base::Bind(&RunSimpleLambda<Func, Arg>, func); -} - -// This implements the generated Chromium variant of PicklePasser. -class ChromiumPicklePasserImpl : public PicklePasser { - public: - ChromiumPicklePasserImpl() {} - - // mojo::test::PicklePasser: - void PassPickledStruct(PickledStructChromium pickle, - const PassPickledStructCallback& callback) override { - callback.Run(std::move(pickle)); - } - - void PassPickledEnum(PickledEnumChromium pickle, - const PassPickledEnumCallback& callback) override { - callback.Run(pickle); - } - - void PassPickleContainer( - PickleContainerPtr container, - const PassPickleContainerCallback& callback) override { - callback.Run(std::move(container)); - } - - void PassPickles(std::vector<PickledStructChromium> pickles, - const PassPicklesCallback& callback) override { - callback.Run(std::move(pickles)); - } - - void PassPickleArrays( - std::vector<std::vector<PickledStructChromium>> pickle_arrays, - const PassPickleArraysCallback& callback) override { - callback.Run(std::move(pickle_arrays)); - } -}; - -// This implements the generated Blink variant of PicklePasser. -class BlinkPicklePasserImpl : public blink::PicklePasser { - public: - BlinkPicklePasserImpl() {} - - // mojo::test::blink::PicklePasser: - void PassPickledStruct(PickledStructBlink pickle, - const PassPickledStructCallback& callback) override { - callback.Run(std::move(pickle)); - } - - void PassPickledEnum(PickledEnumBlink pickle, - const PassPickledEnumCallback& callback) override { - callback.Run(pickle); - } - - void PassPickleContainer( - blink::PickleContainerPtr container, - const PassPickleContainerCallback& callback) override { - callback.Run(std::move(container)); - } - - void PassPickles(WTF::Vector<PickledStructBlink> pickles, - const PassPicklesCallback& callback) override { - callback.Run(std::move(pickles)); - } - - void PassPickleArrays( - WTF::Vector<WTF::Vector<PickledStructBlink>> pickle_arrays, - const PassPickleArraysCallback& callback) override { - callback.Run(std::move(pickle_arrays)); - } -}; - -// A test which runs both Chromium and Blink implementations of the -// PicklePasser service. -class PickleTest : public testing::Test { - public: - PickleTest() {} - - template <typename ProxyType = PicklePasser> - InterfacePtr<ProxyType> ConnectToChromiumService() { - InterfacePtr<ProxyType> proxy; - InterfaceRequest<ProxyType> request(&proxy); - chromium_bindings_.AddBinding( - &chromium_service_, - ConvertInterfaceRequest<PicklePasser>(std::move(request))); - return proxy; - } - - template <typename ProxyType = blink::PicklePasser> - InterfacePtr<ProxyType> ConnectToBlinkService() { - InterfacePtr<ProxyType> proxy; - InterfaceRequest<ProxyType> request(&proxy); - blink_bindings_.AddBinding( - &blink_service_, - ConvertInterfaceRequest<blink::PicklePasser>(std::move(request))); - return proxy; - } - - private: - base::MessageLoop loop_; - ChromiumPicklePasserImpl chromium_service_; - BindingSet<PicklePasser> chromium_bindings_; - BlinkPicklePasserImpl blink_service_; - BindingSet<blink::PicklePasser> blink_bindings_; -}; - -} // namespace - -TEST_F(PickleTest, ChromiumProxyToChromiumService) { - auto chromium_proxy = ConnectToChromiumService(); - { - base::RunLoop loop; - chromium_proxy->PassPickledStruct( - PickledStructChromium(1, 2), - ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - chromium_proxy->PassPickledStruct( - PickledStructChromium(4, 5), - ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); - loop.Run(); - } - - { - base::RunLoop loop; - chromium_proxy->PassPickledEnum( - PickledEnumChromium::VALUE_1, - ExpectEnumResult(PickledEnumChromium::VALUE_1, loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(PickleTest, ChromiumProxyToBlinkService) { - auto chromium_proxy = ConnectToBlinkService<PicklePasser>(); - { - base::RunLoop loop; - chromium_proxy->PassPickledStruct( - PickledStructChromium(1, 2), - ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - chromium_proxy->PassPickledStruct( - PickledStructChromium(4, 5), - ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); - loop.Run(); - } - // The Blink service should drop our connection because the - // PickledStructBlink ParamTraits deserializer rejects negative values. - { - base::RunLoop loop; - chromium_proxy->PassPickledStruct( - PickledStructChromium(-1, -1), - Fail<PickledStructChromium>("Blink service should reject this.")); - ExpectError(&chromium_proxy, loop.QuitClosure()); - loop.Run(); - } - - chromium_proxy = ConnectToBlinkService<PicklePasser>(); - { - base::RunLoop loop; - chromium_proxy->PassPickledEnum( - PickledEnumChromium::VALUE_0, - ExpectEnumResult(PickledEnumChromium::VALUE_0, loop.QuitClosure())); - loop.Run(); - } - - // The Blink service should drop our connection because the - // PickledEnumBlink ParamTraits deserializer rejects this value. - { - base::RunLoop loop; - chromium_proxy->PassPickledEnum( - PickledEnumChromium::VALUE_2, - EnumFail<PickledEnumChromium>("Blink service should reject this.")); - ExpectError(&chromium_proxy, loop.QuitClosure()); - loop.Run(); - } -} - -TEST_F(PickleTest, BlinkProxyToBlinkService) { - auto blink_proxy = ConnectToBlinkService(); - { - base::RunLoop loop; - blink_proxy->PassPickledStruct( - PickledStructBlink(1, 1), - ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); - loop.Run(); - } - - { - base::RunLoop loop; - blink_proxy->PassPickledEnum( - PickledEnumBlink::VALUE_0, - ExpectEnumResult(PickledEnumBlink::VALUE_0, loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(PickleTest, BlinkProxyToChromiumService) { - auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>(); - { - base::RunLoop loop; - blink_proxy->PassPickledStruct( - PickledStructBlink(1, 1), - ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); - loop.Run(); - } - - { - base::RunLoop loop; - blink_proxy->PassPickledEnum( - PickledEnumBlink::VALUE_1, - ExpectEnumResult(PickledEnumBlink::VALUE_1, loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(PickleTest, PickleArray) { - auto proxy = ConnectToChromiumService(); - auto pickles = std::vector<PickledStructChromium>(2); - pickles[0].set_foo(1); - pickles[0].set_bar(2); - pickles[0].set_baz(100); - pickles[1].set_foo(3); - pickles[1].set_bar(4); - pickles[1].set_baz(100); - { - base::RunLoop run_loop; - // Verify that the array of pickled structs can be serialized and - // deserialized intact. This ensures that the ParamTraits are actually used - // rather than doing a byte-for-byte copy of the element data, beacuse the - // |baz| field should never be serialized. - proxy->PassPickles(std::move(pickles), - BindSimpleLambda<std::vector<PickledStructChromium>>( - [&](std::vector<PickledStructChromium> passed) { - ASSERT_EQ(2u, passed.size()); - EXPECT_EQ(1, passed[0].foo()); - EXPECT_EQ(2, passed[0].bar()); - EXPECT_EQ(0, passed[0].baz()); - EXPECT_EQ(3, passed[1].foo()); - EXPECT_EQ(4, passed[1].bar()); - EXPECT_EQ(0, passed[1].baz()); - run_loop.Quit(); - })); - run_loop.Run(); - } -} - -TEST_F(PickleTest, PickleArrayArray) { - auto proxy = ConnectToChromiumService(); - auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2); - for (size_t i = 0; i < 2; ++i) - pickle_arrays[i] = std::vector<PickledStructChromium>(2); - - pickle_arrays[0][0].set_foo(1); - pickle_arrays[0][0].set_bar(2); - pickle_arrays[0][0].set_baz(100); - pickle_arrays[0][1].set_foo(3); - pickle_arrays[0][1].set_bar(4); - pickle_arrays[0][1].set_baz(100); - pickle_arrays[1][0].set_foo(5); - pickle_arrays[1][0].set_bar(6); - pickle_arrays[1][0].set_baz(100); - pickle_arrays[1][1].set_foo(7); - pickle_arrays[1][1].set_bar(8); - pickle_arrays[1][1].set_baz(100); - { - base::RunLoop run_loop; - // Verify that the array-of-arrays serializes and deserializes properly. - proxy->PassPickleArrays( - std::move(pickle_arrays), - BindSimpleLambda<std::vector<std::vector<PickledStructChromium>>>( - [&](std::vector<std::vector<PickledStructChromium>> passed) { - ASSERT_EQ(2u, passed.size()); - ASSERT_EQ(2u, passed[0].size()); - ASSERT_EQ(2u, passed[1].size()); - EXPECT_EQ(1, passed[0][0].foo()); - EXPECT_EQ(2, passed[0][0].bar()); - EXPECT_EQ(0, passed[0][0].baz()); - EXPECT_EQ(3, passed[0][1].foo()); - EXPECT_EQ(4, passed[0][1].bar()); - EXPECT_EQ(0, passed[0][1].baz()); - EXPECT_EQ(5, passed[1][0].foo()); - EXPECT_EQ(6, passed[1][0].bar()); - EXPECT_EQ(0, passed[1][0].baz()); - EXPECT_EQ(7, passed[1][1].foo()); - EXPECT_EQ(8, passed[1][1].bar()); - EXPECT_EQ(0, passed[1][1].baz()); - run_loop.Quit(); - })); - run_loop.Run(); - } -} - -TEST_F(PickleTest, PickleContainer) { - auto proxy = ConnectToChromiumService(); - PickleContainerPtr pickle_container = PickleContainer::New(); - pickle_container->f_struct.set_foo(42); - pickle_container->f_struct.set_bar(43); - pickle_container->f_struct.set_baz(44); - pickle_container->f_enum = PickledEnumChromium::VALUE_1; - EXPECT_TRUE(pickle_container.Equals(pickle_container)); - EXPECT_FALSE(pickle_container.Equals(PickleContainer::New())); - { - base::RunLoop run_loop; - proxy->PassPickleContainer(std::move(pickle_container), - BindSimpleLambda<PickleContainerPtr>( - [&](PickleContainerPtr passed) { - ASSERT_FALSE(passed.is_null()); - EXPECT_EQ(42, passed->f_struct.foo()); - EXPECT_EQ(43, passed->f_struct.bar()); - EXPECT_EQ(0, passed->f_struct.baz()); - EXPECT_EQ(PickledEnumChromium::VALUE_1, - passed->f_enum); - run_loop.Quit(); - })); - run_loop.Run(); - } -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/pickled_types_blink.cc b/mojo/public/cpp/bindings/tests/pickled_types_blink.cc deleted file mode 100644 index 7e55650..0000000 --- a/mojo/public/cpp/bindings/tests/pickled_types_blink.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/pickled_types_blink.h" - -#include "base/logging.h" -#include "base/pickle.h" - -namespace mojo { -namespace test { - -PickledStructBlink::PickledStructBlink() {} - -PickledStructBlink::PickledStructBlink(int foo, int bar) - : foo_(foo), bar_(bar) { - DCHECK_GE(foo_, 0); - DCHECK_GE(bar_, 0); -} - -PickledStructBlink::~PickledStructBlink() {} - -} // namespace test -} // namespace mojo - -namespace IPC { - -void ParamTraits<mojo::test::PickledStructBlink>::GetSize( - base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt(); - sizer->AddInt(); -} - -void ParamTraits<mojo::test::PickledStructBlink>::Write(base::Pickle* m, - const param_type& p) { - m->WriteInt(p.foo()); - m->WriteInt(p.bar()); -} - -bool ParamTraits<mojo::test::PickledStructBlink>::Read( - const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - int foo, bar; - if (!iter->ReadInt(&foo) || !iter->ReadInt(&bar) || foo < 0 || bar < 0) - return false; - - p->set_foo(foo); - p->set_bar(bar); - return true; -} - -#include "ipc/param_traits_size_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumBlink, - mojo::test::PickledEnumBlink::VALUE_1) -#include "ipc/param_traits_write_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumBlink, - mojo::test::PickledEnumBlink::VALUE_1) -#include "ipc/param_traits_read_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumBlink, - mojo::test::PickledEnumBlink::VALUE_1) -#include "ipc/param_traits_log_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumBlink, - mojo::test::PickledEnumBlink::VALUE_1) - -} // namespace IPC diff --git a/mojo/public/cpp/bindings/tests/pickled_types_blink.h b/mojo/public/cpp/bindings/tests/pickled_types_blink.h deleted file mode 100644 index 37e9e70..0000000 --- a/mojo/public/cpp/bindings/tests/pickled_types_blink.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_BLINK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_BLINK_H_ - -#include <stddef.h> - -#include <string> - -#include "base/logging.h" -#include "base/macros.h" -#include "ipc/ipc_message_macros.h" -#include "ipc/ipc_param_traits.h" - -namespace base { -class Pickle; -class PickleIterator; -class PickleSizer; -} - -namespace mojo { -namespace test { - -// Implementation of types with IPC::ParamTraits for consumers in Blink. - -enum class PickledEnumBlink { VALUE_0, VALUE_1 }; - -// To make things slightly more interesting, this variation of the type doesn't -// support negative values. It'll DCHECK if you try to construct it with any, -// and it will fail deserialization if negative values are decoded. -class PickledStructBlink { - public: - PickledStructBlink(); - PickledStructBlink(int foo, int bar); - PickledStructBlink(PickledStructBlink&& other) = default; - ~PickledStructBlink(); - - PickledStructBlink& operator=(PickledStructBlink&& other) = default; - - int foo() const { return foo_; } - void set_foo(int foo) { - DCHECK_GE(foo, 0); - foo_ = foo; - } - - int bar() const { return bar_; } - void set_bar(int bar) { - DCHECK_GE(bar, 0); - bar_ = bar; - } - - // The |baz| field should never be serialized. - int baz() const { return baz_; } - void set_baz(int baz) { baz_ = baz; } - - private: - int foo_ = 0; - int bar_ = 0; - int baz_ = 0; - - DISALLOW_COPY_AND_ASSIGN(PickledStructBlink); -}; - -} // namespace test -} // namespace mojo - -namespace IPC { - -template <> -struct ParamTraits<mojo::test::PickledStructBlink> { - using param_type = mojo::test::PickledStructBlink; - - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l) {} -}; - -} // namespace IPC - -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumBlink, - mojo::test::PickledEnumBlink::VALUE_1) - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_BLINK_H_ diff --git a/mojo/public/cpp/bindings/tests/pickled_types_chromium.cc b/mojo/public/cpp/bindings/tests/pickled_types_chromium.cc deleted file mode 100644 index 9957c9a..0000000 --- a/mojo/public/cpp/bindings/tests/pickled_types_chromium.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/pickled_types_chromium.h" - -#include "base/pickle.h" - -namespace mojo { -namespace test { - -PickledStructChromium::PickledStructChromium() {} - -PickledStructChromium::PickledStructChromium(int foo, int bar) - : foo_(foo), bar_(bar) {} - -PickledStructChromium::~PickledStructChromium() {} - -bool operator==(const PickledStructChromium& a, - const PickledStructChromium& b) { - return a.foo() == b.foo() && a.bar() == b.bar() && a.baz() == b.baz(); -} - -} // namespace test -} // namespace mojo - -namespace IPC { - -void ParamTraits<mojo::test::PickledStructChromium>::GetSize( - base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt(); - sizer->AddInt(); -} - -void ParamTraits<mojo::test::PickledStructChromium>::Write( - base::Pickle* m, - const param_type& p) { - m->WriteInt(p.foo()); - m->WriteInt(p.bar()); -} - -bool ParamTraits<mojo::test::PickledStructChromium>::Read( - const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - int foo, bar; - if (!iter->ReadInt(&foo) || !iter->ReadInt(&bar)) - return false; - - p->set_foo(foo); - p->set_bar(bar); - return true; -} - -#include "ipc/param_traits_size_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumChromium, - mojo::test::PickledEnumChromium::VALUE_2) -#include "ipc/param_traits_write_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumChromium, - mojo::test::PickledEnumChromium::VALUE_2) -#include "ipc/param_traits_read_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumChromium, - mojo::test::PickledEnumChromium::VALUE_2) -#include "ipc/param_traits_log_macros.h" -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumChromium, - mojo::test::PickledEnumChromium::VALUE_2) - -} // namespace IPC diff --git a/mojo/public/cpp/bindings/tests/pickled_types_chromium.h b/mojo/public/cpp/bindings/tests/pickled_types_chromium.h deleted file mode 100644 index d9287b6..0000000 --- a/mojo/public/cpp/bindings/tests/pickled_types_chromium.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_CHROMIUM_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_CHROMIUM_H_ - -#include <stddef.h> - -#include <string> - -#include "base/macros.h" -#include "ipc/ipc_message_macros.h" -#include "ipc/ipc_param_traits.h" - -namespace base { -class Pickle; -class PickleIterator; -class PickleSizer; -} - -namespace mojo { -namespace test { - -// Implementation of types with IPC::ParamTraits for consumers in the greater -// Chromium tree. - -enum class PickledEnumChromium { VALUE_0, VALUE_1, VALUE_2 }; - -class PickledStructChromium { - public: - PickledStructChromium(); - PickledStructChromium(int foo, int bar); - PickledStructChromium(PickledStructChromium&& other) = default; - ~PickledStructChromium(); - - PickledStructChromium& operator=(PickledStructChromium&& other) = default; - - int foo() const { return foo_; } - void set_foo(int foo) { foo_ = foo; } - - int bar() const { return bar_; } - void set_bar(int bar) { bar_ = bar; } - - // The |baz| field should never be serialized. - int baz() const { return baz_; } - void set_baz(int baz) { baz_ = baz; } - - private: - int foo_ = 0; - int bar_ = 0; - int baz_ = 0; - - DISALLOW_COPY_AND_ASSIGN(PickledStructChromium); -}; - -bool operator==(const PickledStructChromium& a, const PickledStructChromium& b); - -} // namespace test -} // namespace mojo - -namespace IPC { - -template <> -struct ParamTraits<mojo::test::PickledStructChromium> { - using param_type = mojo::test::PickledStructChromium; - - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l) {} -}; - -} // namespace IPC - -IPC_ENUM_TRAITS_MAX_VALUE(mojo::test::PickledEnumChromium, - mojo::test::PickledEnumChromium::VALUE_2) - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_PICKLED_TYPES_CHROMIUM_H_ diff --git a/mojo/public/cpp/bindings/tests/rect_blink.h b/mojo/public/cpp/bindings/tests/rect_blink.h deleted file mode 100644 index 7335989..0000000 --- a/mojo/public/cpp/bindings/tests/rect_blink.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_H_ - -#include "base/logging.h" - -namespace mojo { -namespace test { - -// An implementation of a hypothetical Rect type specifically for consumers in -// in Blink. Unlike the Chromium variant (see rect_chromium.h) this does not -// support negative origin coordinates and is not copyable. -class RectBlink { - public: - RectBlink() {} - RectBlink(int x, int y, int width, int height) : - x_(x), y_(y), width_(width), height_(height) { - DCHECK_GE(x_, 0); - DCHECK_GE(y_, 0); - DCHECK_GE(width_, 0); - DCHECK_GE(height_, 0); - } - ~RectBlink() {} - - int x() const { return x_; } - void setX(int x) { - DCHECK_GE(x, 0); - x_ = x; - } - - int y() const { return y_; } - void setY(int y) { - DCHECK_GE(y, 0); - y_ = y; - } - - int width() const { return width_; } - void setWidth(int width) { - DCHECK_GE(width, 0); - width_ = width; - } - - int height() const { return height_; } - void setHeight(int height) { - DCHECK_GE(height, 0); - height_ = height; - } - - int computeArea() const { return width_ * height_; } - - bool operator==(const RectBlink& other) const { - return (x() == other.x() && y() == other.y() && width() == other.width() && - height() == other.height()); - } - bool operator!=(const RectBlink& other) const { return !(*this == other); } - - private: - int x_ = 0; - int y_ = 0; - int width_ = 0; - int height_ = 0; -}; - -} // namespace test -} // namespace mojo - -namespace std { - -template <> -struct hash<mojo::test::RectBlink> { - size_t operator()(const mojo::test::RectBlink& value) { - // Terrible hash function: - return (std::hash<int>()(value.x()) ^ std::hash<int>()(value.y()) ^ - std::hash<int>()(value.width()) ^ std::hash<int>()(value.height())); - } -}; - -} // namespace std - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_H_ diff --git a/mojo/public/cpp/bindings/tests/rect_blink.typemap b/mojo/public/cpp/bindings/tests/rect_blink.typemap deleted file mode 100644 index 657ea1a..0000000 --- a/mojo/public/cpp/bindings/tests/rect_blink.typemap +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/public/interfaces/bindings/tests/rect.mojom" -public_headers = [ - "//mojo/public/cpp/bindings/tests/rect_blink.h", - "//mojo/public/cpp/bindings/tests/shared_rect.h", -] -traits_headers = [ - "//mojo/public/cpp/bindings/tests/rect_blink_traits.h", - "//mojo/public/cpp/bindings/tests/shared_rect_traits.h", -] - -type_mappings = [ - "mojo.test.TypemappedRect=mojo::test::RectBlink[hashable]", - "mojo.test.SharedTypemappedRect=mojo::test::SharedRect", -] diff --git a/mojo/public/cpp/bindings/tests/rect_blink_traits.h b/mojo/public/cpp/bindings/tests/rect_blink_traits.h deleted file mode 100644 index 7258739..0000000 --- a/mojo/public/cpp/bindings/tests/rect_blink_traits.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_TRAITS_H_ - -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/tests/rect_blink.h" -#include "mojo/public/interfaces/bindings/tests/rect.mojom-blink.h" - -namespace mojo { - -template <> -struct StructTraits<test::TypemappedRectDataView, test::RectBlink> { - static int x(const test::RectBlink& r) { return r.x(); } - static int y(const test::RectBlink& r) { return r.y(); } - static int width(const test::RectBlink& r) { return r.width(); } - static int height(const test::RectBlink& r) { return r.height(); } - - static bool Read(test::TypemappedRectDataView r, test::RectBlink* out) { - if (r.x() < 0 || r.y() < 0 || r.width() < 0 || r.height() < 0) { - return false; - } - out->setX(r.x()); - out->setY(r.y()); - out->setWidth(r.width()); - out->setHeight(r.height()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_BLINK_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/tests/rect_chromium.h b/mojo/public/cpp/bindings/tests/rect_chromium.h deleted file mode 100644 index d2e0a3e..0000000 --- a/mojo/public/cpp/bindings/tests/rect_chromium.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_H_ - -#include "base/logging.h" - -namespace mojo { -namespace test { - -// An implementation of a hypothetical Rect type specifically for consumers in -// in Chromium. -class RectChromium { - public: - RectChromium() {} - RectChromium(const RectChromium& other) - : x_(other.x_), - y_(other.y_), - width_(other.width_), - height_(other.height_) {} - RectChromium(int x, int y, int width, int height) : - x_(x), y_(y), width_(width), height_(height) { - DCHECK_GE(width_, 0); - DCHECK_GE(height_, 0); - } - ~RectChromium() {} - - RectChromium& operator=(const RectChromium& other) { - x_ = other.x_; - y_ = other.y_; - width_ = other.width_; - height_ = other.height_; - return *this; - } - - int x() const { return x_; } - void set_x(int x) { x_ = x; } - - int y() const { return y_; } - void set_y(int y) { y_ = y; } - - int width() const { return width_; } - void set_width(int width) { - DCHECK_GE(width, 0); - width_ = width; - } - - int height() const { return height_; } - void set_height(int height) { - DCHECK_GE(height, 0); - height_ = height; - } - - int GetArea() const { return width_ * height_; } - - bool operator==(const RectChromium& other) const { - return (x() == other.x() && y() == other.y() && width() == other.width() && - height() == other.height()); - } - bool operator!=(const RectChromium& other) const { return !(*this == other); } - - private: - int x_ = 0; - int y_ = 0; - int width_ = 0; - int height_ = 0; -}; - -} // namespace test -} // namespace mojo - -namespace std { - -template <> -struct hash<mojo::test::RectChromium> { - size_t operator()(const mojo::test::RectChromium& value) { - // Terrible hash function: - return (std::hash<int>()(value.x()) ^ std::hash<int>()(value.y()) ^ - std::hash<int>()(value.width()) ^ std::hash<int>()(value.height())); - } -}; - -} // namespace std - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_H_ diff --git a/mojo/public/cpp/bindings/tests/rect_chromium.typemap b/mojo/public/cpp/bindings/tests/rect_chromium.typemap deleted file mode 100644 index 7e5df84..0000000 --- a/mojo/public/cpp/bindings/tests/rect_chromium.typemap +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/public/interfaces/bindings/tests/rect.mojom" -public_headers = [ - "//mojo/public/cpp/bindings/tests/rect_chromium.h", - "//mojo/public/cpp/bindings/tests/shared_rect.h", -] -traits_headers = [ - "//mojo/public/cpp/bindings/tests/rect_chromium_traits.h", - "//mojo/public/cpp/bindings/tests/shared_rect_traits.h", -] - -type_mappings = [ - "mojo.test.TypemappedRect=mojo::test::RectChromium[hashable]", - "mojo.test.SharedTypemappedRect=mojo::test::SharedRect", -] diff --git a/mojo/public/cpp/bindings/tests/rect_chromium_traits.h b/mojo/public/cpp/bindings/tests/rect_chromium_traits.h deleted file mode 100644 index b446d7d..0000000 --- a/mojo/public/cpp/bindings/tests/rect_chromium_traits.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_TRAITS_H_ - -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/tests/rect_chromium.h" -#include "mojo/public/interfaces/bindings/tests/rect.mojom.h" - -namespace mojo { - -template <> -struct StructTraits<test::TypemappedRectDataView, test::RectChromium> { - static int x(const test::RectChromium& r) { return r.x(); } - static int y(const test::RectChromium& r) { return r.y(); } - static int width(const test::RectChromium& r) { return r.width(); } - static int height(const test::RectChromium& r) { return r.height(); } - - static bool Read(test::TypemappedRectDataView r, test::RectChromium* out) { - if (r.width() < 0 || r.height() < 0) - return false; - out->set_x(r.x()); - out->set_y(r.y()); - out->set_width(r.width()); - out->set_height(r.height()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_RECT_CHROMIUM_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc b/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc deleted file mode 100644 index 1bf3f7a..0000000 --- a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/interfaces/bindings/tests/test_bad_messages.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -class TestBadMessagesImpl : public TestBadMessages { - public: - TestBadMessagesImpl() : binding_(this) {} - ~TestBadMessagesImpl() override {} - - void BindImpl(TestBadMessagesRequest request) { - binding_.Bind(std::move(request)); - } - - const ReportBadMessageCallback& bad_message_callback() { - return bad_message_callback_; - } - - private: - // TestBadMessages: - void RejectEventually(const RejectEventuallyCallback& callback) override { - bad_message_callback_ = GetBadMessageCallback(); - callback.Run(); - } - - void RequestResponse(const RequestResponseCallback& callback) override { - callback.Run(); - } - - void RejectSync(const RejectSyncCallback& callback) override { - callback.Run(); - ReportBadMessage("go away"); - } - - void RequestResponseSync( - const RequestResponseSyncCallback& callback) override { - callback.Run(); - } - - ReportBadMessageCallback bad_message_callback_; - mojo::Binding<TestBadMessages> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestBadMessagesImpl); -}; - -class ReportBadMessageTest : public testing::Test { - public: - ReportBadMessageTest() {} - - void SetUp() override { - mojo::edk::SetDefaultProcessErrorCallback( - base::Bind(&ReportBadMessageTest::OnProcessError, - base::Unretained(this))); - - impl_.BindImpl(MakeRequest(&proxy_)); - } - - void TearDown() override { - mojo::edk::SetDefaultProcessErrorCallback( - mojo::edk::ProcessErrorCallback()); - } - - TestBadMessages* proxy() { return proxy_.get(); } - - TestBadMessagesImpl* impl() { return &impl_; } - - void SetErrorHandler(const base::Closure& handler) { - error_handler_ = handler; - } - - private: - void OnProcessError(const std::string& error) { - if (!error_handler_.is_null()) - error_handler_.Run(); - } - - TestBadMessagesPtr proxy_; - TestBadMessagesImpl impl_; - base::Closure error_handler_; - base::MessageLoop message_loop; -}; - -TEST_F(ReportBadMessageTest, Request) { - // Verify that basic immediate error reporting works. - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - EXPECT_TRUE(proxy()->RejectSync()); - EXPECT_TRUE(error); -} - -TEST_F(ReportBadMessageTest, RequestAsync) { - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - - // This should capture a bad message reporting callback in the impl. - base::RunLoop loop; - proxy()->RejectEventually(loop.QuitClosure()); - loop.Run(); - - EXPECT_FALSE(error); - - // Now we can run the callback and it should trigger a bad message report. - DCHECK(!impl()->bad_message_callback().is_null()); - impl()->bad_message_callback().Run("bad!"); - EXPECT_TRUE(error); -} - -TEST_F(ReportBadMessageTest, Response) { - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - - base::RunLoop loop; - proxy()->RequestResponse( - base::Bind([] (const base::Closure& quit) { - // Report a bad message inside the response callback. This should - // trigger the error handler. - ReportBadMessage("no way!"); - quit.Run(); - }, - loop.QuitClosure())); - loop.Run(); - - EXPECT_TRUE(error); -} - -TEST_F(ReportBadMessageTest, ResponseAsync) { - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - - ReportBadMessageCallback bad_message_callback; - base::RunLoop loop; - proxy()->RequestResponse( - base::Bind([] (const base::Closure& quit, - ReportBadMessageCallback* callback) { - // Capture the bad message callback inside the response callback. - *callback = GetBadMessageCallback(); - quit.Run(); - }, - loop.QuitClosure(), &bad_message_callback)); - loop.Run(); - - EXPECT_FALSE(error); - - // Invoking this callback should report a bad message and trigger the error - // handler immediately. - bad_message_callback.Run("this message is bad and should feel bad"); - EXPECT_TRUE(error); -} - -TEST_F(ReportBadMessageTest, ResponseSync) { - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - - SyncMessageResponseContext context; - proxy()->RequestResponseSync(); - - EXPECT_FALSE(error); - context.ReportBadMessage("i don't like this response"); - EXPECT_TRUE(error); -} - -TEST_F(ReportBadMessageTest, ResponseSyncDeferred) { - bool error = false; - SetErrorHandler(base::Bind([] (bool* flag) { *flag = true; }, &error)); - - ReportBadMessageCallback bad_message_callback; - { - SyncMessageResponseContext context; - proxy()->RequestResponseSync(); - bad_message_callback = context.GetBadMessageCallback(); - } - - EXPECT_FALSE(error); - bad_message_callback.Run("nope nope nope"); - EXPECT_TRUE(error); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/mojo/public/cpp/bindings/tests/request_response_unittest.cc deleted file mode 100644 index 43b8f0d..0000000 --- a/mojo/public/cpp/bindings/tests/request_response_unittest.cc +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> -#include <utility> - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "mojo/public/interfaces/bindings/tests/sample_import.mojom.h" -#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -class ProviderImpl : public sample::Provider { - public: - explicit ProviderImpl(InterfaceRequest<sample::Provider> request) - : binding_(this, std::move(request)) {} - - void EchoString(const std::string& a, - const EchoStringCallback& callback) override { - EchoStringCallback callback_copy; - // Make sure operator= is used. - callback_copy = callback; - callback_copy.Run(a); - } - - void EchoStrings(const std::string& a, - const std::string& b, - const EchoStringsCallback& callback) override { - callback.Run(a, b); - } - - void EchoMessagePipeHandle( - ScopedMessagePipeHandle a, - const EchoMessagePipeHandleCallback& callback) override { - callback.Run(std::move(a)); - } - - void EchoEnum(sample::Enum a, const EchoEnumCallback& callback) override { - callback.Run(a); - } - - void EchoInt(int32_t a, const EchoIntCallback& callback) override { - callback.Run(a); - } - - Binding<sample::Provider> binding_; -}; - -void RecordString(std::string* storage, - const base::Closure& closure, - const std::string& str) { - *storage = str; - closure.Run(); -} - -void RecordStrings(std::string* storage, - const base::Closure& closure, - const std::string& a, - const std::string& b) { - *storage = a + b; - closure.Run(); -} - -void WriteToMessagePipe(const char* text, - const base::Closure& closure, - ScopedMessagePipeHandle handle) { - WriteTextMessage(handle.get(), text); - closure.Run(); -} - -void RecordEnum(sample::Enum* storage, - const base::Closure& closure, - sample::Enum value) { - *storage = value; - closure.Run(); -} - -class RequestResponseTest : public testing::Test { - public: - RequestResponseTest() {} - ~RequestResponseTest() override { base::RunLoop().RunUntilIdle(); } - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - private: - base::MessageLoop loop_; -}; - -TEST_F(RequestResponseTest, EchoString) { - sample::ProviderPtr provider; - ProviderImpl provider_impl(MakeRequest(&provider)); - - std::string buf; - base::RunLoop run_loop; - provider->EchoString("hello", - base::Bind(&RecordString, &buf, run_loop.QuitClosure())); - - run_loop.Run(); - - EXPECT_EQ(std::string("hello"), buf); -} - -TEST_F(RequestResponseTest, EchoStrings) { - sample::ProviderPtr provider; - ProviderImpl provider_impl(MakeRequest(&provider)); - - std::string buf; - base::RunLoop run_loop; - provider->EchoStrings("hello", " world", base::Bind(&RecordStrings, &buf, - run_loop.QuitClosure())); - - run_loop.Run(); - - EXPECT_EQ(std::string("hello world"), buf); -} - -TEST_F(RequestResponseTest, EchoMessagePipeHandle) { - sample::ProviderPtr provider; - ProviderImpl provider_impl(MakeRequest(&provider)); - - MessagePipe pipe2; - base::RunLoop run_loop; - provider->EchoMessagePipeHandle( - std::move(pipe2.handle1), - base::Bind(&WriteToMessagePipe, "hello", run_loop.QuitClosure())); - - run_loop.Run(); - - std::string value; - ReadTextMessage(pipe2.handle0.get(), &value); - - EXPECT_EQ(std::string("hello"), value); -} - -TEST_F(RequestResponseTest, EchoEnum) { - sample::ProviderPtr provider; - ProviderImpl provider_impl(MakeRequest(&provider)); - - sample::Enum value; - base::RunLoop run_loop; - provider->EchoEnum(sample::Enum::VALUE, - base::Bind(&RecordEnum, &value, run_loop.QuitClosure())); - run_loop.Run(); - - EXPECT_EQ(sample::Enum::VALUE, value); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/router_test_util.cc b/mojo/public/cpp/bindings/tests/router_test_util.cc deleted file mode 100644 index 9bab1cb..0000000 --- a/mojo/public/cpp/bindings/tests/router_test_util.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/router_test_util.h" - -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/tests/message_queue.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { - -void AllocRequestMessage(uint32_t name, const char* text, Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(name, Message::kFlagExpectsResponse, - payload_size, 0); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - *message = std::move(*builder.message()); -} - -void AllocResponseMessage(uint32_t name, - const char* text, - uint64_t request_id, - Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::MessageBuilder builder(name, Message::kFlagIsResponse, payload_size, - 0); - builder.message()->set_request_id(request_id); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - *message = std::move(*builder.message()); -} - -MessageAccumulator::MessageAccumulator(MessageQueue* queue, - const base::Closure& closure) - : queue_(queue), closure_(closure) {} - -MessageAccumulator::~MessageAccumulator() {} - -bool MessageAccumulator::Accept(Message* message) { - queue_->Push(message); - if (!closure_.is_null()) { - closure_.Run(); - closure_.Reset(); - } - return true; -} - -ResponseGenerator::ResponseGenerator() {} - -bool ResponseGenerator::Accept(Message* message) { - return false; -} - -bool ResponseGenerator::AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) { - EXPECT_TRUE(message->has_flag(Message::kFlagExpectsResponse)); - - bool result = SendResponse(message->name(), message->request_id(), - reinterpret_cast<const char*>(message->payload()), - responder.get()); - EXPECT_TRUE(responder->IsValid()); - return result; -} - -bool ResponseGenerator::SendResponse(uint32_t name, - uint64_t request_id, - const char* request_string, - MessageReceiver* responder) { - Message response; - std::string response_string(request_string); - response_string += " world!"; - AllocResponseMessage(name, response_string.c_str(), request_id, &response); - - return responder->Accept(&response); -} - -LazyResponseGenerator::LazyResponseGenerator(const base::Closure& closure) - : responder_(nullptr), name_(0), request_id_(0), closure_(closure) {} - -LazyResponseGenerator::~LazyResponseGenerator() = default; - -bool LazyResponseGenerator::AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) { - name_ = message->name(); - request_id_ = message->request_id(); - request_string_ = - std::string(reinterpret_cast<const char*>(message->payload())); - responder_ = std::move(responder); - if (!closure_.is_null()) { - closure_.Run(); - closure_.Reset(); - } - return true; -} - -void LazyResponseGenerator::Complete(bool send_response) { - if (send_response) { - SendResponse(name_, request_id_, request_string_.c_str(), responder_.get()); - } - responder_ = nullptr; -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/router_test_util.h b/mojo/public/cpp/bindings/tests/router_test_util.h deleted file mode 100644 index dd6aff6..0000000 --- a/mojo/public/cpp/bindings/tests/router_test_util.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_ - -#include <stdint.h> - -#include <string> - -#include "base/callback.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace test { - -class MessageQueue; - -void AllocRequestMessage(uint32_t name, const char* text, Message* message); -void AllocResponseMessage(uint32_t name, - const char* text, - uint64_t request_id, - Message* message); - -class MessageAccumulator : public MessageReceiver { - public: - MessageAccumulator(MessageQueue* queue, - const base::Closure& closure = base::Closure()); - ~MessageAccumulator() override; - - bool Accept(Message* message) override; - - private: - MessageQueue* queue_; - base::Closure closure_; -}; - -class ResponseGenerator : public MessageReceiverWithResponderStatus { - public: - ResponseGenerator(); - - bool Accept(Message* message) override; - - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) override; - bool SendResponse(uint32_t name, - uint64_t request_id, - const char* request_string, - MessageReceiver* responder); -}; - -class LazyResponseGenerator : public ResponseGenerator { - public: - explicit LazyResponseGenerator( - const base::Closure& closure = base::Closure()); - - ~LazyResponseGenerator() override; - - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiverWithStatus> responder) override; - - bool has_responder() const { return !!responder_; } - - bool responder_is_valid() const { return responder_->IsValid(); } - - void set_closure(const base::Closure& closure) { closure_ = closure; } - - // Sends the response and delete the responder. - void CompleteWithResponse() { Complete(true); } - - // Deletes the responder without sending a response. - void CompleteWithoutResponse() { Complete(false); } - - private: - // Completes the request handling by deleting responder_. Optionally - // also sends a response. - void Complete(bool send_response); - - std::unique_ptr<MessageReceiverWithStatus> responder_; - uint32_t name_; - uint64_t request_id_; - std::string request_string_; - base::Closure closure_; -}; - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_ diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc deleted file mode 100644 index 1f95a27..0000000 --- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <algorithm> -#include <ostream> -#include <string> -#include <utility> - -#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { - -template <> -struct TypeConverter<int32_t, sample::BarPtr> { - static int32_t Convert(const sample::BarPtr& bar) { - return static_cast<int32_t>(bar->alpha) << 16 | - static_cast<int32_t>(bar->beta) << 8 | - static_cast<int32_t>(bar->gamma); - } -}; - -} // namespace mojo - -namespace sample { -namespace { - -// Set this variable to true to print the message in hex. -bool g_dump_message_as_hex = false; - -// Set this variable to true to print the message in human readable form. -bool g_dump_message_as_text = false; - -// Make a sample |Foo|. -FooPtr MakeFoo() { - std::string name("foopy"); - - BarPtr bar(Bar::New(20, 40, 60, Bar::Type::VERTICAL)); - - std::vector<BarPtr> extra_bars(3); - for (size_t i = 0; i < extra_bars.size(); ++i) { - Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL; - uint8_t base = static_cast<uint8_t>(i * 100); - extra_bars[i] = Bar::New(base, base + 20, base + 40, type); - } - - std::vector<uint8_t> data(10); - for (size_t i = 0; i < data.size(); ++i) - data[i] = static_cast<uint8_t>(data.size() - i); - - std::vector<mojo::ScopedDataPipeConsumerHandle> input_streams(2); - std::vector<mojo::ScopedDataPipeProducerHandle> output_streams(2); - for (size_t i = 0; i < input_streams.size(); ++i) { - MojoCreateDataPipeOptions options; - options.struct_size = sizeof(MojoCreateDataPipeOptions); - options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; - options.element_num_bytes = 1; - options.capacity_num_bytes = 1024; - mojo::ScopedDataPipeProducerHandle producer; - mojo::ScopedDataPipeConsumerHandle consumer; - mojo::CreateDataPipe(&options, &producer, &consumer); - input_streams[i] = std::move(consumer); - output_streams[i] = std::move(producer); - } - - std::vector<std::vector<bool>> array_of_array_of_bools(2); - for (size_t i = 0; i < 2; ++i) { - std::vector<bool> array_of_bools(2); - for (size_t j = 0; j < 2; ++j) - array_of_bools[j] = j; - array_of_array_of_bools[i] = std::move(array_of_bools); - } - - mojo::MessagePipe pipe; - return Foo::New(name, 1, 2, false, true, false, std::move(bar), - std::move(extra_bars), std::move(data), - std::move(pipe.handle1), std::move(input_streams), - std::move(output_streams), std::move(array_of_array_of_bools), - base::nullopt, base::nullopt); -} - -// Check that the given |Foo| is identical to the one made by |MakeFoo()|. -void CheckFoo(const Foo& foo) { - const std::string kName("foopy"); - EXPECT_EQ(kName.size(), foo.name.size()); - for (size_t i = 0; i < std::min(kName.size(), foo.name.size()); i++) { - // Test both |operator[]| and |at|. - EXPECT_EQ(kName[i], foo.name.at(i)) << i; - EXPECT_EQ(kName[i], foo.name[i]) << i; - } - EXPECT_EQ(kName, foo.name); - - EXPECT_EQ(1, foo.x); - EXPECT_EQ(2, foo.y); - EXPECT_FALSE(foo.a); - EXPECT_TRUE(foo.b); - EXPECT_FALSE(foo.c); - - EXPECT_EQ(20, foo.bar->alpha); - EXPECT_EQ(40, foo.bar->beta); - EXPECT_EQ(60, foo.bar->gamma); - EXPECT_EQ(Bar::Type::VERTICAL, foo.bar->type); - - EXPECT_EQ(3u, foo.extra_bars->size()); - for (size_t i = 0; i < foo.extra_bars->size(); i++) { - uint8_t base = static_cast<uint8_t>(i * 100); - Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL; - EXPECT_EQ(base, (*foo.extra_bars)[i]->alpha) << i; - EXPECT_EQ(base + 20, (*foo.extra_bars)[i]->beta) << i; - EXPECT_EQ(base + 40, (*foo.extra_bars)[i]->gamma) << i; - EXPECT_EQ(type, (*foo.extra_bars)[i]->type) << i; - } - - EXPECT_EQ(10u, foo.data->size()); - for (size_t i = 0; i < foo.data->size(); ++i) { - EXPECT_EQ(static_cast<uint8_t>(foo.data->size() - i), (*foo.data)[i]) << i; - } - - EXPECT_TRUE(foo.input_streams); - EXPECT_EQ(2u, foo.input_streams->size()); - - EXPECT_TRUE(foo.output_streams); - EXPECT_EQ(2u, foo.output_streams->size()); - - EXPECT_EQ(2u, foo.array_of_array_of_bools->size()); - for (size_t i = 0; i < foo.array_of_array_of_bools->size(); ++i) { - EXPECT_EQ(2u, (*foo.array_of_array_of_bools)[i].size()); - for (size_t j = 0; j < (*foo.array_of_array_of_bools)[i].size(); ++j) { - EXPECT_EQ(bool(j), (*foo.array_of_array_of_bools)[i][j]); - } - } -} - -void PrintSpacer(int depth) { - for (int i = 0; i < depth; ++i) - std::cout << " "; -} - -void Print(int depth, const char* name, bool value) { - PrintSpacer(depth); - std::cout << name << ": " << (value ? "true" : "false") << std::endl; -} - -void Print(int depth, const char* name, int32_t value) { - PrintSpacer(depth); - std::cout << name << ": " << value << std::endl; -} - -void Print(int depth, const char* name, uint8_t value) { - PrintSpacer(depth); - std::cout << name << ": " << uint32_t(value) << std::endl; -} - -template <typename H> -void Print(int depth, - const char* name, - const mojo::ScopedHandleBase<H>& value) { - PrintSpacer(depth); - std::cout << name << ": 0x" << std::hex << value.get().value() << std::endl; -} - -void Print(int depth, const char* name, const std::string& str) { - PrintSpacer(depth); - std::cout << name << ": \"" << str << "\"" << std::endl; -} - -void Print(int depth, const char* name, const BarPtr& bar) { - PrintSpacer(depth); - std::cout << name << ":" << std::endl; - if (!bar.is_null()) { - ++depth; - Print(depth, "alpha", bar->alpha); - Print(depth, "beta", bar->beta); - Print(depth, "gamma", bar->gamma); - Print(depth, "packed", bar.To<int32_t>()); - --depth; - } -} - -template <typename T> -void Print(int depth, const char* name, const std::vector<T>& array) { - PrintSpacer(depth); - std::cout << name << ":" << std::endl; - ++depth; - for (size_t i = 0; i < array.size(); ++i) { - std::stringstream buf; - buf << i; - Print(depth, buf.str().data(), array.at(i)); - } - --depth; -} - -template <typename T> -void Print(int depth, - const char* name, - const base::Optional<std::vector<T>>& array) { - if (array) - Print(depth, name, *array); - else - Print(depth, name, std::vector<T>()); -} - -void Print(int depth, const char* name, const FooPtr& foo) { - PrintSpacer(depth); - std::cout << name << ":" << std::endl; - if (!foo.is_null()) { - ++depth; - Print(depth, "name", foo->name); - Print(depth, "x", foo->x); - Print(depth, "y", foo->y); - Print(depth, "a", foo->a); - Print(depth, "b", foo->b); - Print(depth, "c", foo->c); - Print(depth, "bar", foo->bar); - Print(depth, "extra_bars", foo->extra_bars); - Print(depth, "data", foo->data); - Print(depth, "source", foo->source); - Print(depth, "input_streams", foo->input_streams); - Print(depth, "output_streams", foo->output_streams); - Print(depth, "array_of_array_of_bools", foo->array_of_array_of_bools); - --depth; - } -} - -void DumpHex(const uint8_t* bytes, uint32_t num_bytes) { - for (uint32_t i = 0; i < num_bytes; ++i) { - std::cout << std::setw(2) << std::setfill('0') << std::hex - << uint32_t(bytes[i]); - - if (i % 16 == 15) { - std::cout << std::endl; - continue; - } - - if (i % 2 == 1) - std::cout << " "; - if (i % 8 == 7) - std::cout << " "; - } -} - -class ServiceImpl : public Service { - public: - void Frobinate(FooPtr foo, - BazOptions baz, - PortPtr port, - const Service::FrobinateCallback& callback) override { - // Users code goes here to handle the incoming Frobinate message. - - // We mainly check that we're given the expected arguments. - EXPECT_FALSE(foo.is_null()); - if (!foo.is_null()) - CheckFoo(*foo); - EXPECT_EQ(BazOptions::EXTRA, baz); - - if (g_dump_message_as_text) { - // Also dump the Foo structure and all of its members. - std::cout << "Frobinate:" << std::endl; - int depth = 1; - Print(depth, "foo", foo); - Print(depth, "baz", static_cast<int32_t>(baz)); - Print(depth, "port", port.get()); - } - callback.Run(5); - } - - void GetPort(mojo::InterfaceRequest<Port> port_request) override {} -}; - -class ServiceProxyImpl : public ServiceProxy { - public: - explicit ServiceProxyImpl(mojo::MessageReceiverWithResponder* receiver) - : ServiceProxy(receiver) {} -}; - -class SimpleMessageReceiver : public mojo::MessageReceiverWithResponder { - public: - bool Accept(mojo::Message* message) override { - // Imagine some IPC happened here. - - if (g_dump_message_as_hex) { - DumpHex(reinterpret_cast<const uint8_t*>(message->data()), - message->data_num_bytes()); - } - - // In the receiving process, an implementation of ServiceStub is known to - // the system. It receives the incoming message. - ServiceImpl impl; - - ServiceStub<> stub; - stub.set_sink(&impl); - return stub.Accept(message); - } - - bool AcceptWithResponder( - mojo::Message* message, - std::unique_ptr<mojo::MessageReceiver> responder) override { - return false; - } -}; - -using BindingsSampleTest = testing::Test; - -TEST_F(BindingsSampleTest, Basic) { - SimpleMessageReceiver receiver; - - // User has a proxy to a Service somehow. - Service* service = new ServiceProxyImpl(&receiver); - - // User constructs a message to send. - - // Notice that it doesn't matter in what order the structs / arrays are - // allocated. Here, the various members of Foo are allocated before Foo is - // allocated. - - FooPtr foo = MakeFoo(); - CheckFoo(*foo); - - PortPtr port; - service->Frobinate(std::move(foo), Service::BazOptions::EXTRA, - std::move(port), Service::FrobinateCallback()); - - delete service; -} - -TEST_F(BindingsSampleTest, DefaultValues) { - DefaultsTestPtr defaults(DefaultsTest::New()); - EXPECT_EQ(-12, defaults->a0); - EXPECT_EQ(kTwelve, defaults->a1); - EXPECT_EQ(1234, defaults->a2); - EXPECT_EQ(34567U, defaults->a3); - EXPECT_EQ(123456, defaults->a4); - EXPECT_EQ(3456789012U, defaults->a5); - EXPECT_EQ(-111111111111LL, defaults->a6); - EXPECT_EQ(9999999999999999999ULL, defaults->a7); - EXPECT_EQ(0x12345, defaults->a8); - EXPECT_EQ(-0x12345, defaults->a9); - EXPECT_EQ(1234, defaults->a10); - EXPECT_TRUE(defaults->a11); - EXPECT_FALSE(defaults->a12); - EXPECT_FLOAT_EQ(123.25f, defaults->a13); - EXPECT_DOUBLE_EQ(1234567890.123, defaults->a14); - EXPECT_DOUBLE_EQ(1E10, defaults->a15); - EXPECT_DOUBLE_EQ(-1.2E+20, defaults->a16); - EXPECT_DOUBLE_EQ(1.23E-20, defaults->a17); - EXPECT_TRUE(defaults->a18.empty()); - EXPECT_TRUE(defaults->a19.empty()); - EXPECT_EQ(Bar::Type::BOTH, defaults->a20); - EXPECT_TRUE(defaults->a21.is_null()); - ASSERT_FALSE(defaults->a22.is_null()); - EXPECT_EQ(imported::Shape::RECTANGLE, defaults->a22->shape); - EXPECT_EQ(imported::Color::BLACK, defaults->a22->color); - EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, defaults->a23); - EXPECT_EQ(0x123456789, defaults->a24); - EXPECT_EQ(-0x123456789, defaults->a25); -} - -} // namespace -} // namespace sample diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc deleted file mode 100644 index 275f10f..0000000 --- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Serialization warnings are only recorded when DLOG is enabled. -#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - -#include <stddef.h> -#include <utility> - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -using mojo::internal::ContainerValidateParams; - -// Creates an array of arrays of handles (2 X 3) for testing. -std::vector<base::Optional<std::vector<ScopedHandle>>> -CreateTestNestedHandleArray() { - std::vector<base::Optional<std::vector<ScopedHandle>>> array(2); - for (size_t i = 0; i < array.size(); ++i) { - std::vector<ScopedHandle> nested_array(3); - for (size_t j = 0; j < nested_array.size(); ++j) { - MessagePipe pipe; - nested_array[j] = ScopedHandle::From(std::move(pipe.handle1)); - } - array[i].emplace(std::move(nested_array)); - } - - return array; -} - -class SerializationWarningTest : public testing::Test { - public: - ~SerializationWarningTest() override {} - - protected: - template <typename T> - void TestWarning(T obj, mojo::internal::ValidationError expected_warning) { - using MojomType = typename T::Struct::DataView; - - warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE); - - mojo::internal::SerializationContext context; - mojo::internal::FixedBufferForTesting buf( - mojo::internal::PrepareToSerialize<MojomType>(obj, &context)); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::Serialize<MojomType>(obj, &buf, &data, &context); - - EXPECT_EQ(expected_warning, warning_observer_.last_warning()); - } - - template <typename MojomType, typename T> - void TestArrayWarning(T obj, - mojo::internal::ValidationError expected_warning, - const ContainerValidateParams* validate_params) { - warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE); - - mojo::internal::SerializationContext context; - mojo::internal::FixedBufferForTesting buf( - mojo::internal::PrepareToSerialize<MojomType>(obj, &context)); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::Serialize<MojomType>(obj, &buf, &data, validate_params, - &context); - - EXPECT_EQ(expected_warning, warning_observer_.last_warning()); - } - - template <typename T> - void TestUnionWarning(T obj, - mojo::internal::ValidationError expected_warning) { - using MojomType = typename T::Struct::DataView; - - warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE); - - mojo::internal::SerializationContext context; - mojo::internal::FixedBufferForTesting buf( - mojo::internal::PrepareToSerialize<MojomType>(obj, false, &context)); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::Serialize<MojomType>(obj, &buf, &data, false, &context); - - EXPECT_EQ(expected_warning, warning_observer_.last_warning()); - } - - mojo::internal::SerializationWarningObserverForTesting warning_observer_; -}; - -TEST_F(SerializationWarningTest, HandleInStruct) { - Struct2Ptr test_struct(Struct2::New()); - EXPECT_FALSE(test_struct->hdl.is_valid()); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE); - - test_struct = Struct2::New(); - MessagePipe pipe; - test_struct->hdl = ScopedHandle::From(std::move(pipe.handle1)); - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); -} - -TEST_F(SerializationWarningTest, StructInStruct) { - Struct3Ptr test_struct(Struct3::New()); - EXPECT_TRUE(!test_struct->struct_1); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); - - test_struct = Struct3::New(); - test_struct->struct_1 = Struct1::New(); - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); -} - -TEST_F(SerializationWarningTest, ArrayOfStructsInStruct) { - Struct4Ptr test_struct(Struct4::New()); - test_struct->data.resize(1); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); - - test_struct = Struct4::New(); - test_struct->data.resize(0); - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); - - test_struct = Struct4::New(); - test_struct->data.resize(1); - test_struct->data[0] = Struct1::New(); - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); -} - -TEST_F(SerializationWarningTest, FixedArrayOfStructsInStruct) { - Struct5Ptr test_struct(Struct5::New()); - test_struct->pair.resize(1); - test_struct->pair[0] = Struct1::New(); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); - - test_struct = Struct5::New(); - test_struct->pair.resize(2); - test_struct->pair[0] = Struct1::New(); - test_struct->pair[1] = Struct1::New(); - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); -} - -TEST_F(SerializationWarningTest, ArrayOfArraysOfHandles) { - using MojomType = ArrayDataView<ArrayDataView<ScopedHandle>>; - auto test_array = CreateTestNestedHandleArray(); - test_array[0] = base::nullopt; - (*test_array[1])[0] = ScopedHandle(); - - ContainerValidateParams validate_params_0( - 0, true, new ContainerValidateParams(0, true, nullptr)); - TestArrayWarning<MojomType>(std::move(test_array), - mojo::internal::VALIDATION_ERROR_NONE, - &validate_params_0); - - test_array = CreateTestNestedHandleArray(); - test_array[0] = base::nullopt; - ContainerValidateParams validate_params_1( - 0, false, new ContainerValidateParams(0, true, nullptr)); - TestArrayWarning<MojomType>( - std::move(test_array), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - &validate_params_1); - - test_array = CreateTestNestedHandleArray(); - (*test_array[1])[0] = ScopedHandle(); - ContainerValidateParams validate_params_2( - 0, true, new ContainerValidateParams(0, false, nullptr)); - TestArrayWarning<MojomType>( - std::move(test_array), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, - &validate_params_2); -} - -TEST_F(SerializationWarningTest, ArrayOfStrings) { - using MojomType = ArrayDataView<StringDataView>; - - std::vector<std::string> test_array(3); - for (size_t i = 0; i < test_array.size(); ++i) - test_array[i] = "hello"; - - ContainerValidateParams validate_params_0( - 0, true, new ContainerValidateParams(0, false, nullptr)); - TestArrayWarning<MojomType>(std::move(test_array), - mojo::internal::VALIDATION_ERROR_NONE, - &validate_params_0); - - std::vector<base::Optional<std::string>> optional_test_array(3); - ContainerValidateParams validate_params_1( - 0, false, new ContainerValidateParams(0, false, nullptr)); - TestArrayWarning<MojomType>( - std::move(optional_test_array), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - &validate_params_1); - - test_array = std::vector<std::string>(2); - ContainerValidateParams validate_params_2( - 3, true, new ContainerValidateParams(0, false, nullptr)); - TestArrayWarning<MojomType>( - std::move(test_array), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - &validate_params_2); -} - -TEST_F(SerializationWarningTest, StructInUnion) { - DummyStructPtr dummy(nullptr); - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_dummy(std::move(dummy)); - - TestUnionWarning(std::move(obj), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); -} - -TEST_F(SerializationWarningTest, UnionInUnion) { - PodUnionPtr pod(nullptr); - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_pod_union(std::move(pod)); - - TestUnionWarning(std::move(obj), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); -} - -TEST_F(SerializationWarningTest, HandleInUnion) { - ScopedMessagePipeHandle pipe; - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_message_pipe(std::move(pipe)); - - TestUnionWarning(std::move(handle), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE); -} - -} // namespace -} // namespace test -} // namespace mojo - -#endif diff --git a/mojo/public/cpp/bindings/tests/shared_rect.h b/mojo/public/cpp/bindings/tests/shared_rect.h deleted file mode 100644 index c0a4771..0000000 --- a/mojo/public/cpp/bindings/tests/shared_rect.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_H_ - -#include "base/logging.h" - -namespace mojo { -namespace test { - -// An implementation of a hypothetical Rect type specifically for consumers in -// both Chromium and Blink. -class SharedRect { - public: - SharedRect() {} - SharedRect(int x, int y, int width, int height) - : x_(x), y_(y), width_(width), height_(height) {} - - int x() const { return x_; } - void set_x(int x) { x_ = x; } - - int y() const { return y_; } - void set_y(int y) { y_ = y; } - - int width() const { return width_; } - void set_width(int width) { width_ = width; } - - int height() const { return height_; } - void set_height(int height) { height_ = height; } - - private: - int x_ = 0; - int y_ = 0; - int width_ = 0; - int height_ = 0; -}; - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_H_ diff --git a/mojo/public/cpp/bindings/tests/shared_rect_traits.h b/mojo/public/cpp/bindings/tests/shared_rect_traits.h deleted file mode 100644 index bbf04d5..0000000 --- a/mojo/public/cpp/bindings/tests/shared_rect_traits.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_TRAITS_H_ - -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/tests/shared_rect.h" -#include "mojo/public/interfaces/bindings/tests/rect.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits<test::SharedTypemappedRectDataView, test::SharedRect> { - static int x(const test::SharedRect& r) { return r.x(); } - static int y(const test::SharedRect& r) { return r.y(); } - static int width(const test::SharedRect& r) { return r.width(); } - static int height(const test::SharedRect& r) { return r.height(); } - - static bool Read(test::SharedTypemappedRectDataView r, - test::SharedRect* out) { - out->set_x(r.x()); - out->set_y(r.y()); - out->set_width(r.width()); - out->set_height(r.height()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_SHARED_RECT_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc b/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc deleted file mode 100644 index 77b448a..0000000 --- a/mojo/public/cpp/bindings/tests/struct_traits_unittest.cc +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#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/struct_with_traits_impl_traits.h" -#include "mojo/public/cpp/bindings/tests/variant_test_util.h" -#include "mojo/public/cpp/system/wait.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.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -template <typename T> -void DoExpectResult(const T& expected, - const base::Closure& callback, - const T& actual) { - EXPECT_EQ(expected.x(), actual.x()); - EXPECT_EQ(expected.y(), actual.y()); - EXPECT_EQ(expected.width(), actual.width()); - EXPECT_EQ(expected.height(), actual.height()); - callback.Run(); -} - -template <typename T> -base::Callback<void(const T&)> ExpectResult(const T& r, - const base::Closure& callback) { - return base::Bind(&DoExpectResult<T>, r, callback); -} - -template <typename T> -void DoFail(const std::string& reason, const T&) { - EXPECT_TRUE(false) << reason; -} - -template <typename T> -base::Callback<void(const T&)> Fail(const std::string& reason) { - return base::Bind(&DoFail<T>, reason); -} - -template <typename T> -void ExpectError(InterfacePtr<T> *proxy, const base::Closure& callback) { - proxy->set_connection_error_handler(callback); -} - -// This implements the generated Chromium variant of RectService. -class ChromiumRectServiceImpl : public RectService { - public: - ChromiumRectServiceImpl() {} - - // mojo::test::RectService: - void AddRect(const RectChromium& r) override { - if (r.GetArea() > largest_rect_.GetArea()) - largest_rect_ = r; - } - - void GetLargestRect(const GetLargestRectCallback& callback) override { - callback.Run(largest_rect_); - } - - void PassSharedRect(const SharedRect& r, - const PassSharedRectCallback& callback) override { - callback.Run(r); - } - - private: - RectChromium largest_rect_; -}; - -// This implements the generated Blink variant of RectService. -class BlinkRectServiceImpl : public blink::RectService { - public: - BlinkRectServiceImpl() {} - - // mojo::test::blink::RectService: - void AddRect(const RectBlink& r) override { - if (r.computeArea() > largest_rect_.computeArea()) { - largest_rect_.setX(r.x()); - largest_rect_.setY(r.y()); - largest_rect_.setWidth(r.width()); - largest_rect_.setHeight(r.height()); - } - } - - void GetLargestRect(const GetLargestRectCallback& callback) override { - callback.Run(largest_rect_); - } - - void PassSharedRect(const SharedRect& r, - const PassSharedRectCallback& callback) override { - callback.Run(r); - } - - private: - RectBlink largest_rect_; -}; - -// A test which runs both Chromium and Blink implementations of a RectService. -class StructTraitsTest : public testing::Test, - public TraitsTestService { - public: - StructTraitsTest() {} - - protected: - void BindToChromiumService(RectServiceRequest request) { - chromium_bindings_.AddBinding(&chromium_service_, std::move(request)); - } - void BindToChromiumService(blink::RectServiceRequest request) { - chromium_bindings_.AddBinding( - &chromium_service_, - ConvertInterfaceRequest<RectService>(std::move(request))); - } - - void BindToBlinkService(blink::RectServiceRequest request) { - blink_bindings_.AddBinding(&blink_service_, std::move(request)); - } - void BindToBlinkService(RectServiceRequest request) { - blink_bindings_.AddBinding( - &blink_service_, - ConvertInterfaceRequest<blink::RectService>(std::move(request))); - } - - TraitsTestServicePtr GetTraitsTestProxy() { - return traits_test_bindings_.CreateInterfacePtrAndBind(this); - } - - private: - // TraitsTestService: - void EchoStructWithTraits( - const StructWithTraitsImpl& s, - const EchoStructWithTraitsCallback& callback) override { - callback.Run(s); - } - - void EchoTrivialStructWithTraits( - TrivialStructWithTraitsImpl s, - const EchoTrivialStructWithTraitsCallback& callback) override { - callback.Run(s); - } - - void EchoMoveOnlyStructWithTraits( - MoveOnlyStructWithTraitsImpl s, - const EchoMoveOnlyStructWithTraitsCallback& callback) override { - callback.Run(std::move(s)); - } - - void EchoNullableMoveOnlyStructWithTraits( - base::Optional<MoveOnlyStructWithTraitsImpl> s, - const EchoNullableMoveOnlyStructWithTraitsCallback& callback) override { - callback.Run(std::move(s)); - } - - void EchoEnumWithTraits(EnumWithTraitsImpl e, - const EchoEnumWithTraitsCallback& callback) override { - callback.Run(e); - } - - void EchoStructWithTraitsForUniquePtr( - std::unique_ptr<int> e, - const EchoStructWithTraitsForUniquePtrCallback& callback) override { - callback.Run(std::move(e)); - } - - void EchoNullableStructWithTraitsForUniquePtr( - std::unique_ptr<int> e, - const EchoNullableStructWithTraitsForUniquePtrCallback& callback) - override { - callback.Run(std::move(e)); - } - - void EchoUnionWithTraits( - std::unique_ptr<test::UnionWithTraitsBase> u, - const EchoUnionWithTraitsCallback& callback) override { - callback.Run(std::move(u)); - } - - base::MessageLoop loop_; - - ChromiumRectServiceImpl chromium_service_; - BindingSet<RectService> chromium_bindings_; - - BlinkRectServiceImpl blink_service_; - BindingSet<blink::RectService> blink_bindings_; - - BindingSet<TraitsTestService> traits_test_bindings_; -}; - -} // namespace - -TEST_F(StructTraitsTest, ChromiumProxyToChromiumService) { - RectServicePtr chromium_proxy; - BindToChromiumService(MakeRequest(&chromium_proxy)); - { - base::RunLoop loop; - chromium_proxy->AddRect(RectChromium(1, 1, 4, 5)); - chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2)); - chromium_proxy->GetLargestRect( - ExpectResult(RectChromium(1, 1, 4, 5), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - chromium_proxy->PassSharedRect( - {1, 2, 3, 4}, - ExpectResult(SharedRect({1, 2, 3, 4}), loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(StructTraitsTest, ChromiumToBlinkService) { - RectServicePtr chromium_proxy; - BindToBlinkService(MakeRequest(&chromium_proxy)); - { - base::RunLoop loop; - chromium_proxy->AddRect(RectChromium(1, 1, 4, 5)); - chromium_proxy->AddRect(RectChromium(2, 2, 5, 5)); - chromium_proxy->GetLargestRect( - ExpectResult(RectChromium(2, 2, 5, 5), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - chromium_proxy->PassSharedRect( - {1, 2, 3, 4}, - ExpectResult(SharedRect({1, 2, 3, 4}), loop.QuitClosure())); - loop.Run(); - } - // The Blink service should drop our connection because RectBlink's - // deserializer rejects negative origins. - { - base::RunLoop loop; - ExpectError(&chromium_proxy, loop.QuitClosure()); - chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2)); - chromium_proxy->GetLargestRect( - Fail<RectChromium>("The pipe should have been closed.")); - loop.Run(); - } -} - -TEST_F(StructTraitsTest, BlinkProxyToBlinkService) { - blink::RectServicePtr blink_proxy; - BindToBlinkService(MakeRequest(&blink_proxy)); - { - base::RunLoop loop; - blink_proxy->AddRect(RectBlink(1, 1, 4, 5)); - blink_proxy->AddRect(RectBlink(10, 10, 20, 20)); - blink_proxy->GetLargestRect( - ExpectResult(RectBlink(10, 10, 20, 20), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - blink_proxy->PassSharedRect( - {4, 3, 2, 1}, - ExpectResult(SharedRect({4, 3, 2, 1}), loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(StructTraitsTest, BlinkProxyToChromiumService) { - blink::RectServicePtr blink_proxy; - BindToChromiumService(MakeRequest(&blink_proxy)); - { - base::RunLoop loop; - blink_proxy->AddRect(RectBlink(1, 1, 4, 5)); - blink_proxy->AddRect(RectBlink(10, 10, 2, 2)); - blink_proxy->GetLargestRect( - ExpectResult(RectBlink(1, 1, 4, 5), loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - blink_proxy->PassSharedRect( - {4, 3, 2, 1}, - ExpectResult(SharedRect({4, 3, 2, 1}), loop.QuitClosure())); - loop.Run(); - } -} - -void ExpectStructWithTraits(const StructWithTraitsImpl& expected, - const base::Closure& closure, - const StructWithTraitsImpl& passed) { - EXPECT_EQ(expected.get_enum(), passed.get_enum()); - EXPECT_EQ(expected.get_bool(), passed.get_bool()); - EXPECT_EQ(expected.get_uint32(), passed.get_uint32()); - EXPECT_EQ(expected.get_uint64(), passed.get_uint64()); - EXPECT_EQ(expected.get_string(), passed.get_string()); - EXPECT_EQ(expected.get_string_array(), passed.get_string_array()); - EXPECT_EQ(expected.get_struct(), passed.get_struct()); - EXPECT_EQ(expected.get_struct_array(), passed.get_struct_array()); - EXPECT_EQ(expected.get_struct_map(), passed.get_struct_map()); - closure.Run(); -} - -TEST_F(StructTraitsTest, EchoStructWithTraits) { - StructWithTraitsImpl input; - input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1); - input.set_bool(true); - input.set_uint32(7); - input.set_uint64(42); - input.set_string("hello world!"); - input.get_mutable_string_array().assign({"hello", "world!"}); - input.get_mutable_string_set().insert("hello"); - input.get_mutable_string_set().insert("world!"); - input.get_mutable_struct().value = 42; - input.get_mutable_struct_array().resize(2); - input.get_mutable_struct_array()[0].value = 1; - input.get_mutable_struct_array()[1].value = 2; - input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024); - input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048); - - base::RunLoop loop; - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - proxy->EchoStructWithTraits( - input, - base::Bind(&ExpectStructWithTraits, input, loop.QuitClosure())); - loop.Run(); -} - -TEST_F(StructTraitsTest, CloneStructWithTraitsContainer) { - StructWithTraitsContainerPtr container = StructWithTraitsContainer::New(); - container->f_struct.set_uint32(7); - container->f_struct.set_uint64(42); - StructWithTraitsContainerPtr cloned_container = container.Clone(); - EXPECT_EQ(7u, cloned_container->f_struct.get_uint32()); - EXPECT_EQ(42u, cloned_container->f_struct.get_uint64()); -} - -void ExpectTrivialStructWithTraits(TrivialStructWithTraitsImpl expected, - const base::Closure& closure, - TrivialStructWithTraitsImpl passed) { - EXPECT_EQ(expected.value, passed.value); - closure.Run(); -} - -TEST_F(StructTraitsTest, EchoTrivialStructWithTraits) { - TrivialStructWithTraitsImpl input; - input.value = 42; - - base::RunLoop loop; - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - proxy->EchoTrivialStructWithTraits( - input, - base::Bind(&ExpectTrivialStructWithTraits, input, loop.QuitClosure())); - loop.Run(); -} - -void CaptureMessagePipe(ScopedMessagePipeHandle* storage, - const base::Closure& closure, - MoveOnlyStructWithTraitsImpl passed) { - storage->reset(MessagePipeHandle( - passed.get_mutable_handle().release().value())); - closure.Run(); -} - -TEST_F(StructTraitsTest, EchoMoveOnlyStructWithTraits) { - MessagePipe mp; - MoveOnlyStructWithTraitsImpl input; - input.get_mutable_handle().reset(mp.handle0.release()); - - base::RunLoop loop; - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - ScopedMessagePipeHandle received; - proxy->EchoMoveOnlyStructWithTraits( - std::move(input), - base::Bind(&CaptureMessagePipe, &received, loop.QuitClosure())); - loop.Run(); - - ASSERT_TRUE(received.is_valid()); - - // Verify that the message pipe handle is correctly passed. - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(mp.handle1.get(), kHello, kHelloSize, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, Wait(received.get(), MOJO_HANDLE_SIGNAL_READABLE)); - - char buffer[10] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(received.get(), buffer, &buffer_size, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, buffer_size); - EXPECT_STREQ(kHello, buffer); -} - -void CaptureNullableMoveOnlyStructWithTraitsImpl( - base::Optional<MoveOnlyStructWithTraitsImpl>* storage, - const base::Closure& closure, - base::Optional<MoveOnlyStructWithTraitsImpl> passed) { - *storage = std::move(passed); - closure.Run(); -} - -TEST_F(StructTraitsTest, EchoNullableMoveOnlyStructWithTraits) { - base::RunLoop loop; - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - base::Optional<MoveOnlyStructWithTraitsImpl> received; - proxy->EchoNullableMoveOnlyStructWithTraits( - base::nullopt, base::Bind(&CaptureNullableMoveOnlyStructWithTraitsImpl, - &received, loop.QuitClosure())); - loop.Run(); - - EXPECT_FALSE(received); -} - -void ExpectEnumWithTraits(EnumWithTraitsImpl expected_value, - const base::Closure& closure, - EnumWithTraitsImpl value) { - EXPECT_EQ(expected_value, value); - closure.Run(); -} - -TEST_F(StructTraitsTest, EchoEnumWithTraits) { - base::RunLoop loop; - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - proxy->EchoEnumWithTraits( - EnumWithTraitsImpl::CUSTOM_VALUE_1, - base::Bind(&ExpectEnumWithTraits, EnumWithTraitsImpl::CUSTOM_VALUE_1, - loop.QuitClosure())); - loop.Run(); -} - -TEST_F(StructTraitsTest, SerializeStructWithTraits) { - StructWithTraitsImpl input; - input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1); - input.set_bool(true); - input.set_uint32(7); - input.set_uint64(42); - input.set_string("hello world!"); - input.get_mutable_string_array().assign({ "hello", "world!" }); - input.get_mutable_string_set().insert("hello"); - input.get_mutable_string_set().insert("world!"); - input.get_mutable_struct().value = 42; - input.get_mutable_struct_array().resize(2); - input.get_mutable_struct_array()[0].value = 1; - input.get_mutable_struct_array()[1].value = 2; - input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024); - input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048); - - auto data = StructWithTraits::Serialize(&input); - StructWithTraitsImpl output; - ASSERT_TRUE(StructWithTraits::Deserialize(std::move(data), &output)); - - EXPECT_EQ(input.get_enum(), output.get_enum()); - EXPECT_EQ(input.get_bool(), output.get_bool()); - EXPECT_EQ(input.get_uint32(), output.get_uint32()); - EXPECT_EQ(input.get_uint64(), output.get_uint64()); - EXPECT_EQ(input.get_string(), output.get_string()); - EXPECT_EQ(input.get_string_array(), output.get_string_array()); - EXPECT_EQ(input.get_string_set(), output.get_string_set()); - EXPECT_EQ(input.get_struct(), output.get_struct()); - EXPECT_EQ(input.get_struct_array(), output.get_struct_array()); - EXPECT_EQ(input.get_struct_map(), output.get_struct_map()); -} - -void ExpectUniquePtr(std::unique_ptr<int> expected, - const base::Closure& closure, - std::unique_ptr<int> value) { - ASSERT_EQ(!expected, !value); - if (expected) - EXPECT_EQ(*expected, *value); - closure.Run(); -} - -TEST_F(StructTraitsTest, TypemapUniquePtr) { - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - { - base::RunLoop loop; - proxy->EchoStructWithTraitsForUniquePtr( - base::MakeUnique<int>(12345), - base::Bind(&ExpectUniquePtr, base::Passed(base::MakeUnique<int>(12345)), - loop.QuitClosure())); - loop.Run(); - } - { - base::RunLoop loop; - proxy->EchoNullableStructWithTraitsForUniquePtr( - nullptr, base::Bind(&ExpectUniquePtr, nullptr, loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(StructTraitsTest, EchoUnionWithTraits) { - TraitsTestServicePtr proxy = GetTraitsTestProxy(); - - { - std::unique_ptr<test::UnionWithTraitsBase> input( - new test::UnionWithTraitsInt32(1234)); - base::RunLoop loop; - proxy->EchoUnionWithTraits( - std::move(input), - base::Bind( - [](const base::Closure& quit_closure, - std::unique_ptr<test::UnionWithTraitsBase> passed) { - ASSERT_EQ(test::UnionWithTraitsBase::Type::INT32, passed->type()); - EXPECT_EQ(1234, - static_cast<test::UnionWithTraitsInt32*>(passed.get()) - ->value()); - quit_closure.Run(); - - }, - loop.QuitClosure())); - loop.Run(); - } - - { - std::unique_ptr<test::UnionWithTraitsBase> input( - new test::UnionWithTraitsStruct(4321)); - base::RunLoop loop; - proxy->EchoUnionWithTraits( - std::move(input), - base::Bind( - [](const base::Closure& quit_closure, - std::unique_ptr<test::UnionWithTraitsBase> passed) { - ASSERT_EQ(test::UnionWithTraitsBase::Type::STRUCT, - passed->type()); - EXPECT_EQ(4321, - static_cast<test::UnionWithTraitsStruct*>(passed.get()) - ->get_struct() - .value); - quit_closure.Run(); - - }, - loop.QuitClosure())); - loop.Run(); - } -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc deleted file mode 100644 index a687052..0000000 --- a/mojo/public/cpp/bindings/tests/struct_unittest.cc +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <string.h> -#include <utility> - -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/public/interfaces/bindings/tests/test_export2.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -RectPtr MakeRect(int32_t factor = 1) { - return Rect::New(1 * factor, 2 * factor, 10 * factor, 20 * factor); -} - -void CheckRect(const Rect& rect, int32_t factor = 1) { - EXPECT_EQ(1 * factor, rect.x); - EXPECT_EQ(2 * factor, rect.y); - EXPECT_EQ(10 * factor, rect.width); - EXPECT_EQ(20 * factor, rect.height); -} - -MultiVersionStructPtr MakeMultiVersionStruct() { - MessagePipe pipe; - return MultiVersionStruct::New(123, MakeRect(5), std::string("hello"), - std::vector<int8_t>{10, 9, 8}, - std::move(pipe.handle0), false, 42); -} - -template <typename U, typename T> -U SerializeAndDeserialize(T input) { - using InputMojomType = typename T::Struct::DataView; - using OutputMojomType = typename U::Struct::DataView; - - using InputDataType = - typename mojo::internal::MojomTypeTraits<InputMojomType>::Data*; - using OutputDataType = - typename mojo::internal::MojomTypeTraits<OutputMojomType>::Data*; - - mojo::internal::SerializationContext context; - size_t size = - mojo::internal::PrepareToSerialize<InputMojomType>(input, &context); - mojo::internal::FixedBufferForTesting buf(size + 32); - InputDataType data; - mojo::internal::Serialize<InputMojomType>(input, &buf, &data, &context); - - // Set the subsequent area to a special value, so that we can find out if we - // mistakenly access the area. - void* subsequent_area = buf.Allocate(32); - memset(subsequent_area, 0xAA, 32); - - OutputDataType output_data = reinterpret_cast<OutputDataType>(data); - - U output; - mojo::internal::Deserialize<OutputMojomType>(output_data, &output, &context); - return std::move(output); -} - -using StructTest = testing::Test; - -} // namespace - -TEST_F(StructTest, Rect) { - RectPtr rect; - EXPECT_TRUE(rect.is_null()); - EXPECT_TRUE(!rect); - EXPECT_FALSE(rect); - - rect = nullptr; - EXPECT_TRUE(rect.is_null()); - EXPECT_TRUE(!rect); - EXPECT_FALSE(rect); - - rect = MakeRect(); - EXPECT_FALSE(rect.is_null()); - EXPECT_FALSE(!rect); - EXPECT_TRUE(rect); - - RectPtr null_rect = nullptr; - EXPECT_TRUE(null_rect.is_null()); - EXPECT_TRUE(!null_rect); - EXPECT_FALSE(null_rect); - - CheckRect(*rect); -} - -TEST_F(StructTest, Clone) { - NamedRegionPtr region; - - NamedRegionPtr clone_region = region.Clone(); - EXPECT_TRUE(clone_region.is_null()); - - region = NamedRegion::New(); - clone_region = region.Clone(); - EXPECT_FALSE(clone_region->name); - EXPECT_FALSE(clone_region->rects); - - region->name.emplace("hello world"); - clone_region = region.Clone(); - EXPECT_EQ(region->name, clone_region->name); - - region->rects.emplace(2); - (*region->rects)[1] = MakeRect(); - clone_region = region.Clone(); - EXPECT_EQ(2u, clone_region->rects->size()); - EXPECT_TRUE((*clone_region->rects)[0].is_null()); - CheckRect(*(*clone_region->rects)[1]); - - // NoDefaultFieldValues contains handles, so Clone() is not available, but - // NoDefaultFieldValuesPtr should still compile. - NoDefaultFieldValuesPtr no_default_field_values(NoDefaultFieldValues::New()); - EXPECT_FALSE(no_default_field_values->f13.is_valid()); -} - -// Serialization test of a struct with no pointer or handle members. -TEST_F(StructTest, Serialization_Basic) { - RectPtr rect(MakeRect()); - - size_t size = mojo::internal::PrepareToSerialize<RectDataView>(rect, nullptr); - EXPECT_EQ(8U + 16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::Rect_Data* data; - mojo::internal::Serialize<RectDataView>(rect, &buf, &data, nullptr); - - RectPtr rect2; - mojo::internal::Deserialize<RectDataView>(data, &rect2, nullptr); - - CheckRect(*rect2); -} - -// Construction of a struct with struct pointers from null. -TEST_F(StructTest, Construction_StructPointers) { - RectPairPtr pair; - EXPECT_TRUE(pair.is_null()); - - pair = RectPair::New(); - EXPECT_FALSE(pair.is_null()); - EXPECT_TRUE(pair->first.is_null()); - EXPECT_TRUE(pair->first.is_null()); - - pair = nullptr; - EXPECT_TRUE(pair.is_null()); -} - -// Serialization test of a struct with struct pointers. -TEST_F(StructTest, Serialization_StructPointers) { - RectPairPtr pair(RectPair::New(MakeRect(), MakeRect())); - - size_t size = - mojo::internal::PrepareToSerialize<RectPairDataView>(pair, nullptr); - EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::RectPair_Data* data; - mojo::internal::Serialize<RectPairDataView>(pair, &buf, &data, nullptr); - - RectPairPtr pair2; - mojo::internal::Deserialize<RectPairDataView>(data, &pair2, nullptr); - - CheckRect(*pair2->first); - CheckRect(*pair2->second); -} - -// Serialization test of a struct with an array member. -TEST_F(StructTest, Serialization_ArrayPointers) { - std::vector<RectPtr> rects; - for (size_t i = 0; i < 4; ++i) - rects.push_back(MakeRect(static_cast<int32_t>(i) + 1)); - - NamedRegionPtr region( - NamedRegion::New(std::string("region"), std::move(rects))); - - size_t size = - mojo::internal::PrepareToSerialize<NamedRegionDataView>(region, nullptr); - EXPECT_EQ(8U + // header - 8U + // name pointer - 8U + // rects pointer - 8U + // name header - 8U + // name payload (rounded up) - 8U + // rects header - 4 * 8U + // rects payload (four pointers) - 4 * (8U + // rect header - 16U), // rect payload (four ints) - size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::NamedRegion_Data* data; - mojo::internal::Serialize<NamedRegionDataView>(region, &buf, &data, nullptr); - - NamedRegionPtr region2; - mojo::internal::Deserialize<NamedRegionDataView>(data, ®ion2, nullptr); - - EXPECT_EQ("region", *region2->name); - - EXPECT_EQ(4U, region2->rects->size()); - for (size_t i = 0; i < region2->rects->size(); ++i) - CheckRect(*(*region2->rects)[i], static_cast<int32_t>(i) + 1); -} - -// Serialization test of a struct with null array pointers. -TEST_F(StructTest, Serialization_NullArrayPointers) { - NamedRegionPtr region(NamedRegion::New()); - EXPECT_FALSE(region->name); - EXPECT_FALSE(region->rects); - - size_t size = - mojo::internal::PrepareToSerialize<NamedRegionDataView>(region, nullptr); - EXPECT_EQ(8U + // header - 8U + // name pointer - 8U, // rects pointer - size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::NamedRegion_Data* data; - mojo::internal::Serialize<NamedRegionDataView>(region, &buf, &data, nullptr); - - NamedRegionPtr region2; - mojo::internal::Deserialize<NamedRegionDataView>(data, ®ion2, nullptr); - - EXPECT_FALSE(region2->name); - EXPECT_FALSE(region2->rects); -} - -// Tests deserializing structs as a newer version. -TEST_F(StructTest, Versioning_OldToNew) { - { - MultiVersionStructV0Ptr input(MultiVersionStructV0::New(123)); - MultiVersionStructPtr expected_output(MultiVersionStruct::New(123)); - - MultiVersionStructPtr output = - SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructV1Ptr input(MultiVersionStructV1::New(123, MakeRect(5))); - MultiVersionStructPtr expected_output( - MultiVersionStruct::New(123, MakeRect(5))); - - MultiVersionStructPtr output = - SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructV3Ptr input( - MultiVersionStructV3::New(123, MakeRect(5), std::string("hello"))); - MultiVersionStructPtr expected_output( - MultiVersionStruct::New(123, MakeRect(5), std::string("hello"))); - - MultiVersionStructPtr output = - SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructV5Ptr input(MultiVersionStructV5::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8})); - MultiVersionStructPtr expected_output(MultiVersionStruct::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8})); - - MultiVersionStructPtr output = - SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MessagePipe pipe; - MultiVersionStructV7Ptr input(MultiVersionStructV7::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8}, - std::move(pipe.handle0), false)); - - MultiVersionStructPtr expected_output(MultiVersionStruct::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8})); - // Save the raw handle value separately so that we can compare later. - MojoHandle expected_handle = input->f_message_pipe.get().value(); - - MultiVersionStructPtr output = - SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_EQ(expected_handle, output->f_message_pipe.get().value()); - output->f_message_pipe.reset(); - EXPECT_TRUE(output->Equals(*expected_output)); - } -} - -// Tests deserializing structs as an older version. -TEST_F(StructTest, Versioning_NewToOld) { - { - MultiVersionStructPtr input = MakeMultiVersionStruct(); - MultiVersionStructV7Ptr expected_output(MultiVersionStructV7::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8})); - // Save the raw handle value separately so that we can compare later. - MojoHandle expected_handle = input->f_message_pipe.get().value(); - - MultiVersionStructV7Ptr output = - SerializeAndDeserialize<MultiVersionStructV7Ptr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_EQ(expected_handle, output->f_message_pipe.get().value()); - output->f_message_pipe.reset(); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructPtr input = MakeMultiVersionStruct(); - MultiVersionStructV5Ptr expected_output(MultiVersionStructV5::New( - 123, MakeRect(5), std::string("hello"), std::vector<int8_t>{10, 9, 8})); - - MultiVersionStructV5Ptr output = - SerializeAndDeserialize<MultiVersionStructV5Ptr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructPtr input = MakeMultiVersionStruct(); - MultiVersionStructV3Ptr expected_output( - MultiVersionStructV3::New(123, MakeRect(5), std::string("hello"))); - - MultiVersionStructV3Ptr output = - SerializeAndDeserialize<MultiVersionStructV3Ptr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructPtr input = MakeMultiVersionStruct(); - MultiVersionStructV1Ptr expected_output( - MultiVersionStructV1::New(123, MakeRect(5))); - - MultiVersionStructV1Ptr output = - SerializeAndDeserialize<MultiVersionStructV1Ptr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } - - { - MultiVersionStructPtr input = MakeMultiVersionStruct(); - MultiVersionStructV0Ptr expected_output(MultiVersionStructV0::New(123)); - - MultiVersionStructV0Ptr output = - SerializeAndDeserialize<MultiVersionStructV0Ptr>(std::move(input)); - EXPECT_TRUE(output); - EXPECT_TRUE(output->Equals(*expected_output)); - } -} - -// Serialization test for native struct. -TEST_F(StructTest, Serialization_NativeStruct) { - using Data = mojo::internal::NativeStruct_Data; - { - // Serialization of a null native struct. - NativeStructPtr native; - size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>( - native, nullptr); - EXPECT_EQ(0u, size); - mojo::internal::FixedBufferForTesting buf(size); - - Data* data = nullptr; - mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf, - &data, nullptr); - - EXPECT_EQ(nullptr, data); - - NativeStructPtr output_native; - mojo::internal::Deserialize<NativeStructDataView>(data, &output_native, - nullptr); - EXPECT_TRUE(output_native.is_null()); - } - - { - // Serialization of a native struct with null data. - NativeStructPtr native(NativeStruct::New()); - size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>( - native, nullptr); - EXPECT_EQ(0u, size); - mojo::internal::FixedBufferForTesting buf(size); - - Data* data = nullptr; - mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf, - &data, nullptr); - - EXPECT_EQ(nullptr, data); - - NativeStructPtr output_native; - mojo::internal::Deserialize<NativeStructDataView>(data, &output_native, - nullptr); - EXPECT_TRUE(output_native.is_null()); - } - - { - NativeStructPtr native(NativeStruct::New()); - native->data = std::vector<uint8_t>{'X', 'Y'}; - - size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>( - native, nullptr); - EXPECT_EQ(16u, size); - mojo::internal::FixedBufferForTesting buf(size); - - Data* data = nullptr; - mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf, - &data, nullptr); - - EXPECT_NE(nullptr, data); - - NativeStructPtr output_native; - mojo::internal::Deserialize<NativeStructDataView>(data, &output_native, - nullptr); - ASSERT_TRUE(output_native); - ASSERT_FALSE(output_native->data->empty()); - EXPECT_EQ(2u, output_native->data->size()); - EXPECT_EQ('X', (*output_native->data)[0]); - EXPECT_EQ('Y', (*output_native->data)[1]); - } -} - -TEST_F(StructTest, Serialization_PublicAPI) { - { - // A null struct pointer. - RectPtr null_struct; - auto data = Rect::Serialize(&null_struct); - EXPECT_TRUE(data.empty()); - - // Initialize it to non-null. - RectPtr output(Rect::New()); - ASSERT_TRUE(Rect::Deserialize(data, &output)); - EXPECT_TRUE(output.is_null()); - } - - { - // A struct with no fields. - EmptyStructPtr empty_struct(EmptyStruct::New()); - auto data = EmptyStruct::Serialize(&empty_struct); - EXPECT_FALSE(data.empty()); - - EmptyStructPtr output; - ASSERT_TRUE(EmptyStruct::Deserialize(data, &output)); - EXPECT_FALSE(output.is_null()); - } - - { - // A simple struct. - RectPtr rect = MakeRect(); - RectPtr cloned_rect = rect.Clone(); - auto data = Rect::Serialize(&rect); - - RectPtr output; - ASSERT_TRUE(Rect::Deserialize(data, &output)); - EXPECT_TRUE(output.Equals(cloned_rect)); - } - - { - // A struct containing other objects. - std::vector<RectPtr> rects; - for (size_t i = 0; i < 3; ++i) - rects.push_back(MakeRect(static_cast<int32_t>(i) + 1)); - NamedRegionPtr region( - NamedRegion::New(std::string("region"), std::move(rects))); - - NamedRegionPtr cloned_region = region.Clone(); - auto data = NamedRegion::Serialize(®ion); - - // Make sure that the serialized result gets pointers encoded properly. - auto cloned_data = data; - NamedRegionPtr output; - ASSERT_TRUE(NamedRegion::Deserialize(cloned_data, &output)); - EXPECT_TRUE(output.Equals(cloned_region)); - } - - { - // Deserialization failure. - RectPtr rect = MakeRect(); - auto data = Rect::Serialize(&rect); - - NamedRegionPtr output; - EXPECT_FALSE(NamedRegion::Deserialize(data, &output)); - } - - { - // A struct from another component. - auto pair = test_export2::StringPair::New("hello", "world"); - auto data = test_export2::StringPair::Serialize(&pair); - - test_export2::StringPairPtr output; - ASSERT_TRUE(test_export2::StringPair::Deserialize(data, &output)); - EXPECT_TRUE(output.Equals(pair)); - } -} - -TEST_F(StructTest, VersionedStructConstructor) { - auto reordered = ReorderedStruct::New(123, 456, 789); - EXPECT_EQ(123, reordered->a); - EXPECT_EQ(456, reordered->b); - EXPECT_EQ(789, reordered->c); - - reordered = ReorderedStruct::New(123, 456); - EXPECT_EQ(123, reordered->a); - EXPECT_EQ(6, reordered->b); - EXPECT_EQ(456, reordered->c); - - reordered = ReorderedStruct::New(123); - EXPECT_EQ(3, reordered->a); - EXPECT_EQ(6, reordered->b); - EXPECT_EQ(123, reordered->c); - - reordered = ReorderedStruct::New(); - EXPECT_EQ(3, reordered->a); - EXPECT_EQ(6, reordered->b); - EXPECT_EQ(1, reordered->c); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits.typemap b/mojo/public/cpp/bindings/tests/struct_with_traits.typemap deleted file mode 100644 index 752ce44..0000000 --- a/mojo/public/cpp/bindings/tests/struct_with_traits.typemap +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/public/interfaces/bindings/tests/struct_with_traits.mojom" -public_headers = - [ "//mojo/public/cpp/bindings/tests/struct_with_traits_impl.h" ] -traits_headers = - [ "//mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h" ] -sources = [ - "//mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc", -] -deps = [ - "//mojo/public/cpp/bindings/tests:struct_with_traits_impl", - "//mojo/public/cpp/system:system", -] - -type_mappings = [ - "mojo.test.EnumWithTraits=mojo::test::EnumWithTraitsImpl", - "mojo.test.StructWithTraits=mojo::test::StructWithTraitsImpl", - "mojo.test.NestedStructWithTraits=mojo::test::NestedStructWithTraitsImpl", - "mojo.test.TrivialStructWithTraits=mojo::test::TrivialStructWithTraitsImpl[copyable_pass_by_value]", - "mojo.test.MoveOnlyStructWithTraits=mojo::test::MoveOnlyStructWithTraitsImpl[move_only]", - "mojo.test.StructWithTraitsForUniquePtr=std::unique_ptr<int>[move_only,nullable_is_same_type]", - "mojo.test.UnionWithTraits=std::unique_ptr<mojo::test::UnionWithTraitsBase>[move_only,nullable_is_same_type]", -] diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.cc b/mojo/public/cpp/bindings/tests/struct_with_traits_impl.cc deleted file mode 100644 index cbdd4bf..0000000 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/struct_with_traits_impl.h" - -namespace mojo { -namespace test { - -NestedStructWithTraitsImpl::NestedStructWithTraitsImpl() {} -NestedStructWithTraitsImpl::NestedStructWithTraitsImpl(int32_t in_value) - : value(in_value) {} - -StructWithTraitsImpl::StructWithTraitsImpl() {} - -StructWithTraitsImpl::~StructWithTraitsImpl() {} - -StructWithTraitsImpl::StructWithTraitsImpl(const StructWithTraitsImpl& other) = - default; - -MoveOnlyStructWithTraitsImpl::MoveOnlyStructWithTraitsImpl() {} - -MoveOnlyStructWithTraitsImpl::MoveOnlyStructWithTraitsImpl( - MoveOnlyStructWithTraitsImpl&& other) = default; - -MoveOnlyStructWithTraitsImpl::~MoveOnlyStructWithTraitsImpl() {} - -MoveOnlyStructWithTraitsImpl& MoveOnlyStructWithTraitsImpl::operator=( - MoveOnlyStructWithTraitsImpl&& other) = default; - -UnionWithTraitsInt32::~UnionWithTraitsInt32() {} - -UnionWithTraitsStruct::~UnionWithTraitsStruct() {} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h b/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h deleted file mode 100644 index 7b007cc..0000000 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_H_ - -#include <stdint.h> - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/strings/string_piece.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace test { - -struct NestedStructWithTraitsImpl { - public: - NestedStructWithTraitsImpl(); - explicit NestedStructWithTraitsImpl(int32_t in_value); - - bool operator==(const NestedStructWithTraitsImpl& other) const { - return value == other.value; - } - - int32_t value = 0; -}; - -enum class EnumWithTraitsImpl { CUSTOM_VALUE_0 = 10, CUSTOM_VALUE_1 = 11 }; - -// A type which knows how to look like a mojo::test::StructWithTraits mojom type -// by way of mojo::StructTraits. -class StructWithTraitsImpl { - public: - StructWithTraitsImpl(); - ~StructWithTraitsImpl(); - - StructWithTraitsImpl(const StructWithTraitsImpl& other); - - void set_enum(EnumWithTraitsImpl value) { enum_ = value; } - EnumWithTraitsImpl get_enum() const { return enum_; } - - void set_bool(bool value) { bool_ = value; } - bool get_bool() const { return bool_; } - - void set_uint32(uint32_t value) { uint32_ = value; } - uint32_t get_uint32() const { return uint32_; } - - void set_uint64(uint64_t value) { uint64_ = value; } - uint64_t get_uint64() const { return uint64_; } - - void set_string(std::string value) { string_ = value; } - base::StringPiece get_string_as_string_piece() const { return string_; } - const std::string& get_string() const { return string_; } - - const std::vector<std::string>& get_string_array() const { - return string_array_; - } - std::vector<std::string>& get_mutable_string_array() { return string_array_; } - - const std::set<std::string>& get_string_set() const { - return string_set_; - } - std::set<std::string>& get_mutable_string_set() { return string_set_; } - - const NestedStructWithTraitsImpl& get_struct() const { return struct_; } - NestedStructWithTraitsImpl& get_mutable_struct() { return struct_; } - - const std::vector<NestedStructWithTraitsImpl>& get_struct_array() const { - return struct_array_; - } - std::vector<NestedStructWithTraitsImpl>& get_mutable_struct_array() { - return struct_array_; - } - - const std::map<std::string, NestedStructWithTraitsImpl>& get_struct_map() - const { - return struct_map_; - } - std::map<std::string, NestedStructWithTraitsImpl>& get_mutable_struct_map() { - return struct_map_; - } - - private: - EnumWithTraitsImpl enum_ = EnumWithTraitsImpl::CUSTOM_VALUE_0; - bool bool_ = false; - uint32_t uint32_ = 0; - uint64_t uint64_ = 0; - std::string string_; - std::vector<std::string> string_array_; - std::set<std::string> string_set_; - NestedStructWithTraitsImpl struct_; - std::vector<NestedStructWithTraitsImpl> struct_array_; - std::map<std::string, NestedStructWithTraitsImpl> struct_map_; -}; - -// A type which knows how to look like a mojo::test::TrivialStructWithTraits -// mojom type by way of mojo::StructTraits. -struct TrivialStructWithTraitsImpl { - int32_t value; -}; - -// A type which knows how to look like a mojo::test::MoveOnlyStructWithTraits -// mojom type by way of mojo::StructTraits. -class MoveOnlyStructWithTraitsImpl { - public: - MoveOnlyStructWithTraitsImpl(); - MoveOnlyStructWithTraitsImpl(MoveOnlyStructWithTraitsImpl&& other); - ~MoveOnlyStructWithTraitsImpl(); - - ScopedHandle& get_mutable_handle() { return handle_; } - - MoveOnlyStructWithTraitsImpl& operator=(MoveOnlyStructWithTraitsImpl&& other); - - private: - ScopedHandle handle_; - DISALLOW_COPY_AND_ASSIGN(MoveOnlyStructWithTraitsImpl); -}; - -class UnionWithTraitsBase { - public: - enum class Type { INT32, STRUCT }; - - virtual ~UnionWithTraitsBase() {} - - Type type() const { return type_; } - - protected: - Type type_ = Type::INT32; -}; - -class UnionWithTraitsInt32 : public UnionWithTraitsBase { - public: - UnionWithTraitsInt32() {} - explicit UnionWithTraitsInt32(int32_t value) : value_(value) {} - - ~UnionWithTraitsInt32() override; - - int32_t value() const { return value_; } - void set_value(int32_t value) { value_ = value; } - - private: - int32_t value_ = 0; -}; - -class UnionWithTraitsStruct : public UnionWithTraitsBase { - public: - UnionWithTraitsStruct() { type_ = Type::STRUCT; } - explicit UnionWithTraitsStruct(int32_t value) : struct_(value) { - type_ = Type::STRUCT; - } - ~UnionWithTraitsStruct() override; - - NestedStructWithTraitsImpl& get_mutable_struct() { return struct_; } - const NestedStructWithTraitsImpl& get_struct() const { return struct_; } - - private: - NestedStructWithTraitsImpl struct_; -}; - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_H_ diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc deleted file mode 100644 index 6b770b1..0000000 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h" - -namespace mojo { -namespace { - -struct Context { - int32_t value; -}; - -} // namespace - -// static -void* StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - SetUpContext(const test::NestedStructWithTraitsImpl& input) { - Context* context = new Context; - context->value = input.value; - return context; -} - -// static -void StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - TearDownContext(const test::NestedStructWithTraitsImpl& input, - void* context) { - Context* context_obj = static_cast<Context*>(context); - CHECK_EQ(context_obj->value, input.value); - delete context_obj; -} - -// static -int32_t StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - value(const test::NestedStructWithTraitsImpl& input, void* context) { - Context* context_obj = static_cast<Context*>(context); - CHECK_EQ(context_obj->value, input.value); - return input.value; -} - -// static -bool StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - Read(test::NestedStructWithTraits::DataView data, - test::NestedStructWithTraitsImpl* output) { - output->value = data.value(); - return true; -} - -test::EnumWithTraits -EnumTraits<test::EnumWithTraits, test::EnumWithTraitsImpl>::ToMojom( - test::EnumWithTraitsImpl input) { - switch (input) { - case test::EnumWithTraitsImpl::CUSTOM_VALUE_0: - return test::EnumWithTraits::VALUE_0; - case test::EnumWithTraitsImpl::CUSTOM_VALUE_1: - return test::EnumWithTraits::VALUE_1; - }; - - NOTREACHED(); - return test::EnumWithTraits::VALUE_0; -} - -bool EnumTraits<test::EnumWithTraits, test::EnumWithTraitsImpl>::FromMojom( - test::EnumWithTraits input, - test::EnumWithTraitsImpl* output) { - switch (input) { - case test::EnumWithTraits::VALUE_0: - *output = test::EnumWithTraitsImpl::CUSTOM_VALUE_0; - return true; - case test::EnumWithTraits::VALUE_1: - *output = test::EnumWithTraitsImpl::CUSTOM_VALUE_1; - return true; - }; - - return false; -} - -// static -bool StructTraits<test::StructWithTraitsDataView, test::StructWithTraitsImpl>:: - Read(test::StructWithTraits::DataView data, - test::StructWithTraitsImpl* out) { - test::EnumWithTraitsImpl f_enum; - if (!data.ReadFEnum(&f_enum)) - return false; - out->set_enum(f_enum); - - out->set_bool(data.f_bool()); - out->set_uint32(data.f_uint32()); - out->set_uint64(data.f_uint64()); - - base::StringPiece f_string; - std::string f_string2; - if (!data.ReadFString(&f_string) || !data.ReadFString2(&f_string2) || - f_string != f_string2) { - return false; - } - out->set_string(f_string2); - - if (!data.ReadFStringArray(&out->get_mutable_string_array())) - return false; - - // We can't deserialize as a std::set, so we have to manually copy from the - // data view. - ArrayDataView<StringDataView> string_set_data_view; - data.GetFStringSetDataView(&string_set_data_view); - for (size_t i = 0; i < string_set_data_view.size(); ++i) { - std::string value; - string_set_data_view.Read(i, &value); - out->get_mutable_string_set().insert(value); - } - - if (!data.ReadFStruct(&out->get_mutable_struct())) - return false; - - if (!data.ReadFStructArray(&out->get_mutable_struct_array())) - return false; - - if (!data.ReadFStructMap(&out->get_mutable_struct_map())) - return false; - - return true; -} - -// static -bool StructTraits<test::MoveOnlyStructWithTraitsDataView, - test::MoveOnlyStructWithTraitsImpl>:: - Read(test::MoveOnlyStructWithTraits::DataView data, - test::MoveOnlyStructWithTraitsImpl* out) { - out->get_mutable_handle() = data.TakeFHandle(); - return true; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h deleted file mode 100644 index adcad8a..0000000 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_TRAITS_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/strings/string_piece.h" -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/tests/struct_with_traits_impl.h" -#include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h" - -namespace mojo { - -template <> -struct StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl> { - static void* SetUpContext(const test::NestedStructWithTraitsImpl& input); - static void TearDownContext(const test::NestedStructWithTraitsImpl& input, - void* context); - - static int32_t value(const test::NestedStructWithTraitsImpl& input, - void* context); - - static bool Read(test::NestedStructWithTraitsDataView data, - test::NestedStructWithTraitsImpl* output); -}; - -template <> -struct EnumTraits<test::EnumWithTraits, test::EnumWithTraitsImpl> { - static test::EnumWithTraits ToMojom(test::EnumWithTraitsImpl input); - static bool FromMojom(test::EnumWithTraits input, - test::EnumWithTraitsImpl* output); -}; - -template <> -struct StructTraits<test::StructWithTraitsDataView, - test::StructWithTraitsImpl> { - // Deserialization to test::StructTraitsImpl. - static bool Read(test::StructWithTraitsDataView data, - test::StructWithTraitsImpl* out); - - // Fields in test::StructWithTraits. - // See src/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom. - static test::EnumWithTraitsImpl f_enum( - const test::StructWithTraitsImpl& value) { - return value.get_enum(); - } - - static bool f_bool(const test::StructWithTraitsImpl& value) { - return value.get_bool(); - } - - static uint32_t f_uint32(const test::StructWithTraitsImpl& value) { - return value.get_uint32(); - } - - static uint64_t f_uint64(const test::StructWithTraitsImpl& value) { - return value.get_uint64(); - } - - static base::StringPiece f_string(const test::StructWithTraitsImpl& value) { - return value.get_string_as_string_piece(); - } - - static const std::string& f_string2(const test::StructWithTraitsImpl& value) { - return value.get_string(); - } - - static const std::vector<std::string>& f_string_array( - const test::StructWithTraitsImpl& value) { - return value.get_string_array(); - } - - static const std::set<std::string>& f_string_set( - const test::StructWithTraitsImpl& value) { - return value.get_string_set(); - } - - static const test::NestedStructWithTraitsImpl& f_struct( - const test::StructWithTraitsImpl& value) { - return value.get_struct(); - } - - static const std::vector<test::NestedStructWithTraitsImpl>& f_struct_array( - const test::StructWithTraitsImpl& value) { - return value.get_struct_array(); - } - - static const std::map<std::string, test::NestedStructWithTraitsImpl>& - f_struct_map(const test::StructWithTraitsImpl& value) { - return value.get_struct_map(); - } -}; - -template <> -struct StructTraits<test::TrivialStructWithTraitsDataView, - test::TrivialStructWithTraitsImpl> { - // Deserialization to test::TrivialStructTraitsImpl. - static bool Read(test::TrivialStructWithTraitsDataView data, - test::TrivialStructWithTraitsImpl* out) { - out->value = data.value(); - return true; - } - - // Fields in test::TrivialStructWithTraits. - // See src/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom. - static int32_t value(test::TrivialStructWithTraitsImpl& input) { - return input.value; - } -}; - -template <> -struct StructTraits<test::MoveOnlyStructWithTraitsDataView, - test::MoveOnlyStructWithTraitsImpl> { - // Deserialization to test::MoveOnlyStructTraitsImpl. - static bool Read(test::MoveOnlyStructWithTraitsDataView data, - test::MoveOnlyStructWithTraitsImpl* out); - - // Fields in test::MoveOnlyStructWithTraits. - // See src/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom. - static ScopedHandle f_handle(test::MoveOnlyStructWithTraitsImpl& value) { - return std::move(value.get_mutable_handle()); - } -}; - -template <> -struct StructTraits<test::StructWithTraitsForUniquePtrDataView, - std::unique_ptr<int>> { - static bool IsNull(const std::unique_ptr<int>& data) { return !data; } - static void SetToNull(std::unique_ptr<int>* data) { data->reset(); } - - static int f_int32(const std::unique_ptr<int>& data) { return *data; } - - static bool Read(test::StructWithTraitsForUniquePtrDataView data, - std::unique_ptr<int>* out) { - out->reset(new int(data.f_int32())); - return true; - } -}; - -template <> -struct UnionTraits<test::UnionWithTraitsDataView, - std::unique_ptr<test::UnionWithTraitsBase>> { - static bool IsNull(const std::unique_ptr<test::UnionWithTraitsBase>& data) { - return !data; - } - static void SetToNull(std::unique_ptr<test::UnionWithTraitsBase>* data) { - data->reset(); - } - - static test::UnionWithTraitsDataView::Tag GetTag( - const std::unique_ptr<test::UnionWithTraitsBase>& data) { - if (data->type() == test::UnionWithTraitsBase::Type::INT32) - return test::UnionWithTraitsDataView::Tag::F_INT32; - - return test::UnionWithTraitsDataView::Tag::F_STRUCT; - } - - static int32_t f_int32( - const std::unique_ptr<test::UnionWithTraitsBase>& data) { - return static_cast<test::UnionWithTraitsInt32*>(data.get())->value(); - } - - static const test::NestedStructWithTraitsImpl& f_struct( - const std::unique_ptr<test::UnionWithTraitsBase>& data) { - return static_cast<test::UnionWithTraitsStruct*>(data.get())->get_struct(); - } - - static bool Read(test::UnionWithTraitsDataView data, - std::unique_ptr<test::UnionWithTraitsBase>* out) { - switch (data.tag()) { - case test::UnionWithTraitsDataView::Tag::F_INT32: { - out->reset(new test::UnionWithTraitsInt32(data.f_int32())); - return true; - } - case test::UnionWithTraitsDataView::Tag::F_STRUCT: { - auto* struct_object = new test::UnionWithTraitsStruct(); - out->reset(struct_object); - return data.ReadFStruct(&struct_object->get_mutable_struct()); - } - } - - NOTREACHED(); - return false; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_STRUCT_WITH_TRAITS_IMPL_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc deleted file mode 100644 index 084e080..0000000 --- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc +++ /dev/null @@ -1,831 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -template <typename... Args> -struct LambdaBinder { - using CallbackType = base::Callback<void(Args...)>; - - template <typename Func> - static void RunLambda(Func func, Args... args) { - func(std::move(args)...); - } - - template <typename Func> - static CallbackType BindLambda(Func func) { - return base::Bind(&LambdaBinder::RunLambda<Func>, func); - } -}; - -class TestSyncCommonImpl { - public: - TestSyncCommonImpl() {} - - using PingHandler = base::Callback<void(const base::Callback<void()>&)>; - using PingBinder = LambdaBinder<const base::Callback<void()>&>; - template <typename Func> - void set_ping_handler(Func handler) { - ping_handler_ = PingBinder::BindLambda(handler); - } - - using EchoHandler = - base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>; - using EchoBinder = - LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>; - template <typename Func> - void set_echo_handler(Func handler) { - echo_handler_ = EchoBinder::BindLambda(handler); - } - - using AsyncEchoHandler = - base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>; - using AsyncEchoBinder = - LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>; - template <typename Func> - void set_async_echo_handler(Func handler) { - async_echo_handler_ = AsyncEchoBinder::BindLambda(handler); - } - - using SendInterfaceHandler = base::Callback<void(TestSyncAssociatedPtrInfo)>; - using SendInterfaceBinder = LambdaBinder<TestSyncAssociatedPtrInfo>; - template <typename Func> - void set_send_interface_handler(Func handler) { - send_interface_handler_ = SendInterfaceBinder::BindLambda(handler); - } - - using SendRequestHandler = base::Callback<void(TestSyncAssociatedRequest)>; - using SendRequestBinder = LambdaBinder<TestSyncAssociatedRequest>; - template <typename Func> - void set_send_request_handler(Func handler) { - send_request_handler_ = SendRequestBinder::BindLambda(handler); - } - - void PingImpl(const base::Callback<void()>& callback) { - if (ping_handler_.is_null()) { - callback.Run(); - return; - } - ping_handler_.Run(callback); - } - void EchoImpl(int32_t value, const base::Callback<void(int32_t)>& callback) { - if (echo_handler_.is_null()) { - callback.Run(value); - return; - } - echo_handler_.Run(value, callback); - } - void AsyncEchoImpl(int32_t value, - const base::Callback<void(int32_t)>& callback) { - if (async_echo_handler_.is_null()) { - callback.Run(value); - return; - } - async_echo_handler_.Run(value, callback); - } - void SendInterfaceImpl(TestSyncAssociatedPtrInfo ptr) { - send_interface_handler_.Run(std::move(ptr)); - } - void SendRequestImpl(TestSyncAssociatedRequest request) { - send_request_handler_.Run(std::move(request)); - } - - private: - PingHandler ping_handler_; - EchoHandler echo_handler_; - AsyncEchoHandler async_echo_handler_; - SendInterfaceHandler send_interface_handler_; - SendRequestHandler send_request_handler_; - - DISALLOW_COPY_AND_ASSIGN(TestSyncCommonImpl); -}; - -class TestSyncImpl : public TestSync, public TestSyncCommonImpl { - public: - explicit TestSyncImpl(TestSyncRequest request) - : binding_(this, std::move(request)) {} - - // TestSync implementation: - void Ping(const PingCallback& callback) override { PingImpl(callback); } - void Echo(int32_t value, const EchoCallback& callback) override { - EchoImpl(value, callback); - } - void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { - AsyncEchoImpl(value, callback); - } - - Binding<TestSync>* binding() { return &binding_; } - - private: - Binding<TestSync> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestSyncImpl); -}; - -class TestSyncMasterImpl : public TestSyncMaster, public TestSyncCommonImpl { - public: - explicit TestSyncMasterImpl(TestSyncMasterRequest request) - : binding_(this, std::move(request)) {} - - // TestSyncMaster implementation: - void Ping(const PingCallback& callback) override { PingImpl(callback); } - void Echo(int32_t value, const EchoCallback& callback) override { - EchoImpl(value, callback); - } - void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { - AsyncEchoImpl(value, callback); - } - void SendInterface(TestSyncAssociatedPtrInfo ptr) override { - SendInterfaceImpl(std::move(ptr)); - } - void SendRequest(TestSyncAssociatedRequest request) override { - SendRequestImpl(std::move(request)); - } - - Binding<TestSyncMaster>* binding() { return &binding_; } - - private: - Binding<TestSyncMaster> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestSyncMasterImpl); -}; - -class TestSyncAssociatedImpl : public TestSync, public TestSyncCommonImpl { - public: - explicit TestSyncAssociatedImpl(TestSyncAssociatedRequest request) - : binding_(this, std::move(request)) {} - - // TestSync implementation: - void Ping(const PingCallback& callback) override { PingImpl(callback); } - void Echo(int32_t value, const EchoCallback& callback) override { - EchoImpl(value, callback); - } - void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { - AsyncEchoImpl(value, callback); - } - - AssociatedBinding<TestSync>* binding() { return &binding_; } - - private: - AssociatedBinding<TestSync> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestSyncAssociatedImpl); -}; - -template <typename Interface> -struct ImplTraits; - -template <> -struct ImplTraits<TestSync> { - using Type = TestSyncImpl; -}; - -template <> -struct ImplTraits<TestSyncMaster> { - using Type = TestSyncMasterImpl; -}; - -template <typename Interface> -using ImplTypeFor = typename ImplTraits<Interface>::Type; - -// A wrapper for either an InterfacePtr or scoped_refptr<ThreadSafeInterfacePtr> -// that exposes the InterfacePtr interface. -template <typename Interface> -class PtrWrapper { - public: - explicit PtrWrapper(InterfacePtr<Interface> ptr) : ptr_(std::move(ptr)) {} - - explicit PtrWrapper( - scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr) - : thread_safe_ptr_(thread_safe_ptr) {} - - PtrWrapper(PtrWrapper&& other) = default; - - Interface* operator->() { - return thread_safe_ptr_ ? thread_safe_ptr_->get() : ptr_.get(); - } - - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(!thread_safe_ptr_); - ptr_.set_connection_error_handler(error_handler); - } - - void reset() { - ptr_ = nullptr; - thread_safe_ptr_ = nullptr; - } - - private: - InterfacePtr<Interface> ptr_; - scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr_; - - DISALLOW_COPY_AND_ASSIGN(PtrWrapper); -}; - -// The type parameter for SyncMethodCommonTests for varying the Interface and -// whether to use InterfacePtr or ThreadSafeInterfacePtr. -template <typename InterfaceT, bool use_thread_safe_ptr> -struct TestParams { - using Interface = InterfaceT; - static const bool kIsThreadSafeInterfacePtrTest = use_thread_safe_ptr; - - static PtrWrapper<InterfaceT> Wrap(InterfacePtr<Interface> ptr) { - if (kIsThreadSafeInterfacePtrTest) { - return PtrWrapper<Interface>( - ThreadSafeInterfacePtr<Interface>::Create(std::move(ptr))); - } else { - return PtrWrapper<Interface>(std::move(ptr)); - } - } -}; - -template <typename Interface> -class TestSyncServiceThread { - public: - TestSyncServiceThread() - : thread_("TestSyncServiceThread"), ping_called_(false) { - thread_.Start(); - } - - void SetUp(InterfaceRequest<Interface> request) { - CHECK(thread_.task_runner()->BelongsToCurrentThread()); - impl_.reset(new ImplTypeFor<Interface>(std::move(request))); - impl_->set_ping_handler( - [this](const typename Interface::PingCallback& callback) { - { - base::AutoLock locker(lock_); - ping_called_ = true; - } - callback.Run(); - }); - } - - void TearDown() { - CHECK(thread_.task_runner()->BelongsToCurrentThread()); - impl_.reset(); - } - - base::Thread* thread() { return &thread_; } - bool ping_called() const { - base::AutoLock locker(lock_); - return ping_called_; - } - - private: - base::Thread thread_; - - std::unique_ptr<ImplTypeFor<Interface>> impl_; - - mutable base::Lock lock_; - bool ping_called_; - - DISALLOW_COPY_AND_ASSIGN(TestSyncServiceThread); -}; - -class SyncMethodTest : public testing::Test { - public: - SyncMethodTest() {} - ~SyncMethodTest() override { base::RunLoop().RunUntilIdle(); } - - protected: - base::MessageLoop loop_; -}; - -template <typename T> -class SyncMethodCommonTest : public SyncMethodTest { - public: - SyncMethodCommonTest() {} - ~SyncMethodCommonTest() override {} -}; - -class SyncMethodAssociatedTest : public SyncMethodTest { - public: - SyncMethodAssociatedTest() {} - ~SyncMethodAssociatedTest() override {} - - protected: - void SetUp() override { - master_impl_.reset(new TestSyncMasterImpl(MakeRequest(&master_ptr_))); - - asso_request_ = MakeRequest(&asso_ptr_info_); - opposite_asso_request_ = MakeRequest(&opposite_asso_ptr_info_); - - master_impl_->set_send_interface_handler( - [this](TestSyncAssociatedPtrInfo ptr) { - opposite_asso_ptr_info_ = std::move(ptr); - }); - base::RunLoop run_loop; - master_impl_->set_send_request_handler( - [this, &run_loop](TestSyncAssociatedRequest request) { - asso_request_ = std::move(request); - run_loop.Quit(); - }); - - master_ptr_->SendInterface(std::move(opposite_asso_ptr_info_)); - master_ptr_->SendRequest(std::move(asso_request_)); - run_loop.Run(); - } - - void TearDown() override { - asso_ptr_info_ = TestSyncAssociatedPtrInfo(); - asso_request_ = TestSyncAssociatedRequest(); - opposite_asso_ptr_info_ = TestSyncAssociatedPtrInfo(); - opposite_asso_request_ = TestSyncAssociatedRequest(); - - master_ptr_ = nullptr; - master_impl_.reset(); - } - - InterfacePtr<TestSyncMaster> master_ptr_; - std::unique_ptr<TestSyncMasterImpl> master_impl_; - - // An associated interface whose binding lives at the |master_impl_| side. - TestSyncAssociatedPtrInfo asso_ptr_info_; - TestSyncAssociatedRequest asso_request_; - - // An associated interface whose binding lives at the |master_ptr_| side. - TestSyncAssociatedPtrInfo opposite_asso_ptr_info_; - TestSyncAssociatedRequest opposite_asso_request_; -}; - -void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) { - *flag = true; - closure.Run(); -} - -void ExpectValueAndRunClosure(int32_t expected_value, - const base::Closure& closure, - int32_t value) { - EXPECT_EQ(expected_value, value); - closure.Run(); -} - -template <typename Func> -void CallAsyncEchoCallback(Func func, int32_t value) { - func(value); -} - -template <typename Func> -TestSync::AsyncEchoCallback BindAsyncEchoCallback(Func func) { - return base::Bind(&CallAsyncEchoCallback<Func>, func); -} - -// TestSync (without associated interfaces) and TestSyncMaster (with associated -// interfaces) exercise MultiplexRouter with different configurations. -// Each test is run once with an InterfacePtr and once with a -// ThreadSafeInterfacePtr to ensure that they behave the same with respect to -// sync calls. -using InterfaceTypes = testing::Types<TestParams<TestSync, true>, - TestParams<TestSync, false>, - TestParams<TestSyncMaster, true>, - TestParams<TestSyncMaster, false>>; -TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes); - -TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) { - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - base::RunLoop run_loop; - ptr->Echo(123, base::Bind(&ExpectValueAndRunClosure, 123, - run_loop.QuitClosure())); - run_loop.Run(); -} - -TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) { - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - InterfaceRequest<Interface> request = MakeRequest(&interface_ptr); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - TestSyncServiceThread<Interface> service_thread; - service_thread.thread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestSyncServiceThread<Interface>::SetUp, - base::Unretained(&service_thread), base::Passed(&request))); - ASSERT_TRUE(ptr->Ping()); - ASSERT_TRUE(service_thread.ping_called()); - - int32_t output_value = -1; - ASSERT_TRUE(ptr->Echo(42, &output_value)); - ASSERT_EQ(42, output_value); - - base::RunLoop run_loop; - service_thread.thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&TestSyncServiceThread<Interface>::TearDown, - base::Unretained(&service_thread)), - run_loop.QuitClosure()); - run_loop.Run(); -} - -TYPED_TEST(SyncMethodCommonTest, ReenteredBySyncMethodBinding) { - // Test that an interface pointer waiting for a sync call response can be - // reentered by a binding serving sync methods on the same thread. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - // The binding lives on the same thread as the interface pointer. - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - int32_t output_value = -1; - ASSERT_TRUE(ptr->Echo(42, &output_value)); - EXPECT_EQ(42, output_value); -} - -TYPED_TEST(SyncMethodCommonTest, InterfacePtrDestroyedDuringSyncCall) { - // Test that it won't result in crash or hang if an interface pointer is - // destroyed while it is waiting for a sync call response. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - impl.set_ping_handler([&ptr](const TestSync::PingCallback& callback) { - ptr.reset(); - callback.Run(); - }); - ASSERT_FALSE(ptr->Ping()); -} - -TYPED_TEST(SyncMethodCommonTest, BindingDestroyedDuringSyncCall) { - // Test that it won't result in crash or hang if a binding is - // closed (and therefore the message pipe handle is closed) while the - // corresponding interface pointer is waiting for a sync call response. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - impl.set_ping_handler([&impl](const TestSync::PingCallback& callback) { - impl.binding()->Close(); - callback.Run(); - }); - ASSERT_FALSE(ptr->Ping()); -} - -TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithInOrderResponses) { - // Test that we can call a sync method on an interface ptr, while there is - // already a sync call ongoing. The responses arrive in order. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - // The same variable is used to store the output of the two sync calls, in - // order to test that responses are handled in the correct order. - int32_t result_value = -1; - - bool first_call = true; - impl.set_echo_handler([&first_call, &ptr, &result_value]( - int32_t value, const TestSync::EchoCallback& callback) { - if (first_call) { - first_call = false; - ASSERT_TRUE(ptr->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); - } - callback.Run(value); - }); - - ASSERT_TRUE(ptr->Echo(123, &result_value)); - EXPECT_EQ(123, result_value); -} - -TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithOutOfOrderResponses) { - // Test that we can call a sync method on an interface ptr, while there is - // already a sync call ongoing. The responses arrive out of order. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - // The same variable is used to store the output of the two sync calls, in - // order to test that responses are handled in the correct order. - int32_t result_value = -1; - - bool first_call = true; - impl.set_echo_handler([&first_call, &ptr, &result_value]( - int32_t value, const TestSync::EchoCallback& callback) { - callback.Run(value); - if (first_call) { - first_call = false; - ASSERT_TRUE(ptr->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); - } - }); - - ASSERT_TRUE(ptr->Echo(123, &result_value)); - EXPECT_EQ(123, result_value); -} - -TYPED_TEST(SyncMethodCommonTest, AsyncResponseQueuedDuringSyncCall) { - // Test that while an interface pointer is waiting for the response to a sync - // call, async responses are queued until the sync call completes. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - int32_t async_echo_request_value = -1; - TestSync::AsyncEchoCallback async_echo_request_callback; - base::RunLoop run_loop1; - impl.set_async_echo_handler( - [&async_echo_request_value, &async_echo_request_callback, &run_loop1]( - int32_t value, const TestSync::AsyncEchoCallback& callback) { - async_echo_request_value = value; - async_echo_request_callback = callback; - run_loop1.Quit(); - }); - - bool async_echo_response_dispatched = false; - base::RunLoop run_loop2; - ptr->AsyncEcho( - 123, - BindAsyncEchoCallback( - [&async_echo_response_dispatched, &run_loop2](int32_t result) { - async_echo_response_dispatched = true; - EXPECT_EQ(123, result); - run_loop2.Quit(); - })); - // Run until the AsyncEcho request reaches the service side. - run_loop1.Run(); - - impl.set_echo_handler( - [&async_echo_request_value, &async_echo_request_callback]( - int32_t value, const TestSync::EchoCallback& callback) { - // Send back the async response first. - EXPECT_FALSE(async_echo_request_callback.is_null()); - async_echo_request_callback.Run(async_echo_request_value); - - callback.Run(value); - }); - - int32_t result_value = -1; - ASSERT_TRUE(ptr->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); - - // Although the AsyncEcho response arrives before the Echo response, it should - // be queued and not yet dispatched. - EXPECT_FALSE(async_echo_response_dispatched); - - // Run until the AsyncEcho response is dispatched. - run_loop2.Run(); - - EXPECT_TRUE(async_echo_response_dispatched); -} - -TYPED_TEST(SyncMethodCommonTest, AsyncRequestQueuedDuringSyncCall) { - // Test that while an interface pointer is waiting for the response to a sync - // call, async requests for a binding running on the same thread are queued - // until the sync call completes. - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> interface_ptr; - ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - bool async_echo_request_dispatched = false; - impl.set_async_echo_handler([&async_echo_request_dispatched]( - int32_t value, const TestSync::AsyncEchoCallback& callback) { - async_echo_request_dispatched = true; - callback.Run(value); - }); - - bool async_echo_response_dispatched = false; - base::RunLoop run_loop; - ptr->AsyncEcho( - 123, - BindAsyncEchoCallback( - [&async_echo_response_dispatched, &run_loop](int32_t result) { - async_echo_response_dispatched = true; - EXPECT_EQ(123, result); - run_loop.Quit(); - })); - - impl.set_echo_handler([&async_echo_request_dispatched]( - int32_t value, const TestSync::EchoCallback& callback) { - // Although the AsyncEcho request is sent before the Echo request, it - // shouldn't be dispatched yet at this point, because there is an ongoing - // sync call on the same thread. - EXPECT_FALSE(async_echo_request_dispatched); - callback.Run(value); - }); - - int32_t result_value = -1; - ASSERT_TRUE(ptr->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); - - // Although the AsyncEcho request is sent before the Echo request, it - // shouldn't be dispatched yet. - EXPECT_FALSE(async_echo_request_dispatched); - - // Run until the AsyncEcho response is dispatched. - run_loop.Run(); - - EXPECT_TRUE(async_echo_response_dispatched); -} - -TYPED_TEST(SyncMethodCommonTest, - QueuedMessagesProcessedBeforeErrorNotification) { - // Test that while an interface pointer is waiting for the response to a sync - // call, async responses are queued. If the message pipe is disconnected - // before the queued messages are processed, the connection error - // notification is delayed until all the queued messages are processed. - - // ThreadSafeInterfacePtr doesn't guarantee that messages are delivered before - // error notifications, so skip it for this test. - if (TypeParam::kIsThreadSafeInterfacePtrTest) - return; - - using Interface = typename TypeParam::Interface; - InterfacePtr<Interface> ptr; - ImplTypeFor<Interface> impl(MakeRequest(&ptr)); - - int32_t async_echo_request_value = -1; - TestSync::AsyncEchoCallback async_echo_request_callback; - base::RunLoop run_loop1; - impl.set_async_echo_handler( - [&async_echo_request_value, &async_echo_request_callback, &run_loop1]( - int32_t value, const TestSync::AsyncEchoCallback& callback) { - async_echo_request_value = value; - async_echo_request_callback = callback; - run_loop1.Quit(); - }); - - bool async_echo_response_dispatched = false; - bool connection_error_dispatched = false; - base::RunLoop run_loop2; - ptr->AsyncEcho( - 123, - BindAsyncEchoCallback( - [&async_echo_response_dispatched, &connection_error_dispatched, &ptr, - &run_loop2](int32_t result) { - async_echo_response_dispatched = true; - // At this point, error notification should not be dispatched - // yet. - EXPECT_FALSE(connection_error_dispatched); - EXPECT_FALSE(ptr.encountered_error()); - EXPECT_EQ(123, result); - run_loop2.Quit(); - })); - // Run until the AsyncEcho request reaches the service side. - run_loop1.Run(); - - impl.set_echo_handler( - [&impl, &async_echo_request_value, &async_echo_request_callback]( - int32_t value, const TestSync::EchoCallback& callback) { - // Send back the async response first. - EXPECT_FALSE(async_echo_request_callback.is_null()); - async_echo_request_callback.Run(async_echo_request_value); - - impl.binding()->Close(); - }); - - base::RunLoop run_loop3; - ptr.set_connection_error_handler( - base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched, - run_loop3.QuitClosure())); - - int32_t result_value = -1; - ASSERT_FALSE(ptr->Echo(456, &result_value)); - EXPECT_EQ(-1, result_value); - ASSERT_FALSE(connection_error_dispatched); - EXPECT_FALSE(ptr.encountered_error()); - - // Although the AsyncEcho response arrives before the Echo response, it should - // be queued and not yet dispatched. - EXPECT_FALSE(async_echo_response_dispatched); - - // Run until the AsyncEcho response is dispatched. - run_loop2.Run(); - - EXPECT_TRUE(async_echo_response_dispatched); - - // Run until the error notification is dispatched. - run_loop3.Run(); - - ASSERT_TRUE(connection_error_dispatched); - EXPECT_TRUE(ptr.encountered_error()); -} - -TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) { - // Test that while an interface pointer is waiting for the response to a sync - // call, an invalid incoming message will disconnect the message pipe, cause - // the sync call to return false, and run the connection error handler - // asynchronously. - - using Interface = typename TypeParam::Interface; - MessagePipe pipe; - - InterfacePtr<Interface> interface_ptr; - interface_ptr.Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u)); - auto ptr = TypeParam::Wrap(std::move(interface_ptr)); - - MessagePipeHandle raw_binding_handle = pipe.handle1.get(); - ImplTypeFor<Interface> impl(MakeRequest<Interface>(std::move(pipe.handle1))); - - impl.set_echo_handler([&raw_binding_handle]( - int32_t value, const TestSync::EchoCallback& callback) { - // Write a 1-byte message, which is considered invalid. - char invalid_message = 0; - MojoResult result = - WriteMessageRaw(raw_binding_handle, &invalid_message, 1u, nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE); - ASSERT_EQ(MOJO_RESULT_OK, result); - callback.Run(value); - }); - - bool connection_error_dispatched = false; - base::RunLoop run_loop; - // ThreadSafeInterfacePtr doesn't support setting connection error handlers. - if (!TypeParam::kIsThreadSafeInterfacePtrTest) { - ptr.set_connection_error_handler(base::Bind(&SetFlagAndRunClosure, - &connection_error_dispatched, - run_loop.QuitClosure())); - } - - int32_t result_value = -1; - ASSERT_FALSE(ptr->Echo(456, &result_value)); - EXPECT_EQ(-1, result_value); - ASSERT_FALSE(connection_error_dispatched); - - if (!TypeParam::kIsThreadSafeInterfacePtrTest) { - run_loop.Run(); - ASSERT_TRUE(connection_error_dispatched); - } -} - -TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) { - // Test that an interface pointer waiting for a sync call response can be - // reentered by an associated binding serving sync methods on the same thread. - // The associated binding belongs to the same MultiplexRouter as the waiting - // interface pointer. - - TestSyncAssociatedImpl opposite_asso_impl(std::move(opposite_asso_request_)); - TestSyncAssociatedPtr opposite_asso_ptr; - opposite_asso_ptr.Bind(std::move(opposite_asso_ptr_info_)); - - master_impl_->set_echo_handler([&opposite_asso_ptr]( - int32_t value, const TestSyncMaster::EchoCallback& callback) { - int32_t result_value = -1; - - ASSERT_TRUE(opposite_asso_ptr->Echo(123, &result_value)); - EXPECT_EQ(123, result_value); - callback.Run(value); - }); - - int32_t result_value = -1; - ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); -} - -TEST_F(SyncMethodAssociatedTest, - ReenteredBySyncMethodAssoBindingOfDifferentRouter) { - // Test that an interface pointer waiting for a sync call response can be - // reentered by an associated binding serving sync methods on the same thread. - // The associated binding belongs to a different MultiplexRouter as the - // waiting interface pointer. - - TestSyncAssociatedImpl asso_impl(std::move(asso_request_)); - TestSyncAssociatedPtr asso_ptr; - asso_ptr.Bind(std::move(asso_ptr_info_)); - - master_impl_->set_echo_handler( - [&asso_ptr](int32_t value, const TestSyncMaster::EchoCallback& callback) { - int32_t result_value = -1; - - ASSERT_TRUE(asso_ptr->Echo(123, &result_value)); - EXPECT_EQ(123, result_value); - callback.Run(value); - }); - - int32_t result_value = -1; - ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); - EXPECT_EQ(456, result_value); -} - -// TODO(yzshen): Add more tests related to associated interfaces. - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/test_native_types_blink.typemap b/mojo/public/cpp/bindings/tests/test_native_types_blink.typemap deleted file mode 100644 index 1bdfbbc..0000000 --- a/mojo/public/cpp/bindings/tests/test_native_types_blink.typemap +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/public/interfaces/bindings/tests/test_native_types.mojom" -public_headers = [ "//mojo/public/cpp/bindings/tests/pickled_types_blink.h" ] -sources = [ - "//mojo/public/cpp/bindings/tests/pickled_types_blink.cc", -] -deps = [ - "//ipc", -] - -type_mappings = [ - "mojo.test.PickledEnum=mojo::test::PickledEnumBlink", - "mojo.test.PickledStruct=mojo::test::PickledStructBlink[move_only]", -] diff --git a/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap b/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap deleted file mode 100644 index 50e8076..0000000 --- a/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/public/interfaces/bindings/tests/test_native_types.mojom" -public_headers = [ "//mojo/public/cpp/bindings/tests/pickled_types_chromium.h" ] -sources = [ - "//mojo/public/cpp/bindings/tests/pickled_types_chromium.cc", -] -deps = [ - "//ipc", -] - -type_mappings = [ - "mojo.test.PickledEnum=mojo::test::PickledEnumChromium", - "mojo.test.PickledStruct=mojo::test::PickledStructChromium[move_only]", -] diff --git a/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc b/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc deleted file mode 100644 index b0124aa..0000000 --- a/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc +++ /dev/null @@ -1,161 +0,0 @@ -// 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. - -#include <stddef.h> -#include <stdint.h> - -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -struct RedmondRect { - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; -}; - -struct RedmondNamedRegion { - std::string name; - std::vector<RedmondRect> rects; -}; - -bool AreEqualRectArrays(const std::vector<test::RectPtr>& rects1, - const std::vector<test::RectPtr>& rects2) { - if (rects1.size() != rects2.size()) - return false; - - for (size_t i = 0; i < rects1.size(); ++i) { - if (rects1[i]->x != rects2[i]->x || rects1[i]->y != rects2[i]->y || - rects1[i]->width != rects2[i]->width || - rects1[i]->height != rects2[i]->height) { - return false; - } - } - - return true; -} - -} // namespace - -template <> -struct TypeConverter<test::RectPtr, RedmondRect> { - static test::RectPtr Convert(const RedmondRect& input) { - return test::Rect::New(input.left, input.top, input.right - input.left, - input.bottom - input.top); - } -}; - -template <> -struct TypeConverter<RedmondRect, test::RectPtr> { - static RedmondRect Convert(const test::RectPtr& input) { - RedmondRect rect; - rect.left = input->x; - rect.top = input->y; - rect.right = input->x + input->width; - rect.bottom = input->y + input->height; - return rect; - } -}; - -template <> -struct TypeConverter<test::NamedRegionPtr, RedmondNamedRegion> { - static test::NamedRegionPtr Convert(const RedmondNamedRegion& input) { - return test::NamedRegion::New( - input.name, ConvertTo<std::vector<test::RectPtr>>(input.rects)); - } -}; - -template <> -struct TypeConverter<RedmondNamedRegion, test::NamedRegionPtr> { - static RedmondNamedRegion Convert(const test::NamedRegionPtr& input) { - RedmondNamedRegion region; - if (input->name) - region.name = input->name.value(); - if (input->rects) { - region.rects.reserve(input->rects->size()); - for (const auto& element : *input->rects) - region.rects.push_back(element.To<RedmondRect>()); - } - return region; - } -}; - -namespace test { -namespace { - -TEST(TypeConversionTest, CustomTypeConverter) { - RectPtr rect(Rect::New(10, 20, 50, 45)); - - RedmondRect rr = rect.To<RedmondRect>(); - EXPECT_EQ(10, rr.left); - EXPECT_EQ(20, rr.top); - EXPECT_EQ(60, rr.right); - EXPECT_EQ(65, rr.bottom); - - RectPtr rect2(Rect::From(rr)); - EXPECT_EQ(rect->x, rect2->x); - EXPECT_EQ(rect->y, rect2->y); - EXPECT_EQ(rect->width, rect2->width); - EXPECT_EQ(rect->height, rect2->height); -} - -TEST(TypeConversionTest, CustomTypeConverter_Array_Null) { - std::vector<RectPtr> rects; - - auto redmond_rects = ConvertTo<std::vector<RedmondRect>>(rects); - - EXPECT_TRUE(redmond_rects.empty()); -} - -TEST(TypeConversionTest, CustomTypeConverter_Array) { - const RedmondRect kBase = {10, 20, 30, 40}; - - std::vector<RectPtr> rects(10); - for (size_t i = 0; i < rects.size(); ++i) { - RedmondRect rr = kBase; - rr.left += static_cast<int32_t>(i); - rr.top += static_cast<int32_t>(i); - rects[i] = Rect::From(rr); - } - - auto redmond_rects = ConvertTo<std::vector<RedmondRect>>(rects); - - auto rects2 = ConvertTo<std::vector<RectPtr>>(redmond_rects); - EXPECT_TRUE(AreEqualRectArrays(rects, rects2)); -} - -TEST(TypeConversionTest, CustomTypeConverter_Nested) { - RedmondNamedRegion redmond_region; - redmond_region.name = "foopy"; - - const RedmondRect kBase = {10, 20, 30, 40}; - - for (size_t i = 0; i < 10; ++i) { - RedmondRect rect = kBase; - rect.left += static_cast<int32_t>(i); - rect.top += static_cast<int32_t>(i); - redmond_region.rects.push_back(rect); - } - - // Round-trip through generated struct and TypeConverter. - - NamedRegionPtr copy = NamedRegion::From(redmond_region); - RedmondNamedRegion redmond_region2 = copy.To<RedmondNamedRegion>(); - - EXPECT_EQ(redmond_region.name, redmond_region2.name); - EXPECT_EQ(redmond_region.rects.size(), redmond_region2.rects.size()); - for (size_t i = 0; i < redmond_region.rects.size(); ++i) { - EXPECT_EQ(redmond_region.rects[i].left, redmond_region2.rects[i].left); - EXPECT_EQ(redmond_region.rects[i].top, redmond_region2.rects[i].top); - EXPECT_EQ(redmond_region.rects[i].right, redmond_region2.rects[i].right); - EXPECT_EQ(redmond_region.rects[i].bottom, redmond_region2.rects[i].bottom); - } -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc deleted file mode 100644 index bdf27df..0000000 --- a/mojo/public/cpp/bindings/tests/union_unittest.cc +++ /dev/null @@ -1,1246 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <utility> -#include <vector> - -#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/array_internal.h" -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" -#include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { - -TEST(UnionTest, PlainOldDataGetterSetter) { - PodUnionPtr pod(PodUnion::New()); - - pod->set_f_int8(10); - EXPECT_EQ(10, pod->get_f_int8()); - EXPECT_TRUE(pod->is_f_int8()); - EXPECT_FALSE(pod->is_f_int8_other()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT8); - - pod->set_f_uint8(11); - EXPECT_EQ(11, pod->get_f_uint8()); - EXPECT_TRUE(pod->is_f_uint8()); - EXPECT_FALSE(pod->is_f_int8()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT8); - - pod->set_f_int16(12); - EXPECT_EQ(12, pod->get_f_int16()); - EXPECT_TRUE(pod->is_f_int16()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT16); - - pod->set_f_uint16(13); - EXPECT_EQ(13, pod->get_f_uint16()); - EXPECT_TRUE(pod->is_f_uint16()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT16); - - pod->set_f_int32(14); - EXPECT_EQ(14, pod->get_f_int32()); - EXPECT_TRUE(pod->is_f_int32()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT32); - - pod->set_f_uint32(static_cast<uint32_t>(15)); - EXPECT_EQ(static_cast<uint32_t>(15), pod->get_f_uint32()); - EXPECT_TRUE(pod->is_f_uint32()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT32); - - pod->set_f_int64(16); - EXPECT_EQ(16, pod->get_f_int64()); - EXPECT_TRUE(pod->is_f_int64()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT64); - - pod->set_f_uint64(static_cast<uint64_t>(17)); - EXPECT_EQ(static_cast<uint64_t>(17), pod->get_f_uint64()); - EXPECT_TRUE(pod->is_f_uint64()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT64); - - pod->set_f_float(1.5); - EXPECT_EQ(1.5, pod->get_f_float()); - EXPECT_TRUE(pod->is_f_float()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_FLOAT); - - pod->set_f_double(1.9); - EXPECT_EQ(1.9, pod->get_f_double()); - EXPECT_TRUE(pod->is_f_double()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_DOUBLE); - - pod->set_f_bool(true); - EXPECT_TRUE(pod->get_f_bool()); - pod->set_f_bool(false); - EXPECT_FALSE(pod->get_f_bool()); - EXPECT_TRUE(pod->is_f_bool()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_BOOL); - - pod->set_f_enum(AnEnum::SECOND); - EXPECT_EQ(AnEnum::SECOND, pod->get_f_enum()); - EXPECT_TRUE(pod->is_f_enum()); - EXPECT_EQ(pod->which(), PodUnion::Tag::F_ENUM); -} - -TEST(UnionTest, PodEquals) { - PodUnionPtr pod1(PodUnion::New()); - PodUnionPtr pod2(PodUnion::New()); - - pod1->set_f_int8(10); - pod2->set_f_int8(10); - EXPECT_TRUE(pod1.Equals(pod2)); - - pod2->set_f_int8(11); - EXPECT_FALSE(pod1.Equals(pod2)); - - pod2->set_f_int8_other(10); - EXPECT_FALSE(pod1.Equals(pod2)); -} - -TEST(UnionTest, PodClone) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(10); - - PodUnionPtr pod_clone = pod.Clone(); - EXPECT_EQ(10, pod_clone->get_f_int8()); - EXPECT_TRUE(pod_clone->is_f_int8()); - EXPECT_EQ(pod_clone->which(), PodUnion::Tag::F_INT8); -} - -TEST(UnionTest, PodSerialization) { - PodUnionPtr pod1(PodUnion::New()); - pod1->set_f_int8(10); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>( - pod1, false, &context); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod1, &buf, &data, false, - &context); - - PodUnionPtr pod2; - mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, &context); - - EXPECT_EQ(10, pod2->get_f_int8()); - EXPECT_TRUE(pod2->is_f_int8()); - EXPECT_EQ(pod2->which(), PodUnion::Tag::F_INT8); -} - -TEST(UnionTest, EnumSerialization) { - PodUnionPtr pod1(PodUnion::New()); - pod1->set_f_enum(AnEnum::SECOND); - - size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>( - pod1, false, nullptr); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod1, &buf, &data, false, - nullptr); - - PodUnionPtr pod2; - mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, nullptr); - - EXPECT_EQ(AnEnum::SECOND, pod2->get_f_enum()); - EXPECT_TRUE(pod2->is_f_enum()); - EXPECT_EQ(pod2->which(), PodUnion::Tag::F_ENUM); -} - -TEST(UnionTest, PodValidation) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(10); - - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false, nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE( - internal::PodUnion_Data::Validate(raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, SerializeNotNull) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(0); - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false, nullptr); - EXPECT_FALSE(data->is_null()); -} - -TEST(UnionTest, SerializeIsNullInlined) { - PodUnionPtr pod; - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - EXPECT_EQ(16U, size); - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf); - - // Check that dirty output buffers are handled correctly by serialization. - data->size = 16U; - data->tag = PodUnion::Tag::F_UINT16; - data->data.f_f_int16 = 20; - - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, true, nullptr); - EXPECT_TRUE(data->is_null()); - - PodUnionPtr pod2; - mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, nullptr); - EXPECT_TRUE(pod2.is_null()); -} - -TEST(UnionTest, SerializeIsNullNotInlined) { - PodUnionPtr pod; - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - EXPECT_EQ(16U, size); - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false, nullptr); - EXPECT_EQ(nullptr, data); -} - -TEST(UnionTest, NullValidation) { - void* buf = nullptr; - mojo::internal::ValidationContext validation_context(buf, 0, 0, 0); - EXPECT_TRUE(internal::PodUnion_Data::Validate( - buf, &validation_context, false)); -} - -TEST(UnionTest, OutOfAlignmentValidation) { - size_t size = sizeof(internal::PodUnion_Data); - // Get an aligned object and shift the alignment. - mojo::internal::FixedBufferForTesting aligned_buf(size + 1); - void* raw_buf = aligned_buf.Leak(); - char* buf = reinterpret_cast<char*>(raw_buf) + 1; - - internal::PodUnion_Data* data = - reinterpret_cast<internal::PodUnion_Data*>(buf); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE(internal::PodUnion_Data::Validate( - buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, OOBValidation) { - size_t size = sizeof(internal::PodUnion_Data) - 1; - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - void* raw_buf = buf.Leak(); - EXPECT_FALSE( - internal::PodUnion_Data::Validate(raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, UnknownTagValidation) { - size_t size = sizeof(internal::PodUnion_Data); - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf); - data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - void* raw_buf = buf.Leak(); - EXPECT_FALSE( - internal::PodUnion_Data::Validate(raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, UnknownEnumValueValidation) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_enum(static_cast<AnEnum>(0xFFFF)); - - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false, nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE( - internal::PodUnion_Data::Validate(raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, UnknownExtensibleEnumValueValidation) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_extensible_enum(static_cast<AnExtensibleEnum>(0xFFFF)); - - size_t size = - mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false, nullptr); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::PodUnion_Data* data = nullptr; - mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false, nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE( - internal::PodUnion_Data::Validate(raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, StringGetterSetter) { - ObjectUnionPtr pod(ObjectUnion::New()); - - std::string hello("hello world"); - pod->set_f_string(hello); - EXPECT_EQ(hello, pod->get_f_string()); - EXPECT_TRUE(pod->is_f_string()); - EXPECT_EQ(pod->which(), ObjectUnion::Tag::F_STRING); -} - -TEST(UnionTest, StringEquals) { - ObjectUnionPtr pod1(ObjectUnion::New()); - ObjectUnionPtr pod2(ObjectUnion::New()); - - pod1->set_f_string("hello world"); - pod2->set_f_string("hello world"); - EXPECT_TRUE(pod1.Equals(pod2)); - - pod2->set_f_string("hello universe"); - EXPECT_FALSE(pod1.Equals(pod2)); -} - -TEST(UnionTest, StringClone) { - ObjectUnionPtr pod(ObjectUnion::New()); - - std::string hello("hello world"); - pod->set_f_string(hello); - ObjectUnionPtr pod_clone = pod.Clone(); - EXPECT_EQ(hello, pod_clone->get_f_string()); - EXPECT_TRUE(pod_clone->is_f_string()); - EXPECT_EQ(pod_clone->which(), ObjectUnion::Tag::F_STRING); -} - -TEST(UnionTest, StringSerialization) { - ObjectUnionPtr pod1(ObjectUnion::New()); - - std::string hello("hello world"); - pod1->set_f_string(hello); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - pod1, false, nullptr); - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(pod1, &buf, &data, false, - nullptr); - - ObjectUnionPtr pod2; - mojo::internal::Deserialize<ObjectUnionDataView>(data, &pod2, nullptr); - EXPECT_EQ(hello, pod2->get_f_string()); - EXPECT_TRUE(pod2->is_f_string()); - EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING); -} - -TEST(UnionTest, NullStringValidation) { - size_t size = sizeof(internal::ObjectUnion_Data); - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf); - data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING; - data->data.unknown = 0x0; - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - void* raw_buf = buf.Leak(); - EXPECT_FALSE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, StringPointerOverflowValidation) { - size_t size = sizeof(internal::ObjectUnion_Data); - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf); - data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING; - data->data.unknown = 0xFFFFFFFFFFFFFFFF; - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - void* raw_buf = buf.Leak(); - EXPECT_FALSE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, StringValidateOOB) { - size_t size = 32; - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf); - data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING; - - data->data.f_f_string.offset = 8; - char* ptr = reinterpret_cast<char*>(&data->data.f_f_string); - mojo::internal::ArrayHeader* array_header = - reinterpret_cast<mojo::internal::ArrayHeader*>(ptr + *ptr); - array_header->num_bytes = 20; // This should go out of bounds. - array_header->num_elements = 20; - mojo::internal::ValidationContext validation_context(data, 32, 0, 0); - void* raw_buf = buf.Leak(); - EXPECT_FALSE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -// TODO(azani): Move back in array_unittest.cc when possible. -// Array tests -TEST(UnionTest, PodUnionInArray) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union_array.emplace(2); - small_struct->pod_union_array.value()[0] = PodUnion::New(); - small_struct->pod_union_array.value()[1] = PodUnion::New(); - - small_struct->pod_union_array.value()[0]->set_f_int8(10); - small_struct->pod_union_array.value()[1]->set_f_int16(12); - - EXPECT_EQ(10, small_struct->pod_union_array.value()[0]->get_f_int8()); - EXPECT_EQ(12, small_struct->pod_union_array.value()[1]->get_f_int16()); -} - -TEST(UnionTest, PodUnionInArraySerialization) { - std::vector<PodUnionPtr> array(2); - array[0] = PodUnion::New(); - array[1] = PodUnion::New(); - - array[0]->set_f_int8(10); - array[1]->set_f_int16(12); - EXPECT_EQ(2U, array.size()); - - size_t size = - mojo::internal::PrepareToSerialize<ArrayDataView<PodUnionDataView>>( - array, nullptr); - EXPECT_EQ(40U, size); - - mojo::internal::FixedBufferForTesting buf(size); - mojo::internal::Array_Data<internal::PodUnion_Data>* data; - mojo::internal::ContainerValidateParams validate_params(0, false, nullptr); - mojo::internal::Serialize<ArrayDataView<PodUnionDataView>>( - array, &buf, &data, &validate_params, nullptr); - - std::vector<PodUnionPtr> array2; - mojo::internal::Deserialize<ArrayDataView<PodUnionDataView>>(data, &array2, - nullptr); - - EXPECT_EQ(2U, array2.size()); - - EXPECT_EQ(10, array2[0]->get_f_int8()); - EXPECT_EQ(12, array2[1]->get_f_int16()); -} - -TEST(UnionTest, PodUnionInArraySerializationWithNull) { - std::vector<PodUnionPtr> array(2); - array[0] = PodUnion::New(); - - array[0]->set_f_int8(10); - EXPECT_EQ(2U, array.size()); - - size_t size = - mojo::internal::PrepareToSerialize<ArrayDataView<PodUnionDataView>>( - array, nullptr); - EXPECT_EQ(40U, size); - - mojo::internal::FixedBufferForTesting buf(size); - mojo::internal::Array_Data<internal::PodUnion_Data>* data; - mojo::internal::ContainerValidateParams validate_params(0, true, nullptr); - mojo::internal::Serialize<ArrayDataView<PodUnionDataView>>( - array, &buf, &data, &validate_params, nullptr); - - std::vector<PodUnionPtr> array2; - mojo::internal::Deserialize<ArrayDataView<PodUnionDataView>>(data, &array2, - nullptr); - - EXPECT_EQ(2U, array2.size()); - - EXPECT_EQ(10, array2[0]->get_f_int8()); - EXPECT_TRUE(array2[1].is_null()); -} - -TEST(UnionTest, ObjectUnionInArraySerialization) { - std::vector<ObjectUnionPtr> array(2); - array[0] = ObjectUnion::New(); - array[1] = ObjectUnion::New(); - - array[0]->set_f_string("hello"); - array[1]->set_f_string("world"); - EXPECT_EQ(2U, array.size()); - - size_t size = - mojo::internal::PrepareToSerialize<ArrayDataView<ObjectUnionDataView>>( - array, nullptr); - EXPECT_EQ(72U, size); - - mojo::internal::FixedBufferForTesting buf(size); - - mojo::internal::Array_Data<internal::ObjectUnion_Data>* data; - mojo::internal::ContainerValidateParams validate_params(0, false, nullptr); - mojo::internal::Serialize<ArrayDataView<ObjectUnionDataView>>( - array, &buf, &data, &validate_params, nullptr); - - std::vector<char> new_buf; - new_buf.resize(size); - - void* raw_buf = buf.Leak(); - memcpy(new_buf.data(), raw_buf, size); - free(raw_buf); - - data = - reinterpret_cast<mojo::internal::Array_Data<internal::ObjectUnion_Data>*>( - new_buf.data()); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - ASSERT_TRUE(mojo::internal::Array_Data<internal::ObjectUnion_Data>::Validate( - data, &validation_context, &validate_params)); - - std::vector<ObjectUnionPtr> array2; - mojo::internal::Deserialize<ArrayDataView<ObjectUnionDataView>>(data, &array2, - nullptr); - - EXPECT_EQ(2U, array2.size()); - - EXPECT_EQ("hello", array2[0]->get_f_string()); - EXPECT_EQ("world", array2[1]->get_f_string()); -} - -// TODO(azani): Move back in struct_unittest.cc when possible. -// Struct tests -TEST(UnionTest, Clone_Union) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union = PodUnion::New(); - small_struct->pod_union->set_f_int8(10); - - SmallStructPtr clone = small_struct.Clone(); - EXPECT_EQ(10, clone->pod_union->get_f_int8()); -} - -// Serialization test of a struct with a union of plain old data. -TEST(UnionTest, Serialization_UnionOfPods) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union = PodUnion::New(); - small_struct->pod_union->set_f_int32(10); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>( - small_struct, &context); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallStruct_Data* data = nullptr; - mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data, - &context); - - SmallStructPtr deserialized; - mojo::internal::Deserialize<SmallStructDataView>(data, &deserialized, - &context); - - EXPECT_EQ(10, deserialized->pod_union->get_f_int32()); -} - -// Serialization test of a struct with a union of structs. -TEST(UnionTest, Serialization_UnionOfObjects) { - SmallObjStructPtr obj_struct(SmallObjStruct::New()); - obj_struct->obj_union = ObjectUnion::New(); - std::string hello("hello world"); - obj_struct->obj_union->set_f_string(hello); - - size_t size = mojo::internal::PrepareToSerialize<SmallObjStructDataView>( - obj_struct, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallObjStruct_Data* data = nullptr; - mojo::internal::Serialize<SmallObjStructDataView>(obj_struct, &buf, &data, - nullptr); - - SmallObjStructPtr deserialized; - mojo::internal::Deserialize<SmallObjStructDataView>(data, &deserialized, - nullptr); - - EXPECT_EQ(hello, deserialized->obj_union->get_f_string()); -} - -// Validation test of a struct with a union. -TEST(UnionTest, Validation_UnionsInStruct) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union = PodUnion::New(); - small_struct->pod_union->set_f_int32(10); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>( - small_struct, &context); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallStruct_Data* data = nullptr; - mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data, - &context); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE(internal::SmallStruct_Data::Validate( - raw_buf, &validation_context)); - free(raw_buf); -} - -// Validation test of a struct union fails due to unknown union tag. -TEST(UnionTest, Validation_PodUnionInStruct_Failure) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union = PodUnion::New(); - small_struct->pod_union->set_f_int32(10); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>( - small_struct, &context); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallStruct_Data* data = nullptr; - mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data, - &context); - data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE(internal::SmallStruct_Data::Validate( - raw_buf, &validation_context)); - free(raw_buf); -} - -// Validation fails due to non-nullable null union in struct. -TEST(UnionTest, Validation_NullUnion_Failure) { - SmallStructNonNullableUnionPtr small_struct( - SmallStructNonNullableUnion::New()); - - size_t size = - mojo::internal::PrepareToSerialize<SmallStructNonNullableUnionDataView>( - small_struct, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallStructNonNullableUnion_Data* data = - internal::SmallStructNonNullableUnion_Data::New(&buf); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate( - raw_buf, &validation_context)); - free(raw_buf); -} - -// Validation passes with nullable null union. -TEST(UnionTest, Validation_NullableUnion) { - SmallStructPtr small_struct(SmallStruct::New()); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>( - small_struct, &context); - - mojo::internal::FixedBufferForTesting buf(size); - internal::SmallStruct_Data* data = nullptr; - mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data, - &context); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE(internal::SmallStruct_Data::Validate( - raw_buf, &validation_context)); - free(raw_buf); -} - -// TODO(azani): Move back in map_unittest.cc when possible. -// Map Tests -TEST(UnionTest, PodUnionInMap) { - SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union_map.emplace(); - small_struct->pod_union_map.value()["one"] = PodUnion::New(); - small_struct->pod_union_map.value()["two"] = PodUnion::New(); - - small_struct->pod_union_map.value()["one"]->set_f_int8(8); - small_struct->pod_union_map.value()["two"]->set_f_int16(16); - - EXPECT_EQ(8, small_struct->pod_union_map.value()["one"]->get_f_int8()); - EXPECT_EQ(16, small_struct->pod_union_map.value()["two"]->get_f_int16()); -} - -TEST(UnionTest, PodUnionInMapSerialization) { - using MojomType = MapDataView<StringDataView, PodUnionDataView>; - - std::unordered_map<std::string, PodUnionPtr> map; - map.insert(std::make_pair("one", PodUnion::New())); - map.insert(std::make_pair("two", PodUnion::New())); - - map["one"]->set_f_int8(8); - map["two"]->set_f_int16(16); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<MojomType>(map, &context); - EXPECT_EQ(120U, size); - - mojo::internal::FixedBufferForTesting buf(size); - - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::ContainerValidateParams validate_params( - new mojo::internal::ContainerValidateParams(0, false, nullptr), - new mojo::internal::ContainerValidateParams(0, false, nullptr)); - mojo::internal::Serialize<MojomType>(map, &buf, &data, &validate_params, - &context); - - std::unordered_map<std::string, PodUnionPtr> map2; - mojo::internal::Deserialize<MojomType>(data, &map2, &context); - - EXPECT_EQ(8, map2["one"]->get_f_int8()); - EXPECT_EQ(16, map2["two"]->get_f_int16()); -} - -TEST(UnionTest, PodUnionInMapSerializationWithNull) { - using MojomType = MapDataView<StringDataView, PodUnionDataView>; - - std::unordered_map<std::string, PodUnionPtr> map; - map.insert(std::make_pair("one", PodUnion::New())); - map.insert(std::make_pair("two", nullptr)); - - map["one"]->set_f_int8(8); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<MojomType>(map, &context); - EXPECT_EQ(120U, size); - - mojo::internal::FixedBufferForTesting buf(size); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::ContainerValidateParams validate_params( - new mojo::internal::ContainerValidateParams(0, false, nullptr), - new mojo::internal::ContainerValidateParams(0, true, nullptr)); - mojo::internal::Serialize<MojomType>(map, &buf, &data, &validate_params, - &context); - - std::unordered_map<std::string, PodUnionPtr> map2; - mojo::internal::Deserialize<MojomType>(data, &map2, &context); - - EXPECT_EQ(8, map2["one"]->get_f_int8()); - EXPECT_TRUE(map2["two"].is_null()); -} - -TEST(UnionTest, StructInUnionGetterSetterPasser) { - DummyStructPtr dummy(DummyStruct::New()); - dummy->f_int8 = 8; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_dummy(std::move(dummy)); - - EXPECT_EQ(8, obj->get_f_dummy()->f_int8); -} - -TEST(UnionTest, StructInUnionSerialization) { - DummyStructPtr dummy(DummyStruct::New()); - dummy->f_int8 = 8; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_dummy(std::move(dummy)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - EXPECT_EQ(32U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - ObjectUnionPtr obj2; - mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr); - EXPECT_EQ(8, obj2->get_f_dummy()->f_int8); -} - -TEST(UnionTest, StructInUnionValidation) { - DummyStructPtr dummy(DummyStruct::New()); - dummy->f_int8 = 8; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_dummy(std::move(dummy)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, StructInUnionValidationNonNullable) { - mojo::internal::SerializationWarningObserverForTesting suppress_warning; - - DummyStructPtr dummy(nullptr); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_dummy(std::move(dummy)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, StructInUnionValidationNullable) { - DummyStructPtr dummy(nullptr); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_nullable(std::move(dummy)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, ArrayInUnionGetterSetter) { - std::vector<int8_t> array(2); - array[0] = 8; - array[1] = 9; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_array_int8(std::move(array)); - - EXPECT_EQ(8, obj->get_f_array_int8()[0]); - EXPECT_EQ(9, obj->get_f_array_int8()[1]); -} - -TEST(UnionTest, ArrayInUnionSerialization) { - std::vector<int8_t> array(2); - array[0] = 8; - array[1] = 9; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_array_int8(std::move(array)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - EXPECT_EQ(32U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - ObjectUnionPtr obj2; - mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr); - - EXPECT_EQ(8, obj2->get_f_array_int8()[0]); - EXPECT_EQ(9, obj2->get_f_array_int8()[1]); -} - -TEST(UnionTest, ArrayInUnionValidation) { - std::vector<int8_t> array(2); - array[0] = 8; - array[1] = 9; - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_array_int8(std::move(array)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - - EXPECT_TRUE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, MapInUnionGetterSetter) { - std::unordered_map<std::string, int8_t> map; - map.insert({"one", 1}); - map.insert({"two", 2}); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_map_int8(std::move(map)); - - EXPECT_EQ(1, obj->get_f_map_int8()["one"]); - EXPECT_EQ(2, obj->get_f_map_int8()["two"]); -} - -TEST(UnionTest, MapInUnionSerialization) { - std::unordered_map<std::string, int8_t> map; - map.insert({"one", 1}); - map.insert({"two", 2}); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_map_int8(std::move(map)); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, &context); - EXPECT_EQ(112U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - &context); - - ObjectUnionPtr obj2; - mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, &context); - - EXPECT_EQ(1, obj2->get_f_map_int8()["one"]); - EXPECT_EQ(2, obj2->get_f_map_int8()["two"]); -} - -TEST(UnionTest, MapInUnionValidation) { - std::unordered_map<std::string, int8_t> map; - map.insert({"one", 1}); - map.insert({"two", 2}); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_map_int8(std::move(map)); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, &context); - EXPECT_EQ(112U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - &context); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - - EXPECT_TRUE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, UnionInUnionGetterSetter) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(10); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_pod_union(std::move(pod)); - - EXPECT_EQ(10, obj->get_f_pod_union()->get_f_int8()); -} - -TEST(UnionTest, UnionInUnionSerialization) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(10); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_pod_union(std::move(pod)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - EXPECT_EQ(32U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - ObjectUnionPtr obj2; - mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr); - EXPECT_EQ(10, obj2->get_f_pod_union()->get_f_int8()); -} - -TEST(UnionTest, UnionInUnionValidation) { - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int8(10); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_pod_union(std::move(pod)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - EXPECT_EQ(32U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_TRUE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, UnionInUnionValidationNonNullable) { - mojo::internal::SerializationWarningObserverForTesting suppress_warning; - - PodUnionPtr pod(nullptr); - - ObjectUnionPtr obj(ObjectUnion::New()); - obj->set_f_pod_union(std::move(pod)); - - size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>( - obj, false, nullptr); - - mojo::internal::FixedBufferForTesting buf(size); - internal::ObjectUnion_Data* data = nullptr; - mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false, - nullptr); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 0, 0); - EXPECT_FALSE(internal::ObjectUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, HandleInUnionGetterSetter) { - ScopedMessagePipeHandle pipe0; - ScopedMessagePipeHandle pipe1; - - CreateMessagePipe(nullptr, &pipe0, &pipe1); - - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_message_pipe(std::move(pipe1)); - - std::string golden("hello world"); - WriteTextMessage(pipe0.get(), golden); - - std::string actual; - ReadTextMessage(handle->get_f_message_pipe().get(), &actual); - - EXPECT_EQ(golden, actual); -} - -TEST(UnionTest, HandleInUnionSerialization) { - ScopedMessagePipeHandle pipe0; - ScopedMessagePipeHandle pipe1; - - CreateMessagePipe(nullptr, &pipe0, &pipe1); - - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_message_pipe(std::move(pipe1)); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>( - handle, false, &context); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::HandleUnion_Data* data = nullptr; - mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false, - &context); - EXPECT_EQ(1U, context.handles.size()); - - HandleUnionPtr handle2(HandleUnion::New()); - mojo::internal::Deserialize<HandleUnionDataView>(data, &handle2, &context); - - std::string golden("hello world"); - WriteTextMessage(pipe0.get(), golden); - - std::string actual; - ReadTextMessage(handle2->get_f_message_pipe().get(), &actual); - - EXPECT_EQ(golden, actual); -} - -TEST(UnionTest, HandleInUnionValidation) { - ScopedMessagePipeHandle pipe0; - ScopedMessagePipeHandle pipe1; - - CreateMessagePipe(nullptr, &pipe0, &pipe1); - - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_message_pipe(std::move(pipe1)); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>( - handle, false, &context); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::HandleUnion_Data* data = nullptr; - mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false, - &context); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 1, 0); - EXPECT_TRUE(internal::HandleUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -TEST(UnionTest, HandleInUnionValidationNull) { - mojo::internal::SerializationWarningObserverForTesting suppress_warning; - - ScopedMessagePipeHandle pipe; - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_message_pipe(std::move(pipe)); - - mojo::internal::SerializationContext context; - size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>( - handle, false, &context); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::HandleUnion_Data* data = nullptr; - mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false, - &context); - - void* raw_buf = buf.Leak(); - mojo::internal::ValidationContext validation_context( - data, static_cast<uint32_t>(size), 1, 0); - EXPECT_FALSE(internal::HandleUnion_Data::Validate( - raw_buf, &validation_context, false)); - free(raw_buf); -} - -class SmallCacheImpl : public SmallCache { - public: - explicit SmallCacheImpl(const base::Closure& closure) - : int_value_(0), closure_(closure) {} - ~SmallCacheImpl() override {} - int64_t int_value() const { return int_value_; } - - private: - void SetIntValue(int64_t int_value) override { - int_value_ = int_value; - closure_.Run(); - } - void GetIntValue(const GetIntValueCallback& callback) override { - callback.Run(int_value_); - } - - int64_t int_value_; - base::Closure closure_; -}; - -TEST(UnionTest, InterfaceInUnion) { - base::MessageLoop message_loop; - base::RunLoop run_loop; - SmallCacheImpl impl(run_loop.QuitClosure()); - SmallCachePtr ptr; - Binding<SmallCache> bindings(&impl, MakeRequest(&ptr)); - - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_small_cache(std::move(ptr)); - - handle->get_f_small_cache()->SetIntValue(10); - run_loop.Run(); - EXPECT_EQ(10, impl.int_value()); -} - -TEST(UnionTest, InterfaceInUnionSerialization) { - base::MessageLoop message_loop; - base::RunLoop run_loop; - SmallCacheImpl impl(run_loop.QuitClosure()); - SmallCachePtr ptr; - Binding<SmallCache> bindings(&impl, MakeRequest(&ptr)); - - mojo::internal::SerializationContext context; - HandleUnionPtr handle(HandleUnion::New()); - handle->set_f_small_cache(std::move(ptr)); - size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>( - handle, false, &context); - EXPECT_EQ(16U, size); - - mojo::internal::FixedBufferForTesting buf(size); - internal::HandleUnion_Data* data = nullptr; - mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false, - &context); - EXPECT_EQ(1U, context.handles.size()); - - HandleUnionPtr handle2(HandleUnion::New()); - mojo::internal::Deserialize<HandleUnionDataView>(data, &handle2, &context); - - handle2->get_f_small_cache()->SetIntValue(10); - run_loop.Run(); - EXPECT_EQ(10, impl.int_value()); -} - -class UnionInterfaceImpl : public UnionInterface { - public: - UnionInterfaceImpl() {} - ~UnionInterfaceImpl() override {} - - private: - void Echo(PodUnionPtr in, const EchoCallback& callback) override { - callback.Run(std::move(in)); - } -}; - -void ExpectInt16(int16_t value, PodUnionPtr out) { - EXPECT_EQ(value, out->get_f_int16()); -} - -TEST(UnionTest, UnionInInterface) { - base::MessageLoop message_loop; - UnionInterfaceImpl impl; - UnionInterfacePtr ptr; - Binding<UnionInterface> bindings(&impl, MakeRequest(&ptr)); - - PodUnionPtr pod(PodUnion::New()); - pod->set_f_int16(16); - - ptr->Echo(std::move(pod), base::Bind(&ExpectInt16, 16)); - base::RunLoop().RunUntilIdle(); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/validation_context_unittest.cc b/mojo/public/cpp/bindings/tests/validation_context_unittest.cc deleted file mode 100644 index 9ce9d60..0000000 --- a/mojo/public/cpp/bindings/tests/validation_context_unittest.cc +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/system/core.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -using Handle_Data = mojo::internal::Handle_Data; -using AssociatedEndpointHandle_Data = - mojo::internal::AssociatedEndpointHandle_Data; - -const void* ToPtr(uintptr_t ptr) { - return reinterpret_cast<const void*>(ptr); -} - -#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) -TEST(ValidationContextTest, ConstructorRangeOverflow) { - { - // Test memory range overflow. - internal::ValidationContext context( - ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 5000, 0, 0); - - EXPECT_FALSE(context.IsValidRange( - ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1)); - EXPECT_FALSE(context.ClaimMemory( - ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1)); - } - - if (sizeof(size_t) <= sizeof(uint32_t)) - return; - - { - // Test handle index range overflow. - size_t num_handles = - static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 5; - internal::ValidationContext context(ToPtr(0), 0, num_handles, 0); - - EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); - EXPECT_FALSE(context.ClaimHandle( - Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); - - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(internal::kEncodedInvalidHandleValue))); - } - - { - size_t num_associated_endpoint_handles = - static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 5; - internal::ValidationContext context(ToPtr(0), 0, 0, - num_associated_endpoint_handles); - - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(0))); - EXPECT_FALSE( - context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( - std::numeric_limits<uint32_t>::max() - 1))); - - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); - } -} -#endif - -TEST(ValidationContextTest, IsValidRange) { - { - internal::ValidationContext context(ToPtr(1234), 100, 0, 0); - - // Basics. - EXPECT_FALSE(context.IsValidRange(ToPtr(100), 5)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1230), 50)); - EXPECT_TRUE(context.IsValidRange(ToPtr(1234), 5)); - EXPECT_TRUE(context.IsValidRange(ToPtr(1240), 50)); - EXPECT_TRUE(context.IsValidRange(ToPtr(1234), 100)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 101)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1240), 100)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1333), 5)); - EXPECT_FALSE(context.IsValidRange(ToPtr(2234), 5)); - - // ClaimMemory() updates the valid range. - EXPECT_TRUE(context.ClaimMemory(ToPtr(1254), 10)); - - EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 1)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1254), 10)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1263), 1)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1263), 10)); - EXPECT_TRUE(context.IsValidRange(ToPtr(1264), 10)); - EXPECT_TRUE(context.IsValidRange(ToPtr(1264), 70)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1264), 71)); - } - - { - internal::ValidationContext context(ToPtr(1234), 100, 0, 0); - // Should return false for empty ranges. - EXPECT_FALSE(context.IsValidRange(ToPtr(0), 0)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1200), 0)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 0)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1240), 0)); - EXPECT_FALSE(context.IsValidRange(ToPtr(2234), 0)); - } - - { - // The valid memory range is empty. - internal::ValidationContext context(ToPtr(1234), 0, 0, 0); - - EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 1)); - EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 0)); - } - - { - internal::ValidationContext context( - ToPtr(std::numeric_limits<uintptr_t>::max() - 2000), 1000, 0, 0); - - // Test overflow. - EXPECT_FALSE(context.IsValidRange( - ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 4000)); - EXPECT_FALSE(context.IsValidRange( - ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), - std::numeric_limits<uint32_t>::max())); - - // This should be fine. - EXPECT_TRUE(context.IsValidRange( - ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 200)); - } -} - -TEST(ValidationContextTest, ClaimHandle) { - { - internal::ValidationContext context(ToPtr(0), 0, 10, 0); - - // Basics. - EXPECT_TRUE(context.ClaimHandle(Handle_Data(0))); - EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); - - EXPECT_TRUE(context.ClaimHandle(Handle_Data(9))); - EXPECT_FALSE(context.ClaimHandle(Handle_Data(10))); - - // Should fail because it is smaller than the max index that has been - // claimed. - EXPECT_FALSE(context.ClaimHandle(Handle_Data(8))); - - // Should return true for invalid handle. - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(internal::kEncodedInvalidHandleValue))); - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(internal::kEncodedInvalidHandleValue))); - } - - { - // No handle to claim. - internal::ValidationContext context(ToPtr(0), 0, 0, 0); - - EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); - - // Should still return true for invalid handle. - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(internal::kEncodedInvalidHandleValue))); - } - - { - // Test the case that |num_handles| is the same value as - // |internal::kEncodedInvalidHandleValue|. - EXPECT_EQ(internal::kEncodedInvalidHandleValue, - std::numeric_limits<uint32_t>::max()); - internal::ValidationContext context( - ToPtr(0), 0, std::numeric_limits<uint32_t>::max(), 0); - - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); - EXPECT_FALSE(context.ClaimHandle( - Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); - EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); - - // Should still return true for invalid handle. - EXPECT_TRUE(context.ClaimHandle( - Handle_Data(internal::kEncodedInvalidHandleValue))); - } -} - -TEST(ValidationContextTest, ClaimAssociatedEndpointHandle) { - { - internal::ValidationContext context(ToPtr(0), 0, 0, 10); - - // Basics. - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(0))); - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(0))); - - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(9))); - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(10))); - - // Should fail because it is smaller than the max index that has been - // claimed. - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(8))); - - // Should return true for invalid handle. - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); - } - - { - // No handle to claim. - internal::ValidationContext context(ToPtr(0), 0, 0, 0); - - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(0))); - - // Should still return true for invalid handle. - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); - } - - { - // Test the case that |num_associated_endpoint_handles| is the same value as - // |internal::kEncodedInvalidHandleValue|. - EXPECT_EQ(internal::kEncodedInvalidHandleValue, - std::numeric_limits<uint32_t>::max()); - internal::ValidationContext context(ToPtr(0), 0, 0, - std::numeric_limits<uint32_t>::max()); - - EXPECT_TRUE( - context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( - std::numeric_limits<uint32_t>::max() - 1))); - EXPECT_FALSE( - context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( - std::numeric_limits<uint32_t>::max() - 1))); - EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(0))); - - // Should still return true for invalid handle. - EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( - AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); - } -} - -TEST(ValidationContextTest, ClaimMemory) { - { - internal::ValidationContext context(ToPtr(1000), 2000, 0, 0); - - // Basics. - EXPECT_FALSE(context.ClaimMemory(ToPtr(500), 100)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(800), 300)); - EXPECT_TRUE(context.ClaimMemory(ToPtr(1000), 100)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(1099), 100)); - EXPECT_TRUE(context.ClaimMemory(ToPtr(1100), 200)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(2000), 1001)); - EXPECT_TRUE(context.ClaimMemory(ToPtr(2000), 500)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(2000), 500)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(1400), 100)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(3000), 1)); - EXPECT_TRUE(context.ClaimMemory(ToPtr(2500), 500)); - } - - { - // No memory to claim. - internal::ValidationContext context(ToPtr(10000), 0, 0, 0); - - EXPECT_FALSE(context.ClaimMemory(ToPtr(10000), 1)); - EXPECT_FALSE(context.ClaimMemory(ToPtr(10000), 0)); - } - - { - internal::ValidationContext context( - ToPtr(std::numeric_limits<uintptr_t>::max() - 1000), 500, 0, 0); - - // Test overflow. - EXPECT_FALSE(context.ClaimMemory( - ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 4000)); - EXPECT_FALSE( - context.ClaimMemory(ToPtr(std::numeric_limits<uintptr_t>::max() - 750), - std::numeric_limits<uint32_t>::max())); - - // This should be fine. - EXPECT_TRUE(context.ClaimMemory( - ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 200)); - } -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc b/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc deleted file mode 100644 index f309737..0000000 --- a/mojo/public/cpp/bindings/tests/validation_test_input_parser.cc +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" - -#include <assert.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include <limits> -#include <map> -#include <set> -#include <utility> - -#include "mojo/public/c/system/macros.h" - -namespace mojo { -namespace test { -namespace { - -class ValidationTestInputParser { - public: - ValidationTestInputParser(const std::string& input, - std::vector<uint8_t>* data, - size_t* num_handles, - std::string* error_message); - ~ValidationTestInputParser(); - - bool Run(); - - private: - struct DataType; - - typedef std::pair<const char*, const char*> Range; - - typedef bool (ValidationTestInputParser::*ParseDataFunc)( - const DataType& type, - const std::string& value_string); - - struct DataType { - const char* name; - size_t name_size; - size_t data_size; - ParseDataFunc parse_data_func; - }; - - // A dist4/8 item that hasn't been matched with an anchr item. - struct PendingDistanceItem { - // Where this data item is located in |data_|. - size_t pos; - // Either 4 or 8 (bytes). - size_t data_size; - }; - - bool GetNextItem(Range* range); - - bool ParseItem(const Range& range); - - bool ParseUnsignedInteger(const DataType& type, - const std::string& value_string); - bool ParseSignedInteger(const DataType& type, - const std::string& value_string); - bool ParseFloat(const DataType& type, const std::string& value_string); - bool ParseDouble(const DataType& type, const std::string& value_string); - bool ParseBinarySequence(const DataType& type, - const std::string& value_string); - bool ParseDistance(const DataType& type, const std::string& value_string); - bool ParseAnchor(const DataType& type, const std::string& value_string); - bool ParseHandles(const DataType& type, const std::string& value_string); - - bool StartsWith(const Range& range, const char* prefix, size_t prefix_length); - - bool ConvertToUnsignedInteger(const std::string& value_string, - unsigned long long int* value); - - template <typename T> - void AppendData(T data) { - size_t pos = data_->size(); - data_->resize(pos + sizeof(T)); - memcpy(&(*data_)[pos], &data, sizeof(T)); - } - - template <typename TargetType, typename InputType> - bool ConvertAndAppendData(InputType value) { - if (value > std::numeric_limits<TargetType>::max() || - value < std::numeric_limits<TargetType>::min()) { - return false; - } - AppendData(static_cast<TargetType>(value)); - return true; - } - - template <typename TargetType, typename InputType> - bool ConvertAndFillData(size_t pos, InputType value) { - if (value > std::numeric_limits<TargetType>::max() || - value < std::numeric_limits<TargetType>::min()) { - return false; - } - TargetType target_value = static_cast<TargetType>(value); - assert(pos + sizeof(TargetType) <= data_->size()); - memcpy(&(*data_)[pos], &target_value, sizeof(TargetType)); - return true; - } - - static const DataType kDataTypes[]; - static const size_t kDataTypeCount; - - const std::string& input_; - size_t input_cursor_; - - std::vector<uint8_t>* data_; - size_t* num_handles_; - std::string* error_message_; - - std::map<std::string, PendingDistanceItem> pending_distance_items_; - std::set<std::string> anchors_; -}; - -#define DATA_TYPE(name, data_size, parse_data_func) \ - { name, sizeof(name) - 1, data_size, parse_data_func } - -const ValidationTestInputParser::DataType - ValidationTestInputParser::kDataTypes[] = { - DATA_TYPE("[u1]", 1, &ValidationTestInputParser::ParseUnsignedInteger), - DATA_TYPE("[u2]", 2, &ValidationTestInputParser::ParseUnsignedInteger), - DATA_TYPE("[u4]", 4, &ValidationTestInputParser::ParseUnsignedInteger), - DATA_TYPE("[u8]", 8, &ValidationTestInputParser::ParseUnsignedInteger), - DATA_TYPE("[s1]", 1, &ValidationTestInputParser::ParseSignedInteger), - DATA_TYPE("[s2]", 2, &ValidationTestInputParser::ParseSignedInteger), - DATA_TYPE("[s4]", 4, &ValidationTestInputParser::ParseSignedInteger), - DATA_TYPE("[s8]", 8, &ValidationTestInputParser::ParseSignedInteger), - DATA_TYPE("[b]", 1, &ValidationTestInputParser::ParseBinarySequence), - DATA_TYPE("[f]", 4, &ValidationTestInputParser::ParseFloat), - DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble), - DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance), - DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance), - DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor), - DATA_TYPE("[handles]", 0, &ValidationTestInputParser::ParseHandles)}; - -const size_t ValidationTestInputParser::kDataTypeCount = - sizeof(ValidationTestInputParser::kDataTypes) / - sizeof(ValidationTestInputParser::kDataTypes[0]); - -ValidationTestInputParser::ValidationTestInputParser(const std::string& input, - std::vector<uint8_t>* data, - size_t* num_handles, - std::string* error_message) - : input_(input), - input_cursor_(0), - data_(data), - num_handles_(num_handles), - error_message_(error_message) { - assert(data_); - assert(num_handles_); - assert(error_message_); - data_->clear(); - *num_handles_ = 0; - error_message_->clear(); -} - -ValidationTestInputParser::~ValidationTestInputParser() { -} - -bool ValidationTestInputParser::Run() { - Range range; - bool result = true; - while (result && GetNextItem(&range)) - result = ParseItem(range); - - if (!result) { - *error_message_ = - "Error occurred when parsing " + std::string(range.first, range.second); - } else if (!pending_distance_items_.empty()) { - // We have parsed all the contents in |input_| successfully, but there are - // unmatched dist4/8 items. - *error_message_ = "Error occurred when matching [dist4/8] and [anchr]."; - result = false; - } - if (!result) { - data_->clear(); - *num_handles_ = 0; - } else { - assert(error_message_->empty()); - } - - return result; -} - -bool ValidationTestInputParser::GetNextItem(Range* range) { - const char kWhitespaceChars[] = " \t\n\r"; - const char kItemDelimiters[] = " \t\n\r/"; - const char kEndOfLineChars[] = "\n\r"; - while (true) { - // Skip leading whitespaces. - // If there are no non-whitespace characters left, |input_cursor_| will be - // set to std::npos. - input_cursor_ = input_.find_first_not_of(kWhitespaceChars, input_cursor_); - - if (input_cursor_ >= input_.size()) - return false; - - if (StartsWith( - Range(&input_[0] + input_cursor_, &input_[0] + input_.size()), - "//", - 2)) { - // Skip contents until the end of the line. - input_cursor_ = input_.find_first_of(kEndOfLineChars, input_cursor_); - } else { - range->first = &input_[0] + input_cursor_; - input_cursor_ = input_.find_first_of(kItemDelimiters, input_cursor_); - range->second = input_cursor_ >= input_.size() - ? &input_[0] + input_.size() - : &input_[0] + input_cursor_; - return true; - } - } - return false; -} - -bool ValidationTestInputParser::ParseItem(const Range& range) { - for (size_t i = 0; i < kDataTypeCount; ++i) { - if (StartsWith(range, kDataTypes[i].name, kDataTypes[i].name_size)) { - return (this->*kDataTypes[i].parse_data_func)( - kDataTypes[i], - std::string(range.first + kDataTypes[i].name_size, range.second)); - } - } - - // "[u1]" is optional. - return ParseUnsignedInteger(kDataTypes[0], - std::string(range.first, range.second)); -} - -bool ValidationTestInputParser::ParseUnsignedInteger( - const DataType& type, - const std::string& value_string) { - unsigned long long int value; - if (!ConvertToUnsignedInteger(value_string, &value)) - return false; - - switch (type.data_size) { - case 1: - return ConvertAndAppendData<uint8_t>(value); - case 2: - return ConvertAndAppendData<uint16_t>(value); - case 4: - return ConvertAndAppendData<uint32_t>(value); - case 8: - return ConvertAndAppendData<uint64_t>(value); - default: - assert(false); - return false; - } -} - -bool ValidationTestInputParser::ParseSignedInteger( - const DataType& type, - const std::string& value_string) { - long long int value; - if (sscanf(value_string.c_str(), "%lli", &value) != 1) - return false; - - switch (type.data_size) { - case 1: - return ConvertAndAppendData<int8_t>(value); - case 2: - return ConvertAndAppendData<int16_t>(value); - case 4: - return ConvertAndAppendData<int32_t>(value); - case 8: - return ConvertAndAppendData<int64_t>(value); - default: - assert(false); - return false; - } -} - -bool ValidationTestInputParser::ParseFloat(const DataType& type, - const std::string& value_string) { - static_assert(sizeof(float) == 4, "sizeof(float) is not 4"); - - float value; - if (sscanf(value_string.c_str(), "%f", &value) != 1) - return false; - - AppendData(value); - return true; -} - -bool ValidationTestInputParser::ParseDouble(const DataType& type, - const std::string& value_string) { - static_assert(sizeof(double) == 8, "sizeof(double) is not 8"); - - double value; - if (sscanf(value_string.c_str(), "%lf", &value) != 1) - return false; - - AppendData(value); - return true; -} - -bool ValidationTestInputParser::ParseBinarySequence( - const DataType& type, - const std::string& value_string) { - if (value_string.size() != 8) - return false; - - uint8_t value = 0; - for (std::string::const_iterator iter = value_string.begin(); - iter != value_string.end(); - ++iter) { - value <<= 1; - if (*iter == '1') - value++; - else if (*iter != '0') - return false; - } - AppendData(value); - return true; -} - -bool ValidationTestInputParser::ParseDistance(const DataType& type, - const std::string& value_string) { - if (pending_distance_items_.find(value_string) != - pending_distance_items_.end()) - return false; - - PendingDistanceItem item = {data_->size(), type.data_size}; - data_->resize(data_->size() + type.data_size); - pending_distance_items_[value_string] = item; - - return true; -} - -bool ValidationTestInputParser::ParseAnchor(const DataType& type, - const std::string& value_string) { - if (anchors_.find(value_string) != anchors_.end()) - return false; - anchors_.insert(value_string); - - std::map<std::string, PendingDistanceItem>::iterator iter = - pending_distance_items_.find(value_string); - if (iter == pending_distance_items_.end()) - return false; - - PendingDistanceItem dist_item = iter->second; - pending_distance_items_.erase(iter); - - size_t distance = data_->size() - dist_item.pos; - switch (dist_item.data_size) { - case 4: - return ConvertAndFillData<uint32_t>(dist_item.pos, distance); - case 8: - return ConvertAndFillData<uint64_t>(dist_item.pos, distance); - default: - assert(false); - return false; - } -} - -bool ValidationTestInputParser::ParseHandles(const DataType& type, - const std::string& value_string) { - // It should be the first item. - if (!data_->empty()) - return false; - - unsigned long long int value; - if (!ConvertToUnsignedInteger(value_string, &value)) - return false; - - if (value > std::numeric_limits<size_t>::max()) - return false; - - *num_handles_ = static_cast<size_t>(value); - return true; -} - -bool ValidationTestInputParser::StartsWith(const Range& range, - const char* prefix, - size_t prefix_length) { - if (static_cast<size_t>(range.second - range.first) < prefix_length) - return false; - - return memcmp(range.first, prefix, prefix_length) == 0; -} - -bool ValidationTestInputParser::ConvertToUnsignedInteger( - const std::string& value_string, - unsigned long long int* value) { - const char* format = nullptr; - if (value_string.find_first_of("xX") != std::string::npos) - format = "%llx"; - else - format = "%llu"; - return sscanf(value_string.c_str(), format, value) == 1; -} - -} // namespace - -bool ParseValidationTestInput(const std::string& input, - std::vector<uint8_t>* data, - size_t* num_handles, - std::string* error_message) { - ValidationTestInputParser parser(input, data, num_handles, error_message); - return parser.Run(); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/validation_test_input_parser.h b/mojo/public/cpp/bindings/tests/validation_test_input_parser.h deleted file mode 100644 index d08f359..0000000 --- a/mojo/public/cpp/bindings/tests/validation_test_input_parser.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TESTS_VALIDATION_TEST_INPUT_PARSER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_VALIDATION_TEST_INPUT_PARSER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <string> -#include <vector> - -namespace mojo { -namespace test { - -// Input Format of Mojo Message Validation Tests. -// -// Data items are separated by whitespaces: -// - ' ' (0x20) space; -// - '\t' (0x09) horizontal tab; -// - '\n' (0x0a) newline; -// - '\r' (0x0d) carriage return. -// A comment starts with //, extending to the end of the line. -// Each data item is of the format [<type>]<value>. The types defined and the -// corresponding value formats are described below. -// -// Type: u1 / u2 / u4 / u8 -// Description: Little-endian 1/2/4/8-byte unsigned integer. -// Value Format: -// - Decimal integer: 0|[1-9][0-9]* -// - Hexadecimal integer: 0[xX][0-9a-fA-F]+ -// - The type prefix (including the square brackets) of 1-byte unsigned -// integer is optional. -// -// Type: s1 / s2 / s4 / s8 -// Description: Little-endian 1/2/4/8-byte signed integer. -// Value Format: -// - Decimal integer: [-+]?(0|[1-9][0-9]*) -// - Hexadecimal integer: [-+]?0[xX][0-9a-fA-F]+ -// -// Type: b -// Description: Binary sequence of 1 byte. -// Value Format: [01]{8} -// -// Type: f / d -// Description: Little-endian IEEE-754 format of float (4 bytes) and double (8 -// bytes). -// Value Format: [-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? -// -// Type: dist4 / dist8 -// Description: Little-endian 4/8-byte unsigned integer. The actual value is set -// to the byte distance from the location of this integer to the location of the -// anchr item with the same ID. A dist8 and anchr pair can be used to easily -// represent an encoded pointer. A dist4 and anchr pair can be used to easily -// calculate struct/array size. -// Value Format: The value is an ID: [0-9a-zA-Z_]+ -// -// Type: anchr -// Description: Mark an anchor location. It doesn’t translate into any actual -// data. -// Value Format: The value is an ID of the same format as that of dist4/8. -// -// Type: handles -// Description: The number of handles that are associated with the message. This -// special item is not part of the message data. If specified, it should be the -// first item. -// Value Format: The same format as u1/2/4/8. -// -// EXAMPLE: -// -// Suppose you have the following Mojo types defined: -// struct Bar { -// int32_t a; -// bool b; -// bool c; -// }; -// struct Foo { -// Bar x; -// uint32_t y; -// }; -// -// The following describes a valid message whose payload is a Foo struct: -// // message header -// [dist4]message_header // num_bytes -// [u4]3 // version -// [u4]0 // type -// [u4]1 // flags -// [u8]1234 // request_id -// [anchr]message_header -// -// // payload -// [dist4]foo // num_bytes -// [u4]2 // version -// [dist8]bar_ptr // x -// [u4]0xABCD // y -// [u4]0 // padding -// [anchr]foo -// -// [anchr]bar_ptr -// [dist4]bar // num_bytes -// [u4]3 // version -// [s4]-1 // a -// [b]00000010 // b and c -// 0 0 0 // padding -// [anchr]bar - -// Parses validation test input. -// On success, |data| and |num_handles| store the parsing result, -// |error_message| is cleared; on failure, |error_message| is set to a message -// describing the error, |data| is cleared and |num_handles| set to 0. -// Note: For now, this method only works on little-endian platforms. -bool ParseValidationTestInput(const std::string& input, - std::vector<uint8_t>* data, - size_t* num_handles, - std::string* error_message); - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_VALIDATION_TEST_INPUT_PARSER_H_ diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc deleted file mode 100644 index 7af7396..0000000 --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <algorithm> -#include <string> -#include <utility> -#include <vector> - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/connector.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/test_support/test_support.h" -#include "mojo/public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom.h" -#include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -template <typename T> -void Append(std::vector<uint8_t>* data_vector, T data) { - size_t pos = data_vector->size(); - data_vector->resize(pos + sizeof(T)); - memcpy(&(*data_vector)[pos], &data, sizeof(T)); -} - -bool TestInputParser(const std::string& input, - bool expected_result, - const std::vector<uint8_t>& expected_data, - size_t expected_num_handles) { - std::vector<uint8_t> data; - size_t num_handles; - std::string error_message; - - bool result = - ParseValidationTestInput(input, &data, &num_handles, &error_message); - if (expected_result) { - if (result && error_message.empty() && expected_data == data && - expected_num_handles == num_handles) { - return true; - } - - // Compare with an empty string instead of checking |error_message.empty()|, - // so that the message will be printed out if the two are not equal. - EXPECT_EQ(std::string(), error_message); - EXPECT_EQ(expected_data, data); - EXPECT_EQ(expected_num_handles, num_handles); - return false; - } - - EXPECT_FALSE(error_message.empty()); - return !result && !error_message.empty(); -} - -std::vector<std::string> GetMatchingTests(const std::vector<std::string>& names, - const std::string& prefix) { - const std::string suffix = ".data"; - std::vector<std::string> tests; - for (size_t i = 0; i < names.size(); ++i) { - if (names[i].size() >= suffix.size() && - names[i].substr(0, prefix.size()) == prefix && - names[i].substr(names[i].size() - suffix.size()) == suffix) - tests.push_back(names[i].substr(0, names[i].size() - suffix.size())); - } - return tests; -} - -bool ReadFile(const std::string& path, std::string* result) { - FILE* fp = OpenSourceRootRelativeFile(path.c_str()); - if (!fp) { - ADD_FAILURE() << "File not found: " << path; - return false; - } - fseek(fp, 0, SEEK_END); - size_t size = static_cast<size_t>(ftell(fp)); - if (size == 0) { - result->clear(); - fclose(fp); - return true; - } - fseek(fp, 0, SEEK_SET); - result->resize(size); - size_t size_read = fread(&result->at(0), 1, size, fp); - fclose(fp); - return size == size_read; -} - -bool ReadAndParseDataFile(const std::string& path, - std::vector<uint8_t>* data, - size_t* num_handles) { - std::string input; - if (!ReadFile(path, &input)) - return false; - - std::string error_message; - if (!ParseValidationTestInput(input, data, num_handles, &error_message)) { - ADD_FAILURE() << error_message; - return false; - } - - return true; -} - -bool ReadResultFile(const std::string& path, std::string* result) { - if (!ReadFile(path, result)) - return false; - - // Result files are new-line delimited text files. Remove any CRs. - result->erase(std::remove(result->begin(), result->end(), '\r'), - result->end()); - - // Remove trailing LFs. - size_t pos = result->find_last_not_of('\n'); - if (pos == std::string::npos) - result->clear(); - else - result->resize(pos + 1); - - return true; -} - -std::string GetPath(const std::string& root, const std::string& suffix) { - return "mojo/public/interfaces/bindings/tests/data/validation/" + root + - suffix; -} - -// |message| should be a newly created object. -bool ReadTestCase(const std::string& test, - Message* message, - std::string* expected) { - std::vector<uint8_t> data; - size_t num_handles; - if (!ReadAndParseDataFile(GetPath(test, ".data"), &data, &num_handles) || - !ReadResultFile(GetPath(test, ".expected"), expected)) { - return false; - } - - message->Initialize(static_cast<uint32_t>(data.size()), - false /* zero_initialized */); - if (!data.empty()) - memcpy(message->mutable_data(), &data[0], data.size()); - message->mutable_handles()->resize(num_handles); - - return true; -} - -void RunValidationTests(const std::string& prefix, - MessageReceiver* test_message_receiver) { - std::vector<std::string> names = - EnumerateSourceRootRelativeDirectory(GetPath("", "")); - std::vector<std::string> tests = GetMatchingTests(names, prefix); - ASSERT_FALSE(tests.empty()); - - for (size_t i = 0; i < tests.size(); ++i) { - Message message; - std::string expected; - ASSERT_TRUE(ReadTestCase(tests[i], &message, &expected)); - - std::string result; - base::RunLoop run_loop; - mojo::internal::ValidationErrorObserverForTesting observer( - run_loop.QuitClosure()); - ignore_result(test_message_receiver->Accept(&message)); - if (expected != "PASS") // Observer only gets called on errors. - run_loop.Run(); - if (observer.last_error() == mojo::internal::VALIDATION_ERROR_NONE) - result = "PASS"; - else - result = mojo::internal::ValidationErrorToString(observer.last_error()); - - EXPECT_EQ(expected, result) << "failed test: " << tests[i]; - } -} - -class DummyMessageReceiver : public MessageReceiver { - public: - bool Accept(Message* message) override { - return true; // Any message is OK. - } -}; - -class ValidationTest : public testing::Test { - public: - ValidationTest() {} - - protected: - base::MessageLoop loop_; -}; - -class ValidationIntegrationTest : public ValidationTest { - public: - ValidationIntegrationTest() : test_message_receiver_(nullptr) {} - - ~ValidationIntegrationTest() override {} - - void SetUp() override { - ScopedMessagePipeHandle tester_endpoint; - ASSERT_EQ(MOJO_RESULT_OK, - CreateMessagePipe(nullptr, &tester_endpoint, &testee_endpoint_)); - test_message_receiver_ = - new TestMessageReceiver(this, std::move(tester_endpoint)); - } - - void TearDown() override { - delete test_message_receiver_; - test_message_receiver_ = nullptr; - - // Make sure that the other end receives the OnConnectionError() - // notification. - PumpMessages(); - } - - MessageReceiver* test_message_receiver() { return test_message_receiver_; } - - ScopedMessagePipeHandle testee_endpoint() { - return std::move(testee_endpoint_); - } - - private: - class TestMessageReceiver : public MessageReceiver { - public: - TestMessageReceiver(ValidationIntegrationTest* owner, - ScopedMessagePipeHandle handle) - : owner_(owner), - connector_(std::move(handle), - mojo::Connector::SINGLE_THREADED_SEND, - base::ThreadTaskRunnerHandle::Get()) { - connector_.set_enforce_errors_from_incoming_receiver(false); - } - ~TestMessageReceiver() override {} - - bool Accept(Message* message) override { - return connector_.Accept(message); - } - - public: - ValidationIntegrationTest* owner_; - mojo::Connector connector_; - }; - - void PumpMessages() { base::RunLoop().RunUntilIdle(); } - - TestMessageReceiver* test_message_receiver_; - ScopedMessagePipeHandle testee_endpoint_; -}; - -class IntegrationTestInterfaceImpl : public IntegrationTestInterface { - public: - ~IntegrationTestInterfaceImpl() override {} - - void Method0(BasicStructPtr param0, - const Method0Callback& callback) override { - callback.Run(std::vector<uint8_t>()); - } -}; - -TEST_F(ValidationTest, InputParser) { - { - // The parser, as well as Append() defined above, assumes that this code is - // running on a little-endian platform. Test whether that is true. - uint16_t x = 1; - ASSERT_EQ(1, *(reinterpret_cast<char*>(&x))); - } - { - // Test empty input. - std::string input; - std::vector<uint8_t> expected; - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - // Test input that only consists of comments and whitespaces. - std::string input = " \t // hello world \n\r \t// the answer is 42 "; - std::vector<uint8_t> expected; - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = - "[u1]0x10// hello world !! \n\r \t [u2]65535 \n" - "[u4]65536 [u8]0xFFFFFFFFFFFFFFFF 0 0Xff"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint8_t>(0x10)); - Append(&expected, static_cast<uint16_t>(65535)); - Append(&expected, static_cast<uint32_t>(65536)); - Append(&expected, static_cast<uint64_t>(0xffffffffffffffff)); - Append(&expected, static_cast<uint8_t>(0)); - Append(&expected, static_cast<uint8_t>(0xff)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40"; - std::vector<uint8_t> expected; - Append(&expected, -static_cast<int64_t>(0x800)); - Append(&expected, static_cast<int8_t>(-128)); - Append(&expected, static_cast<int16_t>(0)); - Append(&expected, static_cast<int32_t>(-40)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[b]00001011 [b]10000000 // hello world\r [b]00000000"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint8_t>(11)); - Append(&expected, static_cast<uint8_t>(128)); - Append(&expected, static_cast<uint8_t>(0)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[f]+.3e9 [d]-10.03"; - std::vector<uint8_t> expected; - Append(&expected, +.3e9f); - Append(&expected, -10.03); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint32_t>(14)); - Append(&expected, static_cast<uint8_t>(0)); - Append(&expected, static_cast<uint64_t>(9)); - Append(&expected, static_cast<uint8_t>(0)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "// This message has handles! \n[handles]50 [u8]2"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint64_t>(2)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 50)); - } - - // Test some failure cases. - { - const char* error_inputs[] = {"/ hello world", - "[u1]x", - "[u2]-1000", - "[u1]0x100", - "[s2]-0x8001", - "[b]1", - "[b]1111111k", - "[dist4]unmatched", - "[anchr]hello [dist8]hello", - "[dist4]a [dist4]a [anchr]a", - "[dist4]a [anchr]a [dist4]a [anchr]a", - "0 [handles]50", - nullptr}; - - for (size_t i = 0; error_inputs[i]; ++i) { - std::vector<uint8_t> expected; - if (!TestInputParser(error_inputs[i], false, expected, 0)) - ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i]; - } - } -} - -TEST_F(ValidationTest, Conformance) { - DummyMessageReceiver dummy_receiver; - mojo::FilterChain validators(&dummy_receiver); - validators.Append<mojo::MessageHeaderValidator>(); - validators.Append<ConformanceTestInterface::RequestValidator_>(); - - RunValidationTests("conformance_", &validators); -} - -TEST_F(ValidationTest, AssociatedConformace) { - DummyMessageReceiver dummy_receiver; - mojo::FilterChain validators(&dummy_receiver); - validators.Append<mojo::MessageHeaderValidator>(); - validators.Append<AssociatedConformanceTestInterface::RequestValidator_>(); - - RunValidationTests("associated_conformance_", &validators); -} - -// This test is similar to Conformance test but its goal is specifically -// do bounds-check testing of message validation. For example we test the -// detection of off-by-one errors in method ordinals. -TEST_F(ValidationTest, BoundsCheck) { - DummyMessageReceiver dummy_receiver; - mojo::FilterChain validators(&dummy_receiver); - validators.Append<mojo::MessageHeaderValidator>(); - validators.Append<BoundsCheckTestInterface::RequestValidator_>(); - - RunValidationTests("boundscheck_", &validators); -} - -// This test is similar to the Conformance test but for responses. -TEST_F(ValidationTest, ResponseConformance) { - DummyMessageReceiver dummy_receiver; - mojo::FilterChain validators(&dummy_receiver); - validators.Append<mojo::MessageHeaderValidator>(); - validators.Append<ConformanceTestInterface::ResponseValidator_>(); - - RunValidationTests("resp_conformance_", &validators); -} - -// This test is similar to the BoundsCheck test but for responses. -TEST_F(ValidationTest, ResponseBoundsCheck) { - DummyMessageReceiver dummy_receiver; - mojo::FilterChain validators(&dummy_receiver); - validators.Append<mojo::MessageHeaderValidator>(); - validators.Append<BoundsCheckTestInterface::ResponseValidator_>(); - - RunValidationTests("resp_boundscheck_", &validators); -} - -// Test that InterfacePtr<X> applies the correct validators and they don't -// conflict with each other: -// - MessageHeaderValidator -// - X::ResponseValidator_ -TEST_F(ValidationIntegrationTest, InterfacePtr) { - IntegrationTestInterfacePtr interface_ptr = MakeProxy( - InterfacePtrInfo<IntegrationTestInterface>(testee_endpoint(), 0u)); - interface_ptr.internal_state()->EnableTestingMode(); - - RunValidationTests("integration_intf_resp", test_message_receiver()); - RunValidationTests("integration_msghdr", test_message_receiver()); -} - -// Test that Binding<X> applies the correct validators and they don't -// conflict with each other: -// - MessageHeaderValidator -// - X::RequestValidator_ -TEST_F(ValidationIntegrationTest, Binding) { - IntegrationTestInterfaceImpl interface_impl; - Binding<IntegrationTestInterface> binding( - &interface_impl, - MakeRequest<IntegrationTestInterface>(testee_endpoint())); - binding.EnableTestingMode(); - - RunValidationTests("integration_intf_rqst", test_message_receiver()); - RunValidationTests("integration_msghdr", test_message_receiver()); -} - -// Test pointer validation (specifically, that the encoded offset is 32-bit) -TEST_F(ValidationTest, ValidateEncodedPointer) { - uint64_t offset; - - offset = 0ULL; - EXPECT_TRUE(mojo::internal::ValidateEncodedPointer(&offset)); - - offset = 1ULL; - EXPECT_TRUE(mojo::internal::ValidateEncodedPointer(&offset)); - - // offset must be <= 32-bit. - offset = std::numeric_limits<uint32_t>::max() + 1ULL; - EXPECT_FALSE(mojo::internal::ValidateEncodedPointer(&offset)); -} - -// Tests the IsKnownEnumValue() function generated for BasicEnum. -TEST(EnumValueValidationTest, BasicEnum) { - // BasicEnum can have -3,0,1,10 as possible integral values. - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(-4))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<BasicEnum>(-3))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(-2))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(-1))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<BasicEnum>(0))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<BasicEnum>(1))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(2))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(9))); - // In the mojom, we represent this value as hex (0xa). - EXPECT_TRUE(IsKnownEnumValue(static_cast<BasicEnum>(10))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<BasicEnum>(11))); -} - -// Tests the IsKnownEnumValue() method generated for StructWithEnum. -TEST(EnumValueValidationTest, EnumWithin) { - // StructWithEnum::EnumWithin can have [0,4] as possible integral values. - EXPECT_FALSE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(-1))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(0))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(1))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(2))); - EXPECT_TRUE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(3))); - EXPECT_FALSE(IsKnownEnumValue(static_cast<StructWithEnum::EnumWithin>(4))); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/variant_test_util.h b/mojo/public/cpp/bindings/tests/variant_test_util.h deleted file mode 100644 index 3f6b1f1..0000000 --- a/mojo/public/cpp/bindings/tests/variant_test_util.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_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/versioning_apptest.cc b/mojo/public/cpp/bindings/tests/versioning_apptest.cc deleted file mode 100644 index 95a89c0..0000000 --- a/mojo/public/cpp/bindings/tests/versioning_apptest.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "mojo/public/interfaces/bindings/tests/versioning_test_client.mojom.h" -#include "services/service_manager/public/cpp/application_test_base.h" -#include "services/service_manager/public/cpp/connector.h" - -namespace mojo { -namespace test { -namespace versioning { - -class VersioningApplicationTest : public ApplicationTestBase { - public: - VersioningApplicationTest() : ApplicationTestBase() {} - ~VersioningApplicationTest() override {} - - protected: - // ApplicationTestBase overrides. - void SetUp() override { - ApplicationTestBase::SetUp(); - - connector()->BindInterface("versioning_test_service", &database_); - } - - HumanResourceDatabasePtr database_; - - private: - DISALLOW_COPY_AND_ASSIGN(VersioningApplicationTest); -}; - -TEST_F(VersioningApplicationTest, Struct) { - // The service side uses a newer version of Employee defintion. - // The returned struct should be truncated. - EmployeePtr employee(Employee::New()); - employee->employee_id = 1; - employee->name = "Homer Simpson"; - employee->department = DEPARTMENT_DEV; - - database_->QueryEmployee(1, true, - [&employee](EmployeePtr returned_employee, - Array<uint8_t> returned_finger_print) { - EXPECT_TRUE(employee->Equals(*returned_employee)); - EXPECT_FALSE(returned_finger_print.is_null()); - }); - database_.WaitForIncomingResponse(); - - // Passing a struct of older version to the service side works. - EmployeePtr new_employee(Employee::New()); - new_employee->employee_id = 2; - new_employee->name = "Marge Simpson"; - new_employee->department = DEPARTMENT_SALES; - - database_->AddEmployee(new_employee.Clone(), - [](bool success) { EXPECT_TRUE(success); }); - database_.WaitForIncomingResponse(); - - database_->QueryEmployee( - 2, false, [&new_employee](EmployeePtr returned_employee, - Array<uint8_t> returned_finger_print) { - EXPECT_TRUE(new_employee->Equals(*returned_employee)); - EXPECT_TRUE(returned_finger_print.is_null()); - }); - database_.WaitForIncomingResponse(); -} - -TEST_F(VersioningApplicationTest, QueryVersion) { - EXPECT_EQ(0u, database_.version()); - database_.QueryVersion([](uint32_t version) { EXPECT_EQ(1u, version); }); - database_.WaitForIncomingResponse(); - EXPECT_EQ(1u, database_.version()); -} - -TEST_F(VersioningApplicationTest, RequireVersion) { - EXPECT_EQ(0u, database_.version()); - - database_.RequireVersion(1); - EXPECT_EQ(1u, database_.version()); - database_->QueryEmployee(3, false, - [](EmployeePtr returned_employee, - Array<uint8_t> returned_finger_print) {}); - database_.WaitForIncomingResponse(); - EXPECT_FALSE(database_.encountered_error()); - - // Requiring a version higher than what the service side implements will close - // the pipe. - database_.RequireVersion(3); - EXPECT_EQ(3u, database_.version()); - database_->QueryEmployee(1, false, - [](EmployeePtr returned_employee, - Array<uint8_t> returned_finger_print) {}); - database_.WaitForIncomingResponse(); - EXPECT_TRUE(database_.encountered_error()); -} - -TEST_F(VersioningApplicationTest, CallNonexistentMethod) { - EXPECT_EQ(0u, database_.version()); - - Array<uint8_t> new_finger_print(128); - for (size_t i = 0; i < 128; ++i) - new_finger_print[i] = i + 13; - - // Although the client side doesn't know whether the service side supports - // version 1, calling a version 1 method succeeds as long as the service side - // supports version 1. - database_->AttachFingerPrint(1, new_finger_print.Clone(), - [](bool success) { EXPECT_TRUE(success); }); - database_.WaitForIncomingResponse(); - - // Calling a version 2 method (which the service side doesn't support) closes - // the pipe. - database_->ListEmployeeIds([](Array<uint64_t> ids) { EXPECT_TRUE(false); }); - database_.WaitForIncomingResponse(); - EXPECT_TRUE(database_.encountered_error()); -} - -} // namespace versioning -} // namespace examples -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/versioning_test_service.cc b/mojo/public/cpp/bindings/tests/versioning_test_service.cc deleted file mode 100644 index 313a624..0000000 --- a/mojo/public/cpp/bindings/tests/versioning_test_service.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <map> -#include <utility> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/interfaces/bindings/tests/versioning_test_service.mojom.h" -#include "services/service_manager/public/c/main.h" -#include "services/service_manager/public/cpp/interface_factory.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_runner.h" - -namespace mojo { -namespace test { -namespace versioning { - -struct EmployeeInfo { - public: - EmployeeInfo() {} - - EmployeePtr employee; - Array<uint8_t> finger_print; - - private: - DISALLOW_COPY_AND_ASSIGN(EmployeeInfo); -}; - -class HumanResourceDatabaseImpl : public HumanResourceDatabase { - public: - explicit HumanResourceDatabaseImpl( - InterfaceRequest<HumanResourceDatabase> request) - : strong_binding_(this, std::move(request)) { - // Pretend that there is already some data in the system. - EmployeeInfo* info = new EmployeeInfo(); - employees_[1] = info; - info->employee = Employee::New(); - info->employee->employee_id = 1; - info->employee->name = "Homer Simpson"; - info->employee->department = DEPARTMENT_DEV; - info->employee->birthday = Date::New(); - info->employee->birthday->year = 1955; - info->employee->birthday->month = 5; - info->employee->birthday->day = 12; - info->finger_print.resize(1024); - for (uint32_t i = 0; i < 1024; ++i) - info->finger_print[i] = i; - } - - ~HumanResourceDatabaseImpl() override { - for (auto iter = employees_.begin(); iter != employees_.end(); ++iter) - delete iter->second; - } - - void AddEmployee(EmployeePtr employee, - const AddEmployeeCallback& callback) override { - uint64_t id = employee->employee_id; - if (employees_.find(id) == employees_.end()) - employees_[id] = new EmployeeInfo(); - employees_[id]->employee = std::move(employee); - callback.Run(true); - } - - void QueryEmployee(uint64_t id, - bool retrieve_finger_print, - const QueryEmployeeCallback& callback) override { - if (employees_.find(id) == employees_.end()) { - callback.Run(nullptr, Array<uint8_t>()); - return; - } - callback.Run(employees_[id]->employee.Clone(), - retrieve_finger_print ? employees_[id]->finger_print.Clone() - : Array<uint8_t>()); - } - - void AttachFingerPrint(uint64_t id, - Array<uint8_t> finger_print, - const AttachFingerPrintCallback& callback) override { - if (employees_.find(id) == employees_.end()) { - callback.Run(false); - return; - } - employees_[id]->finger_print = std::move(finger_print); - callback.Run(true); - } - - private: - std::map<uint64_t, EmployeeInfo*> employees_; - - StrongBinding<HumanResourceDatabase> strong_binding_; -}; - -class HumanResourceSystemServer - : public service_manager::Service, - public InterfaceFactory<HumanResourceDatabase> { - public: - HumanResourceSystemServer() {} - - // service_manager::Service implementation. - bool OnConnect(Connection* connection) override { - connection->AddInterface<HumanResourceDatabase>(this); - return true; - } - - // InterfaceFactory<HumanResourceDatabase> implementation. - void Create(Connection* connection, - InterfaceRequest<HumanResourceDatabase> request) override { - // It will be deleted automatically when the underlying pipe encounters a - // connection error. - new HumanResourceDatabaseImpl(std::move(request)); - } -}; - -} // namespace versioning -} // namespace test -} // namespace mojo - -MojoResult ServiceMain(MojoHandle request) { - mojo::ServiceRunner runner( - new mojo::test::versioning::HumanResourceSystemServer()); - - return runner.Run(request); -} diff --git a/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc deleted file mode 100644 index 959d25b..0000000 --- a/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/wtf_hash_util.h" - -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom-blink.h" -#include "mojo/public/interfaces/bindings/tests/test_wtf_types.mojom-blink.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/Source/wtf/HashFunctions.h" - -namespace mojo { -namespace test { -namespace { - -using WTFHashTest = testing::Test; - -TEST_F(WTFHashTest, NestedStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ(::mojo::internal::Hash( - ::mojo::internal::kHashSeed, - blink::SimpleNestedStruct::New(blink::ContainsOther::New(1))), - ::mojo::internal::Hash( - ::mojo::internal::kHashSeed, - blink::SimpleNestedStruct::New(blink::ContainsOther::New(1)))); -} - -TEST_F(WTFHashTest, UnmappedNativeStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ(::mojo::internal::Hash(::mojo::internal::kHashSeed, - blink::UnmappedNativeStruct::New()), - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - blink::UnmappedNativeStruct::New())); -} - -TEST_F(WTFHashTest, Enum) { - // Just check that this template instantiation compiles. - - // Top-level. - ASSERT_EQ(WTF::DefaultHash<blink::TopLevelEnum>::Hash().hash( - blink::TopLevelEnum::E0), - WTF::DefaultHash<blink::TopLevelEnum>::Hash().hash( - blink::TopLevelEnum::E0)); - - // Nested in struct. - ASSERT_EQ(WTF::DefaultHash<blink::TestWTFStruct::NestedEnum>::Hash().hash( - blink::TestWTFStruct::NestedEnum::E0), - WTF::DefaultHash<blink::TestWTFStruct::NestedEnum>::Hash().hash( - blink::TestWTFStruct::NestedEnum::E0)); - - // Nested in interface. - ASSERT_EQ(WTF::DefaultHash<blink::TestWTF::NestedEnum>::Hash().hash( - blink::TestWTF::NestedEnum::E0), - WTF::DefaultHash<blink::TestWTF::NestedEnum>::Hash().hash( - blink::TestWTF::NestedEnum::E0)); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/wtf_map_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_map_unittest.cc deleted file mode 100644 index dc40143..0000000 --- a/mojo/public/cpp/bindings/tests/wtf_map_unittest.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/tests/rect_blink.h" -#include "mojo/public/interfaces/bindings/tests/rect.mojom-blink.h" -#include "mojo/public/interfaces/bindings/tests/test_structs.mojom-blink.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace test { -namespace { - -TEST(WTFMapTest, StructKey) { - WTF::HashMap<blink::RectPtr, int32_t> map; - map.insert(blink::Rect::New(1, 2, 3, 4), 123); - - blink::RectPtr key = blink::Rect::New(1, 2, 3, 4); - ASSERT_NE(map.end(), map.find(key)); - ASSERT_EQ(123, map.find(key)->value); - - map.erase(key); - ASSERT_EQ(0u, map.size()); -} - -TEST(WTFMapTest, TypemappedStructKey) { - WTF::HashMap<blink::ContainsHashablePtr, int32_t> map; - map.insert(blink::ContainsHashable::New(RectBlink(1, 2, 3, 4)), 123); - - blink::ContainsHashablePtr key = - blink::ContainsHashable::New(RectBlink(1, 2, 3, 4)); - ASSERT_NE(map.end(), map.find(key)); - ASSERT_EQ(123, map.find(key)->value); - - map.erase(key); - ASSERT_EQ(0u, map.size()); -} - -} // namespace -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc deleted file mode 100644 index 363ef7c..0000000 --- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#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" -#include "third_party/WebKit/Source/wtf/text/StringHash.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 base::Optional<std::string>& str, - const EchoStringCallback& callback) override { - callback.Run(str); - } - - void EchoStringArray( - const base::Optional<std::vector<base::Optional<std::string>>>& arr, - const EchoStringArrayCallback& callback) override { - callback.Run(std::move(arr)); - } - - void EchoStringMap( - const base::Optional< - std::unordered_map<std::string, base::Optional<std::string>>>& - str_map, - const EchoStringMapCallback& callback) override { - callback.Run(std::move(str_map)); - } - - private: - Binding<TestWTF> binding_; -}; - -class WTFTypesTest : public testing::Test { - public: - WTFTypesTest() {} - - private: - base::MessageLoop loop_; -}; - -WTF::Vector<WTF::String> ConstructStringArray() { - WTF::Vector<WTF::String> strs(4); - // strs[0] is null. - // strs[1] is empty. - strs[1] = ""; - strs[2] = kHelloWorld; - strs[3] = WTF::String::fromUTF8(kUTF8HelloWorld); - - return strs; -} - -WTF::HashMap<WTF::String, WTF::String> ConstructStringMap() { - WTF::HashMap<WTF::String, WTF::String> str_map; - // A null string as value. - str_map.insert("0", WTF::String()); - str_map.insert("1", kHelloWorld); - str_map.insert("2", WTF::String::fromUTF8(kUTF8HelloWorld)); - - return str_map; -} - -void ExpectString(const WTF::String& expected_string, - const base::Closure& closure, - const WTF::String& string) { - EXPECT_EQ(expected_string, string); - closure.Run(); -} - -void ExpectStringArray(WTF::Optional<WTF::Vector<WTF::String>>* expected_arr, - const base::Closure& closure, - const WTF::Optional<WTF::Vector<WTF::String>>& arr) { - EXPECT_EQ(*expected_arr, arr); - closure.Run(); -} - -void ExpectStringMap( - WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map, - const base::Closure& closure, - const WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>& map) { - EXPECT_EQ(*expected_map, map); - closure.Run(); -} - -} // namespace - -TEST_F(WTFTypesTest, Serialization_WTFVectorToWTFVector) { - using MojomType = ArrayDataView<StringDataView>; - - WTF::Vector<WTF::String> strs = ConstructStringArray(); - auto cloned_strs = strs; - - mojo::internal::SerializationContext context; - size_t size = - mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context); - - mojo::internal::FixedBufferForTesting buf(size); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::ContainerValidateParams validate_params( - 0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr)); - mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data, - &validate_params, &context); - - WTF::Vector<WTF::String> strs2; - mojo::internal::Deserialize<MojomType>(data, &strs2, &context); - - EXPECT_EQ(strs, strs2); -} - -TEST_F(WTFTypesTest, Serialization_WTFVectorToStlVector) { - using MojomType = ArrayDataView<StringDataView>; - - WTF::Vector<WTF::String> strs = ConstructStringArray(); - auto cloned_strs = strs; - - mojo::internal::SerializationContext context; - size_t size = - mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context); - - mojo::internal::FixedBufferForTesting buf(size); - typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; - mojo::internal::ContainerValidateParams validate_params( - 0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr)); - mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data, - &validate_params, &context); - - std::vector<base::Optional<std::string>> strs2; - mojo::internal::Deserialize<MojomType>(data, &strs2, &context); - - ASSERT_EQ(4u, strs2.size()); - EXPECT_FALSE(strs2[0]); - EXPECT_EQ("", *strs2[1]); - EXPECT_EQ(kHelloWorld, *strs2[2]); - EXPECT_EQ(kUTF8HelloWorld, *strs2[3]); -} - -TEST_F(WTFTypesTest, Serialization_PublicAPI) { - blink::TestWTFStructPtr input(blink::TestWTFStruct::New(kHelloWorld, 42)); - - blink::TestWTFStructPtr cloned_input = input.Clone(); - - auto data = blink::TestWTFStruct::Serialize(&input); - - blink::TestWTFStructPtr output; - ASSERT_TRUE(blink::TestWTFStruct::Deserialize(std::move(data), &output)); - EXPECT_TRUE(cloned_input.Equals(output)); -} - -TEST_F(WTFTypesTest, SendString) { - blink::TestWTFPtr ptr; - TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr))); - - WTF::Vector<WTF::String> strs = ConstructStringArray(); - - for (size_t i = 0; i < strs.size(); ++i) { - base::RunLoop loop; - // Test that a WTF::String is unchanged after the following conversion: - // - serialized; - // - deserialized as base::Optional<std::string>; - // - serialized; - // - deserialized as WTF::String. - ptr->EchoString(strs[i], - base::Bind(&ExpectString, strs[i], loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(WTFTypesTest, SendStringArray) { - blink::TestWTFPtr ptr; - TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr))); - - WTF::Optional<WTF::Vector<WTF::String>> arrs[3]; - // arrs[0] is empty. - arrs[0].emplace(); - // arrs[1] is null. - arrs[2] = ConstructStringArray(); - - for (size_t i = 0; i < arraysize(arrs); ++i) { - base::RunLoop loop; - // Test that a WTF::Optional<WTF::Vector<WTF::String>> is unchanged after - // the following conversion: - // - serialized; - // - deserialized as - // base::Optional<std::vector<base::Optional<std::string>>>; - // - serialized; - // - deserialized as WTF::Optional<WTF::Vector<WTF::String>>. - ptr->EchoStringArray( - arrs[i], base::Bind(&ExpectStringArray, base::Unretained(&arrs[i]), - loop.QuitClosure())); - loop.Run(); - } -} - -TEST_F(WTFTypesTest, SendStringMap) { - blink::TestWTFPtr ptr; - TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr))); - - WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> maps[3]; - // maps[0] is empty. - maps[0].emplace(); - // maps[1] is null. - maps[2] = ConstructStringMap(); - - for (size_t i = 0; i < arraysize(maps); ++i) { - base::RunLoop loop; - // Test that a WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> is - // unchanged after the following conversion: - // - serialized; - // - deserialized as base::Optional< - // std::unordered_map<std::string, base::Optional<std::string>>>; - // - serialized; - // - deserialized as WTF::Optional<WTF::HashMap<WTF::String, - // WTF::String>>. - ptr->EchoStringMap(maps[i], - base::Bind(&ExpectStringMap, base::Unretained(&maps[i]), - loop.QuitClosure())); - loop.Run(); - } -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h deleted file mode 100644 index 740687f..0000000 --- a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/stl_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" -#include "mojo/public/cpp/bindings/sync_event_watcher.h" - -// ThreadSafeInterfacePtr wraps a non-thread-safe InterfacePtr and proxies -// messages to it. Async calls are posted to the thread that the InteracePtr is -// bound to, and the responses are posted back. Sync calls are dispatched -// directly if the call is made on the thread that the wrapped InterfacePtr is -// bound to, or posted otherwise. It's important to be aware that sync calls -// block both the calling thread and the InterfacePtr thread. That means that -// you cannot make sync calls through a ThreadSafeInterfacePtr if the -// underlying InterfacePtr is bound to a thread that cannot block, like the IO -// thread. - -namespace mojo { - -// Instances of this class may be used from any thread to serialize |Interface| -// messages and forward them elsewhere. In general you should use one of the -// ThreadSafeInterfacePtrBase helper aliases defined below, but this type may be -// useful if you need/want to manually manage the lifetime of the underlying -// proxy object which will be used to ultimately send messages. -template <typename Interface> -class ThreadSafeForwarder : public MessageReceiverWithResponder { - public: - using ProxyType = typename Interface::Proxy_; - using ForwardMessageCallback = base::Callback<void(Message)>; - using ForwardMessageWithResponderCallback = - base::Callback<void(Message, std::unique_ptr<MessageReceiver>)>; - - // Constructs a ThreadSafeForwarder through which Messages are forwarded to - // |forward| or |forward_with_responder| by posting to |task_runner|. - // - // Any message sent through this forwarding interface will dispatch its reply, - // if any, back to the thread which called the corresponding interface method. - ThreadSafeForwarder( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - const ForwardMessageCallback& forward, - const ForwardMessageWithResponderCallback& forward_with_responder, - const AssociatedGroup& associated_group) - : proxy_(this), - task_runner_(task_runner), - forward_(forward), - forward_with_responder_(forward_with_responder), - associated_group_(associated_group), - sync_calls_(new InProgressSyncCalls()) {} - - ~ThreadSafeForwarder() override { - // If there are ongoing sync calls signal their completion now. - base::AutoLock l(sync_calls_->lock); - for (const auto& pending_response : sync_calls_->pending_responses) - pending_response->event.Signal(); - } - - ProxyType& proxy() { return proxy_; } - - private: - // MessageReceiverWithResponder implementation: - bool Accept(Message* message) override { - if (!message->associated_endpoint_handles()->empty()) { - // If this DCHECK fails, it is likely because: - // - This is a non-associated interface pointer setup using - // PtrWrapper::BindOnTaskRunner( - // InterfacePtrInfo<InterfaceType> ptr_info); - // Please see the TODO in that method. - // - This is an associated interface which hasn't been associated with a - // message pipe. In other words, the corresponding - // AssociatedInterfaceRequest hasn't been sent. - DCHECK(associated_group_.GetController()); - message->SerializeAssociatedEndpointHandles( - associated_group_.GetController()); - } - task_runner_->PostTask(FROM_HERE, - base::Bind(forward_, base::Passed(message))); - return true; - } - - bool AcceptWithResponder( - Message* message, - std::unique_ptr<MessageReceiver> responder) override { - if (!message->associated_endpoint_handles()->empty()) { - // Please see comment for the DCHECK in the previous method. - DCHECK(associated_group_.GetController()); - message->SerializeAssociatedEndpointHandles( - associated_group_.GetController()); - } - - // Async messages are always posted (even if |task_runner_| runs tasks on - // this thread) to guarantee that two async calls can't be reordered. - if (!message->has_flag(Message::kFlagIsSync)) { - auto reply_forwarder = - base::MakeUnique<ForwardToCallingThread>(std::move(responder)); - task_runner_->PostTask( - FROM_HERE, base::Bind(forward_with_responder_, base::Passed(message), - base::Passed(&reply_forwarder))); - return true; - } - - SyncCallRestrictions::AssertSyncCallAllowed(); - - // If the InterfacePtr is bound to this thread, dispatch it directly. - if (task_runner_->RunsTasksOnCurrentThread()) { - forward_with_responder_.Run(std::move(*message), std::move(responder)); - return true; - } - - // If the InterfacePtr is bound on another thread, post the call. - // TODO(yzshen, watk): We block both this thread and the InterfacePtr - // thread. Ideally only this thread would block. - auto response = make_scoped_refptr(new SyncResponseInfo()); - auto response_signaler = base::MakeUnique<SyncResponseSignaler>(response); - task_runner_->PostTask( - FROM_HERE, base::Bind(forward_with_responder_, base::Passed(message), - base::Passed(&response_signaler))); - - // Save the pending SyncResponseInfo so that if the sync call deletes - // |this|, we can signal the completion of the call to return from - // SyncWatch(). - auto sync_calls = sync_calls_; - { - base::AutoLock l(sync_calls->lock); - sync_calls->pending_responses.push_back(response.get()); - } - - auto assign_true = [](bool* b) { *b = true; }; - bool event_signaled = false; - SyncEventWatcher watcher(&response->event, - base::Bind(assign_true, &event_signaled)); - watcher.SyncWatch(&event_signaled); - - { - base::AutoLock l(sync_calls->lock); - base::Erase(sync_calls->pending_responses, response.get()); - } - - if (response->received) - ignore_result(responder->Accept(&response->message)); - - return true; - } - - // Data that we need to share between the threads involved in a sync call. - struct SyncResponseInfo - : public base::RefCountedThreadSafe<SyncResponseInfo> { - Message message; - bool received = false; - base::WaitableEvent event{base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED}; - - private: - friend class base::RefCountedThreadSafe<SyncResponseInfo>; - }; - - // A MessageReceiver that signals |response| when it either accepts the - // response message, or is destructed. - class SyncResponseSignaler : public MessageReceiver { - public: - explicit SyncResponseSignaler(scoped_refptr<SyncResponseInfo> response) - : response_(response) {} - - ~SyncResponseSignaler() override { - // If Accept() was not called we must still notify the waiter that the - // sync call is finished. - if (response_) - response_->event.Signal(); - } - - bool Accept(Message* message) { - response_->message = std::move(*message); - response_->received = true; - response_->event.Signal(); - response_ = nullptr; - return true; - } - - private: - scoped_refptr<SyncResponseInfo> response_; - }; - - // A record of the pending sync responses for canceling pending sync calls - // when the owning ThreadSafeForwarder is destructed. - struct InProgressSyncCalls - : public base::RefCountedThreadSafe<InProgressSyncCalls> { - // |lock| protects access to |pending_responses|. - base::Lock lock; - std::vector<SyncResponseInfo*> pending_responses; - }; - - class ForwardToCallingThread : public MessageReceiver { - public: - explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) - : responder_(std::move(responder)), - caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} - - private: - bool Accept(Message* message) { - // The current instance will be deleted when this method returns, so we - // have to relinquish the responder's ownership so it does not get - // deleted. - caller_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, - base::Passed(std::move(responder_)), - base::Passed(std::move(*message)))); - return true; - } - - static void CallAcceptAndDeleteResponder( - std::unique_ptr<MessageReceiver> responder, - Message message) { - ignore_result(responder->Accept(&message)); - } - - std::unique_ptr<MessageReceiver> responder_; - scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; - }; - - ProxyType proxy_; - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - const ForwardMessageCallback forward_; - const ForwardMessageWithResponderCallback forward_with_responder_; - AssociatedGroup associated_group_; - scoped_refptr<InProgressSyncCalls> sync_calls_; - - DISALLOW_COPY_AND_ASSIGN(ThreadSafeForwarder); -}; - -template <typename InterfacePtrType> -class ThreadSafeInterfacePtrBase - : public base::RefCountedThreadSafe< - ThreadSafeInterfacePtrBase<InterfacePtrType>> { - public: - using InterfaceType = typename InterfacePtrType::InterfaceType; - using PtrInfoType = typename InterfacePtrType::PtrInfoType; - - explicit ThreadSafeInterfacePtrBase( - std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder) - : forwarder_(std::move(forwarder)) {} - - // Creates a ThreadSafeInterfacePtrBase wrapping an underlying non-thread-safe - // InterfacePtrType which is bound to the calling thread. All messages sent - // via this thread-safe proxy will internally be sent by first posting to this - // (the calling) thread's TaskRunner. - static scoped_refptr<ThreadSafeInterfacePtrBase> Create( - InterfacePtrType interface_ptr) { - scoped_refptr<PtrWrapper> wrapper = - new PtrWrapper(std::move(interface_ptr)); - return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder()); - } - - // Creates a ThreadSafeInterfacePtrBase which binds the underlying - // non-thread-safe InterfacePtrType on the specified TaskRunner. All messages - // sent via this thread-safe proxy will internally be sent by first posting to - // that TaskRunner. - static scoped_refptr<ThreadSafeInterfacePtrBase> Create( - PtrInfoType ptr_info, - const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) { - scoped_refptr<PtrWrapper> wrapper = new PtrWrapper(bind_task_runner); - wrapper->BindOnTaskRunner(std::move(ptr_info)); - return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder()); - } - - InterfaceType* get() { return &forwarder_->proxy(); } - InterfaceType* operator->() { return get(); } - InterfaceType& operator*() { return *get(); } - - private: - friend class base::RefCountedThreadSafe< - ThreadSafeInterfacePtrBase<InterfacePtrType>>; - - struct PtrWrapperDeleter; - - // Helper class which owns an |InterfacePtrType| instance on an appropriate - // thread. This is kept alive as long its bound within some - // ThreadSafeForwarder's callbacks. - class PtrWrapper - : public base::RefCountedThreadSafe<PtrWrapper, PtrWrapperDeleter> { - public: - explicit PtrWrapper(InterfacePtrType ptr) - : PtrWrapper(base::ThreadTaskRunnerHandle::Get()) { - ptr_ = std::move(ptr); - associated_group_ = *ptr_.internal_state()->associated_group(); - } - - explicit PtrWrapper( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) - : task_runner_(task_runner) {} - - void BindOnTaskRunner(AssociatedInterfacePtrInfo<InterfaceType> ptr_info) { - associated_group_ = AssociatedGroup(ptr_info.handle()); - task_runner_->PostTask(FROM_HERE, base::Bind(&PtrWrapper::Bind, this, - base::Passed(&ptr_info))); - } - - void BindOnTaskRunner(InterfacePtrInfo<InterfaceType> ptr_info) { - // TODO(yzhsen): At the momment we don't have a group controller - // available. That means the user won't be able to pass associated - // endpoints on this interface (at least not immediately). In order to fix - // this, we need to create a MultiplexRouter immediately and bind it to - // the interface pointer on the |task_runner_|. Therefore, MultiplexRouter - // should be able to be created on a thread different than the one that it - // is supposed to listen on. crbug.com/682334 - task_runner_->PostTask(FROM_HERE, base::Bind(&PtrWrapper::Bind, this, - base::Passed(&ptr_info))); - } - - std::unique_ptr<ThreadSafeForwarder<InterfaceType>> CreateForwarder() { - return base::MakeUnique<ThreadSafeForwarder<InterfaceType>>( - task_runner_, base::Bind(&PtrWrapper::Accept, this), - base::Bind(&PtrWrapper::AcceptWithResponder, this), - associated_group_); - } - - private: - friend struct PtrWrapperDeleter; - - ~PtrWrapper() {} - - void Bind(PtrInfoType ptr_info) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - ptr_.Bind(std::move(ptr_info)); - } - - void Accept(Message message) { - ptr_.internal_state()->ForwardMessage(std::move(message)); - } - - void AcceptWithResponder(Message message, - std::unique_ptr<MessageReceiver> responder) { - ptr_.internal_state()->ForwardMessageWithResponder(std::move(message), - std::move(responder)); - } - - void DeleteOnCorrectThread() const { - if (!task_runner_->RunsTasksOnCurrentThread()) { - // NOTE: This is only called when there are no more references to - // |this|, so binding it unretained is both safe and necessary. - task_runner_->PostTask(FROM_HERE, - base::Bind(&PtrWrapper::DeleteOnCorrectThread, - base::Unretained(this))); - } else { - delete this; - } - } - - InterfacePtrType ptr_; - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - AssociatedGroup associated_group_; - - DISALLOW_COPY_AND_ASSIGN(PtrWrapper); - }; - - struct PtrWrapperDeleter { - static void Destruct(const PtrWrapper* interface_ptr) { - interface_ptr->DeleteOnCorrectThread(); - } - }; - - ~ThreadSafeInterfacePtrBase() {} - - const std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder_; - - DISALLOW_COPY_AND_ASSIGN(ThreadSafeInterfacePtrBase); -}; - -template <typename Interface> -using ThreadSafeAssociatedInterfacePtr = - ThreadSafeInterfacePtrBase<AssociatedInterfacePtr<Interface>>; - -template <typename Interface> -using ThreadSafeInterfacePtr = - ThreadSafeInterfacePtrBase<InterfacePtr<Interface>>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ diff --git a/mojo/public/cpp/bindings/type_converter.h b/mojo/public/cpp/bindings/type_converter.h deleted file mode 100644 index 395eeb4..0000000 --- a/mojo/public/cpp/bindings/type_converter.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_ - -#include <stdint.h> - -#include <vector> - -namespace mojo { - -// NOTE: TypeConverter is deprecated. Please consider StructTraits / -// UnionTraits / EnumTraits / ArrayTraits / MapTraits / StringTraits if you -// would like to convert between custom types and the wire format of mojom -// types. -// -// Specialize the following class: -// template <typename T, typename U> struct TypeConverter; -// to perform type conversion for Mojom-defined structs and arrays. Here, T is -// the target type; U is the input type. -// -// Specializations should implement the following interfaces: -// namespace mojo { -// template <> -// struct TypeConverter<X, Y> { -// static X Convert(const Y& input); -// }; -// template <> -// struct TypeConverter<Y, X> { -// static Y Convert(const X& input); -// }; -// } -// -// EXAMPLE: -// -// Suppose you have the following Mojom-defined struct: -// -// module geometry { -// struct Point { -// int32_t x; -// int32_t y; -// }; -// } -// -// Now, imagine you wanted to write a TypeConverter specialization for -// gfx::Point. It might look like this: -// -// namespace mojo { -// template <> -// struct TypeConverter<geometry::PointPtr, gfx::Point> { -// static geometry::PointPtr Convert(const gfx::Point& input) { -// geometry::PointPtr result; -// result->x = input.x(); -// result->y = input.y(); -// return result; -// } -// }; -// template <> -// struct TypeConverter<gfx::Point, geometry::PointPtr> { -// static gfx::Point Convert(const geometry::PointPtr& input) { -// return input ? gfx::Point(input->x, input->y) : gfx::Point(); -// } -// }; -// } -// -// With the above TypeConverter defined, it is possible to write code like this: -// -// void AcceptPoint(const geometry::PointPtr& input) { -// // With an explicit cast using the .To<> method. -// gfx::Point pt = input.To<gfx::Point>(); -// -// // With an explicit cast using the static From() method. -// geometry::PointPtr output = geometry::Point::From(pt); -// -// // Inferring the input type using the ConvertTo helper function. -// gfx::Point pt2 = ConvertTo<gfx::Point>(input); -// } -// -template <typename T, typename U> -struct TypeConverter; - -template <typename T, typename U> -inline T ConvertTo(const U& obj); - -// The following specialization is useful when you are converting between -// Array<POD> and std::vector<POD>. -template <typename T> -struct TypeConverter<T, T> { - static T Convert(const T& obj) { return obj; } -}; - -template <typename T, typename Container> -struct TypeConverter<std::vector<T>, Container> { - static std::vector<T> Convert(const Container& container) { - std::vector<T> output; - output.reserve(container.size()); - for (const auto& obj : container) { - output.push_back(ConvertTo<T>(obj)); - } - return output; - } -}; - -// The following helper function is useful for shorthand. The compiler can infer -// the input type, so you can write: -// OutputType out = ConvertTo<OutputType>(input); -template <typename T, typename U> -inline T ConvertTo(const U& obj) { - return TypeConverter<T, U>::Convert(obj); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_ diff --git a/mojo/public/cpp/bindings/union_traits.h b/mojo/public/cpp/bindings/union_traits.h deleted file mode 100644 index 292ee58..0000000 --- a/mojo/public/cpp/bindings/union_traits.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_UNION_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_UNION_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom union. |DataViewType| is the corresponding data view type of the -// mojom union. For example, if the mojom union is example.Foo, |DataViewType| -// will be example::FooDataView, which can also be referred to by -// example::Foo::DataView (in chromium) and example::blink::Foo::DataView (in -// blink). -// -// Similar to StructTraits, each specialization of UnionTraits implements the -// following methods: -// 1. Getters for each field in the Mojom type. -// 2. Read() method. -// 3. [Optional] IsNull() and SetToNull(). -// 4. [Optional] SetUpContext() and TearDownContext(). -// Please see the documentation of StructTraits for details of these methods. -// -// Unlike StructTraits, there is one more method to implement: -// 5. A static GetTag() method indicating which field is the current active -// field for serialization: -// -// static DataViewType::Tag GetTag(const T& input); -// -// During serialization, only the field getter corresponding to this tag -// will be called. -// -template <typename DataViewType, typename T> -struct UnionTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_UNION_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h b/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h deleted file mode 100644 index f1ac097..0000000 --- a/mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_UNIQUE_PTR_IMPL_REF_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_UNIQUE_PTR_IMPL_REF_TRAITS_H_ - -namespace mojo { - -// Traits for a binding's implementation reference type. -// This corresponds to a unique_ptr reference type. -template <typename Interface> -struct UniquePtrImplRefTraits { - using PointerType = std::unique_ptr<Interface>; - - static bool IsNull(const PointerType& ptr) { return !ptr; } - static Interface* GetRawPointer(PointerType* ptr) { return ptr->get(); } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_UNIQUE_PTR_IMPL_REF_TRAITS_H_ diff --git a/mojo/public/cpp/system/BUILD.gn b/mojo/public/cpp/system/BUILD.gn deleted file mode 100644 index 35087ef..0000000 --- a/mojo/public/cpp/system/BUILD.gn +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Deletes libsystem.dylib from the build dir, since it shadows -# /usr/lib/libSystem.dylib on macOS. -# TODO(thakis): Remove this after a while. -action("clean_up_old_dylib") { - script = "//build/rm.py" - stamp = "$target_gen_dir/clean_up_stamp" - outputs = [ - stamp, - ] - args = [ - "--stamp", - rebase_path(stamp, root_build_dir), - "-f", - "libsystem.dylib", - ] -} - -component("system") { - output_name = "mojo_public_system_cpp" - - sources = [ - "buffer.cc", - "buffer.h", - "core.h", - "data_pipe.h", - "functions.h", - "handle.h", - "handle_signals_state.h", - "message.h", - "message_pipe.h", - "platform_handle.cc", - "platform_handle.h", - "simple_watcher.cc", - "simple_watcher.h", - "system_export.h", - "wait.cc", - "wait.h", - "wait_set.cc", - "wait_set.h", - "watcher.cc", - "watcher.h", - ] - - public_deps = [ - "//base", - "//mojo/public/c/system", - ] - deps = [ - ":clean_up_old_dylib", - ] - - defines = [ "MOJO_CPP_SYSTEM_IMPLEMENTATION" ] -} diff --git a/mojo/public/cpp/system/README.md b/mojo/public/cpp/system/README.md deleted file mode 100644 index 782744f..0000000 --- a/mojo/public/cpp/system/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo C++ System API -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Overview -The Mojo C++ System API provides a convenient set of helper classes and -functions for working with Mojo primitives. Unlike the low-level -[C API](/mojo/public/c/system) (upon which this is built) this library takes -advantage of C++ language features and common STL and `//base` types to provide -a slightly more idiomatic interface to the Mojo system layer, making it -generally easier to use. - -This document provides a brief guide to API usage with example code snippets. -For a detailed API references please consult the headers in -[//mojo/public/cpp/system](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/). - -Note that all API symbols referenced in this document are implicitly in the -top-level `mojo` namespace. - -## Scoped, Typed Handles - -All types of Mojo handles in the C API are simply opaque, integral `MojoHandle` -values. The C++ API has more strongly typed wrappers defined for different -handle types: `MessagePipeHandle`, `SharedBufferHandle`, -`DataPipeConsumerHandle`, `DataPipeProducerHandle`, and `WatcherHandle`. - -Each of these also has a corresponding, move-only, scoped type for safer usage: -`ScopedMessagePipeHandle`, `ScopedSharedBufferHandle`, and so on. When a scoped -handle type is destroyed, its handle is automatically closed via `MojoClose`. -When working with raw handles you should **always** prefer to use one of the -scoped types for ownership. - -Similar to `std::unique_ptr`, scoped handle types expose a `get()` method to get -at the underlying unscoped handle type as well as the `->` operator to -dereference the scoper and make calls directly on the underlying handle type. - -## Message Pipes - -There are two ways to create a new message pipe using the C++ API. You may -construct a `MessagePipe` object: - -``` cpp -mojo::MessagePipe pipe; - -// NOTE: Because pipes are bi-directional there is no implicit semantic -// difference between |handle0| or |handle1| here. They're just two ends of a -// pipe. The choice to treat one as a "client" and one as a "server" is entirely -// a the API user's decision. -mojo::ScopedMessagePipeHandle client = std::move(pipe.handle0); -mojo::ScopedMessagePipeHandle server = std::move(pipe.handle1); -``` - -or you may call `CreateMessagePipe`: - -``` cpp -mojo::ScopedMessagePipeHandle client; -mojo::ScopedMessagePipeHandle server; -mojo::CreateMessagePipe(nullptr, &client, &server); -``` - -There are also some helper functions for constructing message objects and -reading/writing them on pipes using the library's more strongly-typed C++ -handles: - -``` cpp -mojo::ScopedMessageHandle message; -mojo::AllocMessage(6, nullptr, 0, MOJO_ALLOC_MESSAGE_FLAG_NONE, &message); - -void *buffer; -mojo::GetMessageBuffer(message.get(), &buffer); - -const std::string kMessage = "hello"; -std::copy(kMessage.begin(), kMessage.end(), static_cast<char*>(buffer)); - -mojo::WriteMessageNew(client.get(), std::move(message), - MOJO_WRITE_MESSAGE_FLAG_NONE); - -// Some time later... - -mojo::ScopedMessageHandle received_message; -uint32_t num_bytes; -mojo::ReadMessageNew(server.get(), &received_message, &num_bytes, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE); -``` - -See [message_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/message_pipe.h) -for detailed C++ message pipe API documentation. - -## Data Pipes - -Similar to [Message Pipes](#Message-Pipes), the C++ library has some simple -helpers for more strongly-typed data pipe usage: - -``` cpp -mojo::DataPipe pipe; -mojo::ScopedDataPipeProducerHandle producer = std::move(pipe.producer); -mojo::ScopedDataPipeConsumerHandle consumer = std::move(pipe.consumer); - -// Or alternatively: -mojo::ScopedDataPipeProducerHandle producer; -mojo::ScopedDataPipeConsumerHandle consumer; -mojo::CreateDataPipe(null, &producer, &consumer); -``` - -// Reads from a data pipe. See |MojoReadData()| for complete documentation. -inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, - void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) { - return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags); -} - -// Begins a two-phase read -C++ helpers which correspond directly to the -[Data Pipe C API](/mojo/public/c/system#Data-Pipes) for immediate and two-phase -I/O are provided as well. For example: - -``` cpp -uint32_t num_bytes = 7; -mojo::WriteDataRaw(producer.get(), "hihihi", - &num_bytes, MOJO_WRITE_DATA_FLAG_NONE); - -// Some time later... - -char buffer[64]; -uint32_t num_bytes = 64; -mojo::ReadDataRaw(consumer.get(), buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); -``` - -See [data_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/data_pipe.h) -for detailed C++ data pipe API documentation. - -## Shared Buffers - -A new shared buffers can be allocated like so: - -``` cpp -mojo::ScopedSharedBufferHandle buffer = - mojo::ScopedSharedBufferHandle::Create(4096); -``` - -This new handle can be cloned arbitrarily many times by using the underlying -handle's `Clone` method: - -``` cpp -mojo::ScopedSharedBufferHandle another_handle = buffer->Clone(); -mojo::ScopedSharedBufferHandle read_only_handle = - buffer->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY); -``` - -And finally the library also provides a scoper for mapping the shared buffer's -memory: - -``` cpp -mojo::ScopedSharedBufferMapping mapping = buffer->Map(64); -static_cast<int*>(mapping.get()) = 42; - -mojo::ScopedSharedBufferMapping another_mapping = buffer->MapAtOffset(64, 4); -static_cast<int*>(mapping.get()) = 43; -``` - -When `mapping` and `another_mapping` are destroyed, they automatically unmap -their respective memory regions. - -See [buffer.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/buffer.h) -for detailed C++ shared buffer API documentation. - -## Native Platform Handles (File Descriptors, Windows Handles, *etc.*) - -The C++ library provides several helpers for wrapping system handle types. -These are specifically useful when working with a few `//base` types, namely -`base::PlatformFile` and `base::SharedMemoryHandle`. See -[platform_handle.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/platform_handle.h) -for detailed C++ platform handle API documentation. - -## Signals & Watchers - -For an introduction to the concepts of handle signals and watchers, check out -the C API's documentation on [Signals & Watchers](/mojo/public/c/system#Signals-Watchers). - -### Querying Signals - -Any C++ handle type's last known signaling state can be queried by calling the -`QuerySignalsState` method on the handle: - -``` cpp -mojo::MessagePipe message_pipe; -mojo::DataPipe data_pipe; -mojo::HandleSignalsState a = message_pipe.handle0->QuerySignalsState(); -mojo::HandleSignalsState b = data_pipe.consumer->QuerySignalsState(); -``` - -The `HandleSignalsState` is a thin wrapper interface around the C API's -`MojoHandleSignalsState` structure with convenient accessors for testing -the signal bitmasks. Whereas when using the C API you might write: - -``` c -struct MojoHandleSignalsState state; -MojoQueryHandleSignalsState(handle0, &state); -if (state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE) { - // ... -} -``` - -the C++ API equivalent would be: - -``` cpp -if (message_pipe.handle0->QuerySignalsState().readable()) { - // ... -} -``` - -### Watching Handles - -The [`mojo::SimpleWatcher`](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/simple_watcher.h) -class serves as a convenient helper for using the [low-level watcher API](/mojo/public/c/system#Signals-Watchers) -to watch a handle for signaling state changes. A `SimpleWatcher` is bound to a -single thread and always dispatches its notifications on a -`base::SingleThreadTaskRunner`. - -`SimpleWatcher` has two possible modes of operation, selected at construction -time by the `mojo::SimpleWatcher::ArmingPolicy` enum: - -* `MANUAL` mode requires the user to manually call `Arm` and/or `ArmOrNotify` - before any notifications will fire regarding the state of the watched handle. - Every time the notification callback is run, the `SimpleWatcher` must be - rearmed again before the next one can fire. See - [Arming a Watcher](/mojo/public/c/system#Arming-a-Watcher) and the - documentation in `SimpleWatcher`'s header. - -* `AUTOMATIC` mode ensures that the `SimpleWatcher` always either is armed or - has a pending notification task queued for execution. - -`AUTOMATIC` mode is more convenient but can result in redundant notification -tasks, especially if the provided callback does not make a strong effort to -return the watched handle to an uninteresting signaling state (by *e.g.*, -reading all its available messages when notified of readability.) - -Example usage: - -``` cpp -class PipeReader { - public: - PipeReader(mojo::ScopedMessagePipeHandle pipe) - : pipe_(std::move(pipe)), - watcher_(mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC) { - // NOTE: base::Unretained is safe because the callback can never be run - // after SimpleWatcher destruction. - watcher_.Watch(pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&PipeReader::OnReadable, base::Unretained(this))); - } - - ~PipeReader() {} - - private: - void OnReadable(MojoResult result) { - while (result == MOJO_RESULT_OK) { - mojo::ScopedMessageHandle message; - uint32_t num_bytes; - result = mojo::ReadMessageNew(pipe_.get(), &message, &num_bytes, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE); - DCHECK_EQ(result, MOJO_RESULT_OK); - messages_.emplace_back(std::move(message)); - } - } - - mojo::ScopedMessagePipeHandle pipe_; - mojo::SimpleWatcher watcher_; - std::vector<mojo::ScopedMessageHandle> messages_; -}; - -mojo::MessagePipe pipe; -PipeReader reader(std::move(pipe.handle0)); - -// Written messages will asynchronously end up in |reader.messages_|. -WriteABunchOfStuff(pipe.handle1.get()); -``` - -## Synchronous Waiting - -The C++ System API defines some utilities to block a calling thread while -waiting for one or more handles to change signaling state in an interesting way. -These threads combine usage of the [low-level Watcher API](/mojo/public/c/system#Signals-Watchers) -with common synchronization primitives (namely `base::WaitableEvent`.) - -While these API features should be used sparingly, they are sometimes necessary. - -See the documentation in -[wait.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/wait.h) -and [wait_set.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/wait_set.h) -for a more detailed API reference. - -### Waiting On a Single Handle - -The `mojo::Wait` function simply blocks the calling thread until a given signal -mask is either partially satisfied or fully unsatisfiable on a given handle. - -``` cpp -mojo::MessagePipe pipe; -mojo::WriteMessageRaw(pipe.handle0.get(), "hey", 3, nullptr, nullptr, - MOJO_WRITE_MESSAGE_FLAG_NONE); -MojoResult result = mojo::Wait(pipe.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); -DCHECK_EQ(result, MOJO_RESULT_OK); - -// Guaranteed to succeed because we know |handle1| is readable now. -mojo::ScopedMessageHandle message; -uint32_t num_bytes; -mojo::ReadMessageNew(pipe.handle1.get(), &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE); -``` - -`mojo::Wait` is most typically useful in limited testing scenarios. - -### Waiting On Multiple Handles - -`mojo::WaitMany` provides a simple API to wait on multiple handles -simultaneously, returning when any handle's given signal mask is either -partially satisfied or fully unsatisfiable. - -``` cpp -mojo::MessagePipe a, b; -GoDoSomethingWithPipes(std:move(a.handle1), std::move(b.handle1)); - -mojo::MessagePipeHandle handles[2] = {a.handle0.get(), b.handle0.get()}; -MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; -size_t ready_index; -MojoResult result = mojo::WaitMany(handles, signals, 2, &ready_index); -if (ready_index == 0) { - // a.handle0 was ready. -} else { - // b.handle0 was ready. -} -``` - -Similar to `mojo::Wait`, `mojo::WaitMany` is primarily useful in testing. When -waiting on multiple handles in production code, you should almost always instead -use a more efficient and more flexible `mojo::WaitSet` as described in the next -section. - -### Waiting On Handles and Events Simultaneously - -Typically when waiting on one or more handles to signal, the set of handles and -conditions being waited upon do not change much between consecutive blocking -waits. It's also often useful to be able to interrupt the blocking operation -as efficiently as possible. - -[`mojo::WaitSet`](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/wait_set.h) -is designed with these conditions in mind. A `WaitSet` maintains a persistent -set of (not-owned) Mojo handles and `base::WaitableEvent`s, which may be -explicitly added to or removed from the set at any time. - -The `WaitSet` may be waited upon repeatedly, each time blocking the calling -thread until either one of the handles attains an interesting signaling state or -one of the events is signaled. For example let's suppose we want to wait up to 5 -seconds for either one of two handles to become readable: - -``` cpp -base::WaitableEvent timeout_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); -mojo::MessagePipe a, b; - -GoDoStuffWithPipes(std::move(a.handle1), std::move(b.handle1)); - -mojo::WaitSet wait_set; -wait_set.AddHandle(a.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); -wait_set.AddHandle(b.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); -wait_set.AddEvent(&timeout_event); - -// Ensure the Wait() lasts no more than 5 seconds. -bg_thread->task_runner()->PostDelayedTask( - FROM_HERE, - base::Bind([](base::WaitableEvent* e) { e->Signal(); }, &timeout_event); - base::TimeDelta::FromSeconds(5)); - -base::WaitableEvent* ready_event = nullptr; -size_t num_ready_handles = 1; -mojo::Handle ready_handle; -MojoResult ready_result; -wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); - -// The apex of thread-safety. -bg_thread->Stop(); - -if (ready_event) { - // The event signaled... -} - -if (num_ready_handles > 0) { - // At least one of the handles signaled... - // NOTE: This and the above condition are not mutually exclusive. If handle - // signaling races with timeout, both things might be true. -} -``` diff --git a/mojo/public/cpp/system/buffer.cc b/mojo/public/cpp/system/buffer.cc deleted file mode 100644 index 49f45d8..0000000 --- a/mojo/public/cpp/system/buffer.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/buffer.h" - -namespace mojo { - -// static -ScopedSharedBufferHandle SharedBufferHandle::Create(uint64_t num_bytes) { - MojoCreateSharedBufferOptions options = { - sizeof(options), MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; - SharedBufferHandle handle; - MojoCreateSharedBuffer(&options, num_bytes, handle.mutable_value()); - return MakeScopedHandle(handle); -} - -ScopedSharedBufferHandle SharedBufferHandle::Clone( - SharedBufferHandle::AccessMode access_mode) const { - ScopedSharedBufferHandle result; - if (!is_valid()) - return result; - - MojoDuplicateBufferHandleOptions options = { - sizeof(options), MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; - if (access_mode == AccessMode::READ_ONLY) - options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; - SharedBufferHandle result_handle; - MojoDuplicateBufferHandle(value(), &options, result_handle.mutable_value()); - result.reset(result_handle); - return result; -} - -ScopedSharedBufferMapping SharedBufferHandle::Map(uint64_t size) const { - return MapAtOffset(size, 0); -} - -ScopedSharedBufferMapping SharedBufferHandle::MapAtOffset( - uint64_t size, - uint64_t offset) const { - void* buffer = nullptr; - MojoMapBuffer(value(), offset, size, &buffer, MOJO_MAP_BUFFER_FLAG_NONE); - return ScopedSharedBufferMapping(buffer); -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/buffer.h b/mojo/public/cpp/system/buffer.h deleted file mode 100644 index 1ae923c..0000000 --- a/mojo/public/cpp/system/buffer.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a C++ wrapping around the Mojo C API for shared buffers, -// replacing the prefix of "Mojo" with a "mojo" namespace, and using more -// strongly-typed representations of |MojoHandle|s. -// -// Please see "mojo/public/c/system/buffer.h" for complete documentation of the -// API. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_BUFFER_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_BUFFER_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace mojo { -namespace internal { - -struct Unmapper { - void operator()(void* buffer) { - MojoResult result = MojoUnmapBuffer(buffer); - DCHECK_EQ(MOJO_RESULT_OK, result); - } -}; - -} // namespace internal - -using ScopedSharedBufferMapping = std::unique_ptr<void, internal::Unmapper>; - -class SharedBufferHandle; - -typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle; - -// A strongly-typed representation of a |MojoHandle| referring to a shared -// buffer. -class MOJO_CPP_SYSTEM_EXPORT SharedBufferHandle - : NON_EXPORTED_BASE(public Handle) { - public: - enum class AccessMode { - READ_WRITE, - READ_ONLY, - }; - - SharedBufferHandle() {} - explicit SharedBufferHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. - - // Creates a new SharedBufferHandle. Returns an invalid handle on failure. - static ScopedSharedBufferHandle Create(uint64_t num_bytes); - - // Clones this shared buffer handle. If |access_mode| is READ_ONLY or this is - // a read-only handle, the new handle will be read-only. On failure, this will - // return an empty result. - ScopedSharedBufferHandle Clone(AccessMode = AccessMode::READ_WRITE) const; - - // Maps |size| bytes of this shared buffer. On failure, this will return a - // null mapping. - ScopedSharedBufferMapping Map(uint64_t size) const; - - // Maps |size| bytes of this shared buffer, starting |offset| bytes into the - // buffer. On failure, this will return a null mapping. - ScopedSharedBufferMapping MapAtOffset(uint64_t size, uint64_t offset) const; -}; - -static_assert(sizeof(SharedBufferHandle) == sizeof(Handle), - "Bad size for C++ SharedBufferHandle"); -static_assert(sizeof(ScopedSharedBufferHandle) == sizeof(SharedBufferHandle), - "Bad size for C++ ScopedSharedBufferHandle"); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_BUFFER_H_ diff --git a/mojo/public/cpp/system/core.h b/mojo/public/cpp/system/core.h deleted file mode 100644 index f1d18d9..0000000 --- a/mojo/public/cpp/system/core.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ - -#include "mojo/public/cpp/system/buffer.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/cpp/system/functions.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/message_pipe.h" - -#endif // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ diff --git a/mojo/public/cpp/system/data_pipe.h b/mojo/public/cpp/system/data_pipe.h deleted file mode 100644 index 0dbc3c7..0000000 --- a/mojo/public/cpp/system/data_pipe.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a C++ wrapping around the Mojo C API for data pipes, -// replacing the prefix of "Mojo" with a "mojo" namespace, and using more -// strongly-typed representations of |MojoHandle|s. -// -// Please see "mojo/public/c/system/data_pipe.h" for complete documentation of -// the API. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { - -// A strongly-typed representation of a |MojoHandle| to the producer end of a -// data pipe. -class DataPipeProducerHandle : public Handle { - public: - DataPipeProducerHandle() {} - explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. -}; - -static_assert(sizeof(DataPipeProducerHandle) == sizeof(Handle), - "Bad size for C++ DataPipeProducerHandle"); - -typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle; -static_assert(sizeof(ScopedDataPipeProducerHandle) == - sizeof(DataPipeProducerHandle), - "Bad size for C++ ScopedDataPipeProducerHandle"); - -// A strongly-typed representation of a |MojoHandle| to the consumer end of a -// data pipe. -class DataPipeConsumerHandle : public Handle { - public: - DataPipeConsumerHandle() {} - explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. -}; - -static_assert(sizeof(DataPipeConsumerHandle) == sizeof(Handle), - "Bad size for C++ DataPipeConsumerHandle"); - -typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle; -static_assert(sizeof(ScopedDataPipeConsumerHandle) == - sizeof(DataPipeConsumerHandle), - "Bad size for C++ ScopedDataPipeConsumerHandle"); - -// Creates a new data pipe. See |MojoCreateDataPipe()| for complete -// documentation. -inline MojoResult CreateDataPipe( - const MojoCreateDataPipeOptions* options, - ScopedDataPipeProducerHandle* data_pipe_producer, - ScopedDataPipeConsumerHandle* data_pipe_consumer) { - DCHECK(data_pipe_producer); - DCHECK(data_pipe_consumer); - DataPipeProducerHandle producer_handle; - DataPipeConsumerHandle consumer_handle; - MojoResult rv = MojoCreateDataPipe(options, - producer_handle.mutable_value(), - consumer_handle.mutable_value()); - // Reset even on failure (reduces the chances that a "stale"/incorrect handle - // will be used). - data_pipe_producer->reset(producer_handle); - data_pipe_consumer->reset(consumer_handle); - return rv; -} - -// Writes to a data pipe. See |MojoWriteData| for complete documentation. -inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer, - const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) { - return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags); -} - -// Begins a two-phase write to a data pipe. See |MojoBeginWriteData()| for -// complete documentation. -inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer, - void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) { - return MojoBeginWriteData( - data_pipe_producer.value(), buffer, buffer_num_bytes, flags); -} - -// Completes a two-phase write to a data pipe. See |MojoEndWriteData()| for -// complete documentation. -inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer, - uint32_t num_bytes_written) { - return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written); -} - -// Reads from a data pipe. See |MojoReadData()| for complete documentation. -inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, - void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) { - return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags); -} - -// Begins a two-phase read from a data pipe. See |MojoBeginReadData()| for -// complete documentation. -inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, - const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) { - return MojoBeginReadData( - data_pipe_consumer.value(), buffer, buffer_num_bytes, flags); -} - -// Completes a two-phase read from a data pipe. See |MojoEndReadData()| for -// complete documentation. -inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, - uint32_t num_bytes_read) { - return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read); -} - -// A wrapper class that automatically creates a data pipe and owns both handles. -// TODO(vtl): Make an even more friendly version? (Maybe templatized for a -// particular type instead of some "element"? Maybe functions that take -// vectors?) -class DataPipe { - public: - DataPipe(); - explicit DataPipe(const MojoCreateDataPipeOptions& options); - ~DataPipe(); - - ScopedDataPipeProducerHandle producer_handle; - ScopedDataPipeConsumerHandle consumer_handle; -}; - -inline DataPipe::DataPipe() { - MojoResult result = - CreateDataPipe(nullptr, &producer_handle, &consumer_handle); - ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); -} - -inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) { - MojoResult result = - CreateDataPipe(&options, &producer_handle, &consumer_handle); - ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); -} - -inline DataPipe::~DataPipe() { -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_ diff --git a/mojo/public/cpp/system/functions.h b/mojo/public/cpp/system/functions.h deleted file mode 100644 index 31edf57..0000000 --- a/mojo/public/cpp/system/functions.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a C++ wrapping around the standalone functions of the Mojo -// C API, replacing the prefix of "Mojo" with a "mojo" namespace. -// -// Please see "mojo/public/c/system/functions.h" for complete documentation of -// the API. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_ - -#include "mojo/public/c/system/functions.h" - -namespace mojo { - -// Returns the current |MojoTimeTicks| value. See |MojoGetTimeTicksNow()| for -// complete documentation. -inline MojoTimeTicks GetTimeTicksNow() { - return MojoGetTimeTicksNow(); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_ diff --git a/mojo/public/cpp/system/handle.h b/mojo/public/cpp/system/handle.h deleted file mode 100644 index 781944e..0000000 --- a/mojo/public/cpp/system/handle.h +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ - -#include <stdint.h> -#include <limits> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/handle_signals_state.h" - -namespace mojo { - -// OVERVIEW -// -// |Handle| and |...Handle|: -// -// |Handle| is a simple, copyable wrapper for the C type |MojoHandle| (which is -// just an integer). Its purpose is to increase type-safety, not provide -// lifetime management. For the same purpose, we have trivial *subclasses* of -// |Handle|, e.g., |MessagePipeHandle| and |DataPipeProducerHandle|. |Handle| -// and its subclasses impose *no* extra overhead over using |MojoHandle|s -// directly. -// -// Note that though we provide constructors for |Handle|/|...Handle| from a -// |MojoHandle|, we do not provide, e.g., a constructor for |MessagePipeHandle| -// from a |Handle|. This is for type safety: If we did, you'd then be able to -// construct a |MessagePipeHandle| from, e.g., a |DataPipeProducerHandle| (since -// it's a |Handle|). -// -// |ScopedHandleBase| and |Scoped...Handle|: -// -// |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle -// types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped -// wrapper for a |T*|). It provides lifetime management, closing its owned -// handle on destruction. It also provides (emulated) move semantics, again -// along the lines of C++11's |unique_ptr| (and exactly like Chromium's -// |scoped_ptr|). -// -// |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|. -// Similarly, |ScopedMessagePipeHandle| is just a -// |ScopedHandleBase<MessagePipeHandle>|. Etc. Note that a -// |ScopedMessagePipeHandle| is *not* a (subclass of) |ScopedHandle|. -// -// Wrapper functions: -// -// We provide simple wrappers for the |Mojo...()| functions (in -// mojo/public/c/system/core.h -- see that file for details on individual -// functions). -// -// The general guideline is functions that imply ownership transfer of a handle -// should take (or produce) an appropriate |Scoped...Handle|, while those that -// don't take a |...Handle|. For example, |CreateMessagePipe()| has two -// |ScopedMessagePipe| "out" parameters, whereas |Wait()| and |WaitMany()| take -// |Handle| parameters. Some, have both: e.g., |DuplicatedBuffer()| takes a -// suitable (unscoped) handle (e.g., |SharedBufferHandle|) "in" parameter and -// produces a suitable scoped handle (e.g., |ScopedSharedBufferHandle| a.k.a. -// |ScopedHandleBase<SharedBufferHandle>|) as an "out" parameter. -// -// An exception are some of the |...Raw()| functions. E.g., |CloseRaw()| takes a -// |Handle|, leaving the user to discard the wrapper. -// -// ScopedHandleBase ------------------------------------------------------------ - -// Scoper for the actual handle types defined further below. It's move-only, -// like the C++11 |unique_ptr|. -template <class HandleType> -class ScopedHandleBase { - public: - using RawHandleType = HandleType; - - ScopedHandleBase() {} - explicit ScopedHandleBase(HandleType handle) : handle_(handle) {} - ~ScopedHandleBase() { CloseIfNecessary(); } - - template <class CompatibleHandleType> - explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other) - : handle_(other.release()) {} - - // Move-only constructor and operator=. - ScopedHandleBase(ScopedHandleBase&& other) : handle_(other.release()) {} - ScopedHandleBase& operator=(ScopedHandleBase&& other) { - if (&other != this) { - CloseIfNecessary(); - handle_ = other.release(); - } - return *this; - } - - const HandleType& get() const { return handle_; } - const HandleType* operator->() const { return &handle_; } - - template <typename PassedHandleType> - static ScopedHandleBase<HandleType> From( - ScopedHandleBase<PassedHandleType> other) { - static_assert( - sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))), - "HandleType is not a subtype of PassedHandleType"); - return ScopedHandleBase<HandleType>( - static_cast<HandleType>(other.release().value())); - } - - void swap(ScopedHandleBase& other) { handle_.swap(other.handle_); } - - HandleType release() WARN_UNUSED_RESULT { - HandleType rv; - rv.swap(handle_); - return rv; - } - - void reset(HandleType handle = HandleType()) { - CloseIfNecessary(); - handle_ = handle; - } - - bool is_valid() const { return handle_.is_valid(); } - - bool operator==(const ScopedHandleBase& other) const { - return handle_.value() == other.get().value(); - } - - private: - void CloseIfNecessary() { - if (handle_.is_valid()) - handle_.Close(); - } - - HandleType handle_; - - DISALLOW_COPY_AND_ASSIGN(ScopedHandleBase); -}; - -template <typename HandleType> -inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) { - return ScopedHandleBase<HandleType>(handle); -} - -// Handle ---------------------------------------------------------------------- - -const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID; - -// Wrapper base class for |MojoHandle|. -class Handle { - public: - Handle() : value_(kInvalidHandleValue) {} - explicit Handle(MojoHandle value) : value_(value) {} - ~Handle() {} - - void swap(Handle& other) { - MojoHandle temp = value_; - value_ = other.value_; - other.value_ = temp; - } - - bool is_valid() const { return value_ != kInvalidHandleValue; } - - const MojoHandle& value() const { return value_; } - MojoHandle* mutable_value() { return &value_; } - void set_value(MojoHandle value) { value_ = value; } - - void Close() { - DCHECK(is_valid()); - MojoResult result = MojoClose(value_); - ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); - } - - HandleSignalsState QuerySignalsState() const { - HandleSignalsState signals_state; - MojoResult result = MojoQueryHandleSignalsState( - value_, static_cast<MojoHandleSignalsState*>(&signals_state)); - DCHECK_EQ(MOJO_RESULT_OK, result); - return signals_state; - } - - private: - MojoHandle value_; - - // Copying and assignment allowed. -}; - -// Should have zero overhead. -static_assert(sizeof(Handle) == sizeof(MojoHandle), "Bad size for C++ Handle"); - -// The scoper should also impose no more overhead. -typedef ScopedHandleBase<Handle> ScopedHandle; -static_assert(sizeof(ScopedHandle) == sizeof(Handle), - "Bad size for C++ ScopedHandle"); - -// |Close()| takes ownership of the handle, since it'll invalidate it. -// Note: There's nothing to do, since the argument will be destroyed when it -// goes out of scope. -template <class HandleType> -inline void Close(ScopedHandleBase<HandleType> /*handle*/) { -} - -// Most users should typically use |Close()| (above) instead. -inline MojoResult CloseRaw(Handle handle) { - return MojoClose(handle.value()); -} - -// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, -inline bool operator<(const Handle a, const Handle b) { - return a.value() < b.value(); -} - -// Comparison, so that |Handle|s can be used as keys in hash maps. -inline bool operator==(const Handle a, const Handle b) { - return a.value() == b.value(); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ diff --git a/mojo/public/cpp/system/handle_signals_state.h b/mojo/public/cpp/system/handle_signals_state.h deleted file mode 100644 index 9e2430f..0000000 --- a/mojo/public/cpp/system/handle_signals_state.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_HANDLE_SIGNALS_STATE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_SIGNALS_STATE_H_ - -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace mojo { - -// A convenience wrapper around the MojoHandleSignalsState struct. -struct MOJO_CPP_SYSTEM_EXPORT HandleSignalsState final - : public MojoHandleSignalsState { - HandleSignalsState() { - satisfied_signals = MOJO_HANDLE_SIGNAL_NONE; - satisfiable_signals = MOJO_HANDLE_SIGNAL_NONE; - } - - HandleSignalsState(MojoHandleSignals satisfied, - MojoHandleSignals satisfiable) { - satisfied_signals = satisfied; - satisfiable_signals = satisfiable; - } - - bool operator==(const HandleSignalsState& other) const { - return satisfied_signals == other.satisfied_signals && - satisfiable_signals == other.satisfiable_signals; - } - - // TODO(rockot): Remove this in favor of operator==. - bool equals(const HandleSignalsState& other) const { - return satisfied_signals == other.satisfied_signals && - satisfiable_signals == other.satisfiable_signals; - } - - bool satisfies(MojoHandleSignals signals) const { - return !!(satisfied_signals & signals); - } - - bool can_satisfy(MojoHandleSignals signals) const { - return !!(satisfiable_signals & signals); - } - - // The handle is currently readable. May apply to a message pipe handle or - // data pipe consumer handle. - bool readable() const { return satisfies(MOJO_HANDLE_SIGNAL_READABLE); } - - // The handle is currently writable. May apply to a message pipe handle or - // data pipe producer handle. - bool writable() const { return satisfies(MOJO_HANDLE_SIGNAL_WRITABLE); } - - // The handle's peer is closed. May apply to any message pipe or data pipe - // handle. - bool peer_closed() const { return satisfies(MOJO_HANDLE_SIGNAL_PEER_CLOSED); } - - // The handle will never be |readable()| again. - bool never_readable() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_READABLE); - } - - // The handle will never be |writable()| again. - bool never_writable() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_WRITABLE); - } - - // The handle can never indicate |peer_closed()|. Never true for message pipe - // or data pipe handles (they can always signal peer closure), but always true - // for other types of handles (they have no peer.) - bool never_peer_closed() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_PEER_CLOSED); - } - - // (Copy and assignment allowed.) -}; - -static_assert(sizeof(HandleSignalsState) == sizeof(MojoHandleSignalsState), - "HandleSignalsState should add no overhead"); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_SIGNALS_STATE_H_ diff --git a/mojo/public/cpp/system/message.cc b/mojo/public/cpp/system/message.cc deleted file mode 100644 index 09d8d46..0000000 --- a/mojo/public/cpp/system/message.cc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/message.h" - -namespace mojo { - -ScopedMessageHandle::~ScopedMessageHandle() { - -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/message.h b/mojo/public/cpp/system/message.h deleted file mode 100644 index d4406ee..0000000 --- a/mojo/public/cpp/system/message.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ - -#include <limits> - -#include "base/macros.h" -#include "base/strings/string_piece.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { - -const MojoMessageHandle kInvalidMessageHandleValue = - MOJO_MESSAGE_HANDLE_INVALID; - -// Handle wrapper base class for a |MojoMessageHandle|. -class MessageHandle { - public: - MessageHandle() : value_(kInvalidMessageHandleValue) {} - explicit MessageHandle(MojoMessageHandle value) : value_(value) {} - ~MessageHandle() {} - - void swap(MessageHandle& other) { - MojoMessageHandle temp = value_; - value_ = other.value_; - other.value_ = temp; - } - - bool is_valid() const { return value_ != kInvalidMessageHandleValue; } - - const MojoMessageHandle& value() const { return value_; } - MojoMessageHandle* mutable_value() { return &value_; } - void set_value(MojoMessageHandle value) { value_ = value; } - - void Close() { - DCHECK(is_valid()); - MojoResult result = MojoFreeMessage(value_); - ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); - } - - private: - MojoMessageHandle value_; -}; - -using ScopedMessageHandle = ScopedHandleBase<MessageHandle>; - -inline MojoResult AllocMessage(size_t num_bytes, - const MojoHandle* handles, - size_t num_handles, - MojoAllocMessageFlags flags, - ScopedMessageHandle* handle) { - DCHECK_LE(num_bytes, std::numeric_limits<uint32_t>::max()); - DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max()); - MojoMessageHandle raw_handle; - MojoResult rv = MojoAllocMessage(static_cast<uint32_t>(num_bytes), handles, - static_cast<uint32_t>(num_handles), flags, - &raw_handle); - if (rv != MOJO_RESULT_OK) - return rv; - - handle->reset(MessageHandle(raw_handle)); - return MOJO_RESULT_OK; -} - -inline MojoResult GetMessageBuffer(MessageHandle message, void** buffer) { - DCHECK(message.is_valid()); - return MojoGetMessageBuffer(message.value(), buffer); -} - -inline MojoResult NotifyBadMessage(MessageHandle message, - const base::StringPiece& error) { - DCHECK(message.is_valid()); - return MojoNotifyBadMessage(message.value(), error.data(), error.size()); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_H_ diff --git a/mojo/public/cpp/system/message_pipe.h b/mojo/public/cpp/system/message_pipe.h deleted file mode 100644 index 7fbe43f..0000000 --- a/mojo/public/cpp/system/message_pipe.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a C++ wrapping around the Mojo C API for message pipes, -// replacing the prefix of "Mojo" with a "mojo" namespace, and using more -// strongly-typed representations of |MojoHandle|s. -// -// Please see "mojo/public/c/system/message_pipe.h" for complete documentation -// of the API. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_PIPE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_PIPE_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/message.h" - -namespace mojo { - -// A strongly-typed representation of a |MojoHandle| to one end of a message -// pipe. -class MessagePipeHandle : public Handle { - public: - MessagePipeHandle() {} - explicit MessagePipeHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. -}; - -static_assert(sizeof(MessagePipeHandle) == sizeof(Handle), - "Bad size for C++ MessagePipeHandle"); - -typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle; -static_assert(sizeof(ScopedMessagePipeHandle) == sizeof(MessagePipeHandle), - "Bad size for C++ ScopedMessagePipeHandle"); - -// Creates a message pipe. See |MojoCreateMessagePipe()| for complete -// documentation. -inline MojoResult CreateMessagePipe(const MojoCreateMessagePipeOptions* options, - ScopedMessagePipeHandle* message_pipe0, - ScopedMessagePipeHandle* message_pipe1) { - DCHECK(message_pipe0); - DCHECK(message_pipe1); - MessagePipeHandle handle0; - MessagePipeHandle handle1; - MojoResult rv = MojoCreateMessagePipe( - options, handle0.mutable_value(), handle1.mutable_value()); - // Reset even on failure (reduces the chances that a "stale"/incorrect handle - // will be used). - message_pipe0->reset(handle0); - message_pipe1->reset(handle1); - return rv; -} - -// The following "...Raw" versions fully expose the underlying API, and don't -// help with ownership of handles (especially when writing messages). It is -// expected that in most cases these methods will be called through generated -// bindings anyway. -// TODO(vtl): Write friendlier versions of these functions (using scoped -// handles and/or vectors) if there is a demonstrated need for them. - -// Writes to a message pipe. If handles are attached, on success the handles -// will no longer be valid (the receiver will receive equivalent, but logically -// different, handles). See |MojoWriteMessage()| for complete documentation. -inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - return MojoWriteMessage( - message_pipe.value(), bytes, num_bytes, handles, num_handles, flags); -} - -// Reads from a message pipe. See |MojoReadMessage()| for complete -// documentation. -inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - return MojoReadMessage( - message_pipe.value(), bytes, num_bytes, handles, num_handles, flags); -} - -// Writes to a message pipe. Takes ownership of |message| and any attached -// handles. -inline MojoResult WriteMessageNew(MessagePipeHandle message_pipe, - ScopedMessageHandle message, - MojoWriteMessageFlags flags) { - return MojoWriteMessageNew( - message_pipe.value(), message.release().value(), flags); -} - -// Reads from a message pipe. See |MojoReadMessageNew()| for complete -// documentation. -inline MojoResult ReadMessageNew(MessagePipeHandle message_pipe, - ScopedMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - MojoMessageHandle raw_message; - MojoResult rv = MojoReadMessageNew(message_pipe.value(), &raw_message, - num_bytes, handles, num_handles, flags); - if (rv != MOJO_RESULT_OK) - return rv; - - message->reset(MessageHandle(raw_message)); - return MOJO_RESULT_OK; -} - -// Fuses two message pipes together at the given handles. See -// |MojoFuseMessagePipes()| for complete documentation. -inline MojoResult FuseMessagePipes(ScopedMessagePipeHandle message_pipe0, - ScopedMessagePipeHandle message_pipe1) { - return MojoFuseMessagePipes(message_pipe0.release().value(), - message_pipe1.release().value()); -} - -// A wrapper class that automatically creates a message pipe and owns both -// handles. -class MessagePipe { - public: - MessagePipe(); - explicit MessagePipe(const MojoCreateMessagePipeOptions& options); - ~MessagePipe(); - - ScopedMessagePipeHandle handle0; - ScopedMessagePipeHandle handle1; -}; - -inline MessagePipe::MessagePipe() { - MojoResult result = CreateMessagePipe(nullptr, &handle0, &handle1); - DCHECK_EQ(MOJO_RESULT_OK, result); - DCHECK(handle0.is_valid()); - DCHECK(handle1.is_valid()); -} - -inline MessagePipe::MessagePipe(const MojoCreateMessagePipeOptions& options) { - MojoResult result = CreateMessagePipe(&options, &handle0, &handle1); - DCHECK_EQ(MOJO_RESULT_OK, result); - DCHECK(handle0.is_valid()); - DCHECK(handle1.is_valid()); -} - -inline MessagePipe::~MessagePipe() { -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_MESSAGE_PIPE_H_ diff --git a/mojo/public/cpp/system/platform_handle.cc b/mojo/public/cpp/system/platform_handle.cc deleted file mode 100644 index 42e4aba..0000000 --- a/mojo/public/cpp/system/platform_handle.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/platform_handle.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach.h> -#include "base/mac/mach_logging.h" -#endif - -namespace mojo { - -namespace { - -uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) { -#if defined(OS_WIN) - return reinterpret_cast<uint64_t>(file); -#else - return static_cast<uint64_t>(file); -#endif -} - -base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) { -#if defined(OS_WIN) - return reinterpret_cast<base::PlatformFile>(value); -#else - return static_cast<base::PlatformFile>(value); -#endif -} - -} // namespace - -ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) { - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - platform_handle.type = kPlatformFileHandleType; - platform_handle.value = PlatformHandleValueFromPlatformFile(platform_file); - - MojoHandle mojo_handle; - MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle); - CHECK_EQ(result, MOJO_RESULT_OK); - - return ScopedHandle(Handle(mojo_handle)); -} - -MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file) { - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - MojoResult result = MojoUnwrapPlatformHandle(handle.release().value(), - &platform_handle); - if (result != MOJO_RESULT_OK) - return result; - - if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) { - *file = base::kInvalidPlatformFile; - } else { - CHECK_EQ(platform_handle.type, kPlatformFileHandleType); - *file = PlatformFileFromPlatformHandleValue(platform_handle.value); - } - - return MOJO_RESULT_OK; -} - -ScopedSharedBufferHandle WrapSharedMemoryHandle( - const base::SharedMemoryHandle& memory_handle, - size_t size, - bool read_only) { -#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS)) - if (memory_handle.fd == base::kInvalidPlatformFile) - return ScopedSharedBufferHandle(); -#else - if (!memory_handle.IsValid()) - return ScopedSharedBufferHandle(); -#endif - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - platform_handle.type = kPlatformSharedBufferHandleType; -#if defined(OS_MACOSX) && !defined(OS_IOS) - platform_handle.value = - static_cast<uint64_t>(memory_handle.GetMemoryObject()); -#elif defined(OS_POSIX) - platform_handle.value = PlatformHandleValueFromPlatformFile(memory_handle.fd); -#elif defined(OS_WIN) - platform_handle.value = - PlatformHandleValueFromPlatformFile(memory_handle.GetHandle()); -#endif - - MojoPlatformSharedBufferHandleFlags flags = - MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; - if (read_only) - flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; - - MojoHandle mojo_handle; - MojoResult result = MojoWrapPlatformSharedBufferHandle( - &platform_handle, size, flags, &mojo_handle); - CHECK_EQ(result, MOJO_RESULT_OK); - - return ScopedSharedBufferHandle(SharedBufferHandle(mojo_handle)); -} - -MojoResult UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle, - base::SharedMemoryHandle* memory_handle, - size_t* size, - bool* read_only) { - if (!handle.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - - MojoPlatformSharedBufferHandleFlags flags; - size_t num_bytes; - MojoResult result = MojoUnwrapPlatformSharedBufferHandle( - handle.release().value(), &platform_handle, &num_bytes, &flags); - if (result != MOJO_RESULT_OK) - return result; - - if (size) - *size = num_bytes; - - if (read_only) - *read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT); - *memory_handle = base::SharedMemoryHandle( - static_cast<mach_port_t>(platform_handle.value), num_bytes, - base::GetCurrentProcId()); -#elif defined(OS_POSIX) - CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR); - *memory_handle = base::SharedMemoryHandle( - static_cast<int>(platform_handle.value), false); -#elif defined(OS_WIN) - CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE); - *memory_handle = base::SharedMemoryHandle( - reinterpret_cast<HANDLE>(platform_handle.value), - base::GetCurrentProcId()); -#endif - - return MOJO_RESULT_OK; -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -ScopedHandle WrapMachPort(mach_port_t port) { - kern_return_t kr = - mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, 1); - MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) - << "MachPortAttachmentMac mach_port_mod_refs"; - if (kr != KERN_SUCCESS) - return ScopedHandle(); - - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; - platform_handle.value = static_cast<uint64_t>(port); - - MojoHandle mojo_handle; - MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle); - CHECK_EQ(result, MOJO_RESULT_OK); - - return ScopedHandle(Handle(mojo_handle)); -} - -MojoResult UnwrapMachPort(ScopedHandle handle, mach_port_t* port) { - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - MojoResult result = - MojoUnwrapPlatformHandle(handle.release().value(), &platform_handle); - if (result != MOJO_RESULT_OK) - return result; - - CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT); - *port = static_cast<mach_port_t>(platform_handle.value); - return MOJO_RESULT_OK; -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -} // namespace mojo diff --git a/mojo/public/cpp/system/platform_handle.h b/mojo/public/cpp/system/platform_handle.h deleted file mode 100644 index 801264e..0000000 --- a/mojo/public/cpp/system/platform_handle.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a C++ wrapping around the Mojo C API for platform handles, -// replacing the prefix of "Mojo" with a "mojo" namespace. -// -// Please see "mojo/public/c/system/platform_handle.h" for complete -// documentation of the API. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_PLATFORM_HANDLE_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_PLATFORM_HANDLE_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/files/file.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/shared_memory_handle.h" -#include "base/process/process_handle.h" -#include "mojo/public/c/system/platform_handle.h" -#include "mojo/public/cpp/system/buffer.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace mojo { - -#if defined(OS_POSIX) -const MojoPlatformHandleType kPlatformFileHandleType = - MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; - -#if defined(OS_MACOSX) && !defined(OS_IOS) -const MojoPlatformHandleType kPlatformSharedBufferHandleType = - MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; -#else -const MojoPlatformHandleType kPlatformSharedBufferHandleType = - MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -#elif defined(OS_WIN) -const MojoPlatformHandleType kPlatformFileHandleType = - MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; - -const MojoPlatformHandleType kPlatformSharedBufferHandleType = - MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; -#endif // defined(OS_POSIX) - -// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object. -MOJO_CPP_SYSTEM_EXPORT -ScopedHandle WrapPlatformFile(base::PlatformFile platform_file); - -// Unwraps a PlatformFile from a Mojo handle. -MOJO_CPP_SYSTEM_EXPORT -MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file); - -// Wraps a base::SharedMemoryHandle as a Mojo handle. Takes ownership of the -// SharedMemoryHandle. Note that |read_only| is only an indicator of whether -// |memory_handle| only supports read-only mapping. It does NOT have any -// influence on the access control of the shared buffer object. -MOJO_CPP_SYSTEM_EXPORT -ScopedSharedBufferHandle WrapSharedMemoryHandle( - const base::SharedMemoryHandle& memory_handle, - size_t size, - bool read_only); - -// Unwraps a base::SharedMemoryHandle from a Mojo handle. The caller assumes -// responsibility for the lifetime of the SharedMemoryHandle. -MOJO_CPP_SYSTEM_EXPORT MojoResult -UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle, - base::SharedMemoryHandle* memory_handle, - size_t* size, - bool* read_only); - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// Wraps a mach_port_t as a Mojo handle. This takes a reference to the -// Mach port. -MOJO_CPP_SYSTEM_EXPORT ScopedHandle WrapMachPort(mach_port_t port); - -// Unwraps a mach_port_t from a Mojo handle. The caller gets ownership of the -// Mach port. -MOJO_CPP_SYSTEM_EXPORT MojoResult UnwrapMachPort(ScopedHandle handle, - mach_port_t* port); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_PLATFORM_HANDLE_H_ diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc deleted file mode 100644 index ae96faa..0000000 --- a/mojo/public/cpp/system/simple_watcher.cc +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/simple_watcher.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/trace_event/heap_profiler.h" -#include "mojo/public/c/system/watcher.h" - -namespace mojo { - -// Thread-safe Context object used to dispatch watch notifications from a -// arbitrary threads. -class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> { - public: - // Creates a |Context| instance for a new watch on |watcher|, to watch - // |handle| for |signals|. - static scoped_refptr<Context> Create( - base::WeakPtr<SimpleWatcher> watcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - WatcherHandle watcher_handle, - Handle handle, - MojoHandleSignals signals, - int watch_id, - MojoResult* watch_result) { - scoped_refptr<Context> context = - new Context(watcher, task_runner, watch_id); - - // If MojoWatch succeeds, it assumes ownership of a reference to |context|. - // In that case, this reference is balanced in CallNotify() when |result| is - // |MOJO_RESULT_CANCELLED|. - context->AddRef(); - - *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals, - context->value()); - if (*watch_result != MOJO_RESULT_OK) { - // Balanced by the AddRef() above since watching failed. - context->Release(); - return nullptr; - } - - return context; - } - - static void CallNotify(uintptr_t context_value, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - auto* context = reinterpret_cast<Context*>(context_value); - context->Notify(result, signals_state, flags); - - // That was the last notification for the context. We can release the ref - // owned by the watch, which may in turn delete the Context. - if (result == MOJO_RESULT_CANCELLED) - context->Release(); - } - - uintptr_t value() const { return reinterpret_cast<uintptr_t>(this); } - - void DisableCancellationNotifications() { - base::AutoLock lock(lock_); - enable_cancellation_notifications_ = false; - } - - private: - friend class base::RefCountedThreadSafe<Context>; - - Context(base::WeakPtr<SimpleWatcher> weak_watcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - int watch_id) - : weak_watcher_(weak_watcher), - task_runner_(task_runner), - watch_id_(watch_id) {} - ~Context() {} - - void Notify(MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - if (result == MOJO_RESULT_CANCELLED) { - // The SimpleWatcher may have explicitly cancelled this watch, so we don't - // bother dispatching the notification - it would be ignored anyway. - // - // TODO(rockot): This shouldn't really be necessary, but there are already - // instances today where bindings object may be bound and subsequently - // closed due to pipe error, all before the thread's TaskRunner has been - // properly initialized. - base::AutoLock lock(lock_); - if (!enable_cancellation_notifications_) - return; - } - - if ((flags & MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM) && - task_runner_->RunsTasksOnCurrentThread() && weak_watcher_ && - weak_watcher_->is_default_task_runner_) { - // System notifications will trigger from the task runner passed to - // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the - // default task runner for the IO thread. - weak_watcher_->OnHandleReady(watch_id_, result); - } else { - task_runner_->PostTask( - FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, weak_watcher_, - watch_id_, result)); - } - } - - const base::WeakPtr<SimpleWatcher> weak_watcher_; - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - const int watch_id_; - - base::Lock lock_; - bool enable_cancellation_notifications_ = true; - - DISALLOW_COPY_AND_ASSIGN(Context); -}; - -SimpleWatcher::SimpleWatcher(const tracked_objects::Location& from_here, - ArmingPolicy arming_policy, - scoped_refptr<base::SingleThreadTaskRunner> runner) - : arming_policy_(arming_policy), - task_runner_(std::move(runner)), - is_default_task_runner_(task_runner_ == - base::ThreadTaskRunnerHandle::Get()), - heap_profiler_tag_(from_here.file_name()), - weak_factory_(this) { - MojoResult rv = CreateWatcher(&Context::CallNotify, &watcher_handle_); - DCHECK_EQ(MOJO_RESULT_OK, rv); - DCHECK(task_runner_->BelongsToCurrentThread()); -} - -SimpleWatcher::~SimpleWatcher() { - if (IsWatching()) - Cancel(); -} - -bool SimpleWatcher::IsWatching() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return context_ != nullptr; -} - -MojoResult SimpleWatcher::Watch(Handle handle, - MojoHandleSignals signals, - const ReadyCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!IsWatching()); - DCHECK(!callback.is_null()); - - callback_ = callback; - handle_ = handle; - watch_id_ += 1; - - MojoResult watch_result = MOJO_RESULT_UNKNOWN; - context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_, - watcher_handle_.get(), handle_, signals, watch_id_, - &watch_result); - if (!context_) { - handle_.set_value(kInvalidHandleValue); - callback_.Reset(); - DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, watch_result); - return watch_result; - } - - if (arming_policy_ == ArmingPolicy::AUTOMATIC) - ArmOrNotify(); - - return MOJO_RESULT_OK; -} - -void SimpleWatcher::Cancel() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // The watcher may have already been cancelled if the handle was closed. - if (!context_) - return; - - // Prevent the cancellation notification from being dispatched to - // OnHandleReady() when cancellation is explicit. See the note in the - // implementation of DisableCancellationNotifications() above. - context_->DisableCancellationNotifications(); - - handle_.set_value(kInvalidHandleValue); - callback_.Reset(); - - // Ensure |context_| is unset by the time we call MojoCancelWatch, as may - // re-enter the notification callback and we want to ensure |context_| is - // unset by then. - scoped_refptr<Context> context; - std::swap(context, context_); - MojoResult rv = - MojoCancelWatch(watcher_handle_.get().value(), context->value()); - - // It's possible this cancellation could race with a handle closure - // notification, in which case the watch may have already been implicitly - // cancelled. - DCHECK(rv == MOJO_RESULT_OK || rv == MOJO_RESULT_NOT_FOUND); -} - -MojoResult SimpleWatcher::Arm(MojoResult* ready_result) { - DCHECK(thread_checker_.CalledOnValidThread()); - uint32_t num_ready_contexts = 1; - uintptr_t ready_context; - MojoResult local_ready_result; - MojoHandleSignalsState ready_state; - MojoResult rv = - MojoArmWatcher(watcher_handle_.get().value(), &num_ready_contexts, - &ready_context, &local_ready_result, &ready_state); - if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - DCHECK(context_); - DCHECK_EQ(1u, num_ready_contexts); - DCHECK_EQ(context_->value(), ready_context); - if (ready_result) - *ready_result = local_ready_result; - } - - return rv; -} - -void SimpleWatcher::ArmOrNotify() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Already cancelled, nothing to do. - if (!IsWatching()) - return; - - MojoResult ready_result; - MojoResult rv = Arm(&ready_result); - if (rv == MOJO_RESULT_OK) - return; - - DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); - task_runner_->PostTask(FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, - weak_factory_.GetWeakPtr(), - watch_id_, ready_result)); -} - -void SimpleWatcher::OnHandleReady(int watch_id, MojoResult result) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // This notification may be for a previously watched context, in which case - // we just ignore it. - if (watch_id != watch_id_) - return; - - ReadyCallback callback = callback_; - if (result == MOJO_RESULT_CANCELLED) { - // Implicit cancellation due to someone closing the watched handle. We clear - // the SimppleWatcher's state before dispatching this. - context_ = nullptr; - handle_.set_value(kInvalidHandleValue); - callback_.Reset(); - } - - // NOTE: It's legal for |callback| to delete |this|. - if (!callback.is_null()) { - TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event(heap_profiler_tag_); - - base::WeakPtr<SimpleWatcher> weak_self = weak_factory_.GetWeakPtr(); - callback.Run(result); - if (!weak_self) - return; - - if (unsatisfiable_) - return; - - // Prevent |MOJO_RESULT_FAILED_PRECONDITION| task spam by only notifying - // at most once in AUTOMATIC arming mode. - if (result == MOJO_RESULT_FAILED_PRECONDITION) - unsatisfiable_ = true; - - if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching()) - ArmOrNotify(); - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h deleted file mode 100644 index 9001884..0000000 --- a/mojo/public/cpp/system/simple_watcher.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_SIMPLE_WATCHER_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_SIMPLE_WATCHER_H_ - -#include "base/callback.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/system_export.h" -#include "mojo/public/cpp/system/watcher.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace mojo { - -// This provides a convenient thread-bound watcher implementation to safely -// watch a single handle, dispatching state change notifications to an arbitrary -// SingleThreadTaskRunner running on the same thread as the SimpleWatcher. -// -// SimpleWatcher exposes the concept of "arming" from the low-level Watcher API. -// In general, a SimpleWatcher must be "armed" in order to dispatch a single -// notification, and must then be rearmed before it will dispatch another. For -// more details, see the documentation for ArmingPolicy and the Arm() and -// ArmOrNotify() methods below. -class MOJO_CPP_SYSTEM_EXPORT SimpleWatcher { - public: - // A callback to be called any time a watched handle changes state in some - // interesting way. The |result| argument indicates one of the following - // conditions depending on its value: - // - // |MOJO_RESULT_OK|: One or more of the signals being watched is satisfied. - // - // |MOJO_RESULT_FAILED_PRECONDITION|: None of the signals being watched can - // ever be satisfied again. - // - // |MOJO_RESULT_CANCELLED|: The watched handle has been closed. No further - // notifications will be fired, as this equivalent to an implicit - // CancelWatch(). - // - // Note that unlike the first two conditions, this callback may be invoked - // with |MOJO_RESULT_CANCELLED| even while the SimpleWatcher is disarmed. - using ReadyCallback = base::Callback<void(MojoResult result)>; - - // Selects how this SimpleWatcher is to be armed. - enum class ArmingPolicy { - // The SimpleWatcher is armed automatically on Watch() and rearmed again - // after every invocation of the ReadyCallback. There is no need to manually - // call Arm() on a SimpleWatcher using this policy. This mode is equivalent - // to calling ArmOrNotify() once after Watch() and once again after every - // dispatched notification in MANUAL mode. - // - // This provides a reasonable approximation of edge-triggered behavior, - // mitigating (but not completely eliminating) the potential for redundant - // notifications. - // - // NOTE: It is important when using AUTOMATIC policy that your ReadyCallback - // always attempt to change the state of the handle (e.g. read available - // messages on a message pipe.) Otherwise this will result in a potentially - // large number of avoidable redundant tasks. - // - // For perfect edge-triggered behavior, use MANUAL policy and manually Arm() - // the SimpleWatcher as soon as it becomes possible to do so again. - AUTOMATIC, - - // The SimpleWatcher is never armed automatically. Arm() or ArmOrNotify() - // must be called manually before any non-cancellation notification can be - // dispatched to the ReadyCallback. See the documentation for Arm() and - // ArmNotify() methods below for more details. - MANUAL, - }; - - SimpleWatcher(const tracked_objects::Location& from_here, - ArmingPolicy arming_policy, - scoped_refptr<base::SingleThreadTaskRunner> runner = - base::ThreadTaskRunnerHandle::Get()); - ~SimpleWatcher(); - - // Indicates if the SimpleWatcher is currently watching a handle. - bool IsWatching() const; - - // Starts watching |handle|. A SimpleWatcher may only watch one handle at a - // time, but it is safe to call this more than once as long as the previous - // watch has been cancelled (i.e. |IsWatching()| returns |false|.) - // - // If |handle| is not a valid watchable (message or data pipe) handle or - // |signals| is not a valid set of signals to watch, this returns - // |MOJO_RESULT_INVALID_ARGUMENT|. - // - // Otherwise |MOJO_RESULT_OK| is returned and the handle will be watched until - // either |handle| is closed, the SimpleWatcher is destroyed, or Cancel() is - // explicitly called. - // - // Once the watch is started, |callback| may be called at any time on the - // current thread until |Cancel()| is called or the handle is closed. Note - // that |callback| can be called for results other than - // |MOJO_RESULT_CANCELLED| only if the SimpleWatcher is currently armed. Use - // ArmingPolicy to configure how a SimpleWatcher is armed. - // - // |MOJO_RESULT_CANCELLED| may be dispatched even while the SimpleWatcher - // is disarmed, and no further notifications will be dispatched after that. - // - // Destroying the SimpleWatcher implicitly calls |Cancel()|. - MojoResult Watch(Handle handle, - MojoHandleSignals signals, - const ReadyCallback& callback); - - // Cancels the current watch. Once this returns, the ReadyCallback previously - // passed to |Watch()| will never be called again for this SimpleWatcher. - // - // Note that when cancelled with an explicit call to |Cancel()| the - // ReadyCallback will not be invoked with a |MOJO_RESULT_CANCELLED| result. - void Cancel(); - - // Manually arms the SimpleWatcher. - // - // Arming the SimpleWatcher allows it to fire a single notification regarding - // some future relevant change in the watched handle's state. It's only valid - // to call Arm() while a handle is being watched (see Watch() above.) - // - // SimpleWatcher is always disarmed immediately before invoking its - // ReadyCallback and must be rearmed again before another notification can - // fire. - // - // If the watched handle already meets the watched signaling conditions - - // i.e., if it would have notified immediately once armed - the SimpleWatcher - // is NOT armed, and this call fails with a return value of - // |MOJO_RESULT_FAILED_PRECONDITION|. In that case, what would have been the - // result code for that immediate notification is instead placed in - // |*ready_result| if |ready_result| is non-null. - // - // If the watcher is successfully armed, this returns |MOJO_RESULT_OK| and - // |ready_result| is ignored. - MojoResult Arm(MojoResult* ready_result = nullptr); - - // Manually arms the SimpleWatcher OR posts a task to invoke the ReadyCallback - // with the ready result of the failed arming attempt. - // - // This is meant as a convenient helper for a common usage of Arm(), and it - // ensures that the ReadyCallback will be invoked asynchronously again as soon - // as the watch's conditions are satisfied, assuming the SimpleWatcher isn't - // cancelled first. - // - // Unlike Arm() above, this can never fail. - void ArmOrNotify(); - - Handle handle() const { return handle_; } - ReadyCallback ready_callback() const { return callback_; } - - // Sets the tag used by the heap profiler. - // |tag| must be a const string literal. - void set_heap_profiler_tag(const char* heap_profiler_tag) { - heap_profiler_tag_ = heap_profiler_tag; - } - - private: - class Context; - - void OnHandleReady(int watch_id, MojoResult result); - - base::ThreadChecker thread_checker_; - - // The policy used to determine how this SimpleWatcher is armed. - const ArmingPolicy arming_policy_; - - // The TaskRunner of this SimpleWatcher's owning thread. This field is safe to - // access from any thread. - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - // Whether |task_runner_| is the same as base::ThreadTaskRunnerHandle::Get() - // for the thread. - const bool is_default_task_runner_; - - ScopedWatcherHandle watcher_handle_; - - // A thread-safe context object corresponding to the currently active watch, - // if any. - scoped_refptr<Context> context_; - - // Fields below must only be accessed on the SimpleWatcher's owning thread. - - // The handle currently under watch. Not owned. - Handle handle_; - - // A simple counter to disambiguate notifications from multiple watch contexts - // in the event that this SimpleWatcher cancels and watches multiple times. - int watch_id_ = 0; - - // The callback to call when the handle is signaled. - ReadyCallback callback_; - - // Tracks if the SimpleWatcher has already notified of unsatisfiability. This - // is used to prevent redundant notifications in AUTOMATIC mode. - bool unsatisfiable_ = false; - - // Tag used to ID memory allocations that originated from notifications in - // this watcher. - const char* heap_profiler_tag_ = nullptr; - - base::WeakPtrFactory<SimpleWatcher> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SimpleWatcher); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_SIMPLE_WATCHER_H_ diff --git a/mojo/public/cpp/system/system_export.h b/mojo/public/cpp/system/system_export.h deleted file mode 100644 index c9bb140..0000000 --- a/mojo/public/cpp/system/system_export.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_SYSTEM_EXPORT_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_SYSTEM_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(MOJO_CPP_SYSTEM_IMPLEMENTATION) -#define MOJO_CPP_SYSTEM_EXPORT __declspec(dllexport) -#else -#define MOJO_CPP_SYSTEM_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_CPP_SYSTEM_IMPLEMENTATION) -#define MOJO_CPP_SYSTEM_EXPORT __attribute((visibility("default"))) -#else -#define MOJO_CPP_SYSTEM_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) - -#define MOJO_CPP_SYSTEM_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // MOJO_PUBLIC_CPP_SYSTEM_SYSTEM_EXPORT_H_ diff --git a/mojo/public/cpp/system/tests/BUILD.gn b/mojo/public/cpp/system/tests/BUILD.gn deleted file mode 100644 index 705d009..0000000 --- a/mojo/public/cpp/system/tests/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("tests") { - testonly = true - - sources = [ - "core_unittest.cc", - "handle_signals_state_unittest.cc", - "simple_watcher_unittest.cc", - "wait_set_unittest.cc", - "wait_unittest.cc", - ] - - deps = [ - "//base", - "//mojo/public/c/system/tests", - "//mojo/public/cpp/system", - "//mojo/public/cpp/test_support:test_utils", - "//testing/gtest", - ] -} diff --git a/mojo/public/cpp/system/tests/core_unittest.cc b/mojo/public/cpp/system/tests/core_unittest.cc deleted file mode 100644 index 40a94f0..0000000 --- a/mojo/public/cpp/system/tests/core_unittest.cc +++ /dev/null @@ -1,510 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file tests the C++ Mojo system core wrappers. -// TODO(vtl): Maybe rename "CoreCppTest" -> "CoreTest" if/when this gets -// compiled into a different binary from the C API tests. - -#include "mojo/public/cpp/system/core.h" - -#include <stddef.h> -#include <stdint.h> -#include <map> -#include <utility> - -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -const MojoHandleSignals kSignalReadableWritable = - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; - -const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -TEST(CoreCppTest, GetTimeTicksNow) { - const MojoTimeTicks start = GetTimeTicksNow(); - EXPECT_NE(static_cast<MojoTimeTicks>(0), start) - << "GetTimeTicksNow should return nonzero value"; -} - -TEST(CoreCppTest, Basic) { - // Basic |Handle| implementation: - { - EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue); - - Handle h0; - EXPECT_EQ(kInvalidHandleValue, h0.value()); - EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value()); - EXPECT_FALSE(h0.is_valid()); - - Handle h1(static_cast<MojoHandle>(123)); - EXPECT_EQ(static_cast<MojoHandle>(123), h1.value()); - EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value()); - EXPECT_TRUE(h1.is_valid()); - *h1.mutable_value() = static_cast<MojoHandle>(456); - EXPECT_EQ(static_cast<MojoHandle>(456), h1.value()); - EXPECT_TRUE(h1.is_valid()); - - h1.swap(h0); - EXPECT_EQ(static_cast<MojoHandle>(456), h0.value()); - EXPECT_TRUE(h0.is_valid()); - EXPECT_FALSE(h1.is_valid()); - - h1.set_value(static_cast<MojoHandle>(789)); - h0.swap(h1); - EXPECT_EQ(static_cast<MojoHandle>(789), h0.value()); - EXPECT_TRUE(h0.is_valid()); - EXPECT_EQ(static_cast<MojoHandle>(456), h1.value()); - EXPECT_TRUE(h1.is_valid()); - - // Make sure copy constructor works. - Handle h2(h0); - EXPECT_EQ(static_cast<MojoHandle>(789), h2.value()); - // And assignment. - h2 = h1; - EXPECT_EQ(static_cast<MojoHandle>(456), h2.value()); - - // Make sure that we can put |Handle|s into |std::map|s. - h0 = Handle(static_cast<MojoHandle>(987)); - h1 = Handle(static_cast<MojoHandle>(654)); - h2 = Handle(static_cast<MojoHandle>(321)); - Handle h3; - std::map<Handle, int> handle_to_int; - handle_to_int[h0] = 0; - handle_to_int[h1] = 1; - handle_to_int[h2] = 2; - handle_to_int[h3] = 3; - - EXPECT_EQ(4u, handle_to_int.size()); - EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end()); - EXPECT_EQ(0, handle_to_int[h0]); - EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end()); - EXPECT_EQ(1, handle_to_int[h1]); - EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end()); - EXPECT_EQ(2, handle_to_int[h2]); - EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end()); - EXPECT_EQ(3, handle_to_int[h3]); - EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) == - handle_to_int.end()); - - // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out - // how to support the variations of |hash_map|.) - } - - // |Handle|/|ScopedHandle| functions: - { - ScopedHandle h; - - EXPECT_EQ(kInvalidHandleValue, h.get().value()); - - // This should be a no-op. - Close(std::move(h)); - - // It should still be invalid. - EXPECT_EQ(kInvalidHandleValue, h.get().value()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - Wait(h.get(), ~MOJO_HANDLE_SIGNAL_NONE)); - - std::vector<Handle> wh; - wh.push_back(h.get()); - std::vector<MojoHandleSignals> sigs; - sigs.push_back(~MOJO_HANDLE_SIGNAL_NONE); - size_t result_index; - MojoResult rv = WaitMany(wh.data(), sigs.data(), wh.size(), &result_index); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, rv); - } - - // |MakeScopedHandle| (just compilation tests): - { - EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid()); - EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid()); - EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid()); - EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid()); - EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid()); - } - - // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions: - { - MessagePipeHandle h_invalid; - EXPECT_FALSE(h_invalid.is_valid()); - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - WriteMessageRaw( - h_invalid, nullptr, 0, nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - char buffer[10] = {0}; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - WriteMessageRaw(h_invalid, - buffer, - sizeof(buffer), - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - ReadMessageRaw(h_invalid, - nullptr, - nullptr, - nullptr, - nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - ReadMessageRaw(h_invalid, - buffer, - &buffer_size, - nullptr, - nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Basic tests of waiting and closing. - MojoHandle hv0 = kInvalidHandleValue; - { - ScopedMessagePipeHandle h0; - ScopedMessagePipeHandle h1; - EXPECT_FALSE(h0.get().is_valid()); - EXPECT_FALSE(h1.get().is_valid()); - - CreateMessagePipe(nullptr, &h0, &h1); - EXPECT_TRUE(h0.get().is_valid()); - EXPECT_TRUE(h1.get().is_valid()); - EXPECT_NE(h0.get().value(), h1.get().value()); - // Save the handle values, so we can check that things got closed - // correctly. - hv0 = h0.get().value(); - MojoHandle hv1 = h1.get().value(); - MojoHandleSignalsState state = h0->QuerySignalsState(); - - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - std::vector<Handle> wh; - wh.push_back(h0.get()); - wh.push_back(h1.get()); - std::vector<MojoHandleSignals> sigs; - sigs.push_back(MOJO_HANDLE_SIGNAL_READABLE); - sigs.push_back(MOJO_HANDLE_SIGNAL_WRITABLE); - std::vector<MojoHandleSignalsState> states(sigs.size()); - - size_t result_index; - MojoResult rv = WaitMany(wh.data(), sigs.data(), wh.size(), &result_index, - states.data()); - EXPECT_EQ(MOJO_RESULT_OK, rv); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals); - EXPECT_EQ(kSignalAll, states[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[1].satisfied_signals); - EXPECT_EQ(kSignalAll, states[1].satisfiable_signals); - - // Test closing |h1| explicitly. - Close(std::move(h1)); - EXPECT_FALSE(h1.get().is_valid()); - - // Make sure |h1| is closed. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - Wait(Handle(hv1), ~MOJO_HANDLE_SIGNAL_NONE)); - - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, &state)); - - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - } - // |hv0| should have been closed when |h0| went out of scope, so this close - // should fail. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); - - // Actually test writing/reading messages. - { - ScopedMessagePipeHandle h0; - ScopedMessagePipeHandle h1; - CreateMessagePipe(nullptr, &h0, &h1); - - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h0.get(), - kHello, - kHelloSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, - Wait(h1.get(), MOJO_HANDLE_SIGNAL_READABLE, &state)); - EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - char buffer[10] = {0}; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(h1.get(), - buffer, - &buffer_size, - nullptr, - nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, buffer_size); - EXPECT_STREQ(kHello, buffer); - - // Send a handle over the previously-establish message pipe. Use the - // |MessagePipe| wrapper (to test it), which automatically creates a - // message pipe. - MessagePipe mp; - - // Write a message to |mp.handle0|, before we send |mp.handle1|. - const char kWorld[] = "world!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(mp.handle0.get(), - kWorld, - kWorldSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Send |mp.handle1| over |h1| to |h0|. - MojoHandle handles[5]; - handles[0] = mp.handle1.release().value(); - EXPECT_NE(kInvalidHandleValue, handles[0]); - EXPECT_FALSE(mp.handle1.get().is_valid()); - uint32_t handles_count = 1; - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h1.get(), - kHello, - kHelloSize, - handles, - handles_count, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - // |handles[0]| should actually be invalid now. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0])); - - // Read "hello" and the sent handle. - EXPECT_EQ(MOJO_RESULT_OK, - Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, &state)); - EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - memset(buffer, 0, sizeof(buffer)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - for (size_t i = 0; i < arraysize(handles); i++) - handles[i] = kInvalidHandleValue; - handles_count = static_cast<uint32_t>(arraysize(handles)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(h0.get(), - buffer, - &buffer_size, - handles, - &handles_count, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, buffer_size); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(1u, handles_count); - EXPECT_NE(kInvalidHandleValue, handles[0]); - - // Read from the sent/received handle. - mp.handle1.reset(MessagePipeHandle(handles[0])); - // Save |handles[0]| to check that it gets properly closed. - hv0 = handles[0]; - - EXPECT_EQ(MOJO_RESULT_OK, - Wait(mp.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &state)); - EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - memset(buffer, 0, sizeof(buffer)); - buffer_size = static_cast<uint32_t>(sizeof(buffer)); - for (size_t i = 0; i < arraysize(handles); i++) - handles[i] = kInvalidHandleValue; - handles_count = static_cast<uint32_t>(arraysize(handles)); - EXPECT_EQ(MOJO_RESULT_OK, - ReadMessageRaw(mp.handle1.get(), - buffer, - &buffer_size, - handles, - &handles_count, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, buffer_size); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(0u, handles_count); - } - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); - } - - // TODO(vtl): Test |CloseRaw()|. - // TODO(vtl): Test |reset()| more thoroughly? -} - -TEST(CoreCppTest, TearDownWithMessagesEnqueued) { - // Tear down a message pipe which still has a message enqueued, with the - // message also having a valid message pipe handle. - { - ScopedMessagePipeHandle h0; - ScopedMessagePipeHandle h1; - CreateMessagePipe(nullptr, &h0, &h1); - - // Send a handle over the previously-establish message pipe. - ScopedMessagePipeHandle h2; - ScopedMessagePipeHandle h3; - if (CreateMessagePipe(nullptr, &h2, &h3) != MOJO_RESULT_OK) - CreateMessagePipe(nullptr, &h2, &h3); // Must be old EDK. - - // Write a message to |h2|, before we send |h3|. - const char kWorld[] = "world!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h2.get(), - kWorld, - kWorldSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - // And also a message to |h3|. - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h3.get(), - kWorld, - kWorldSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Send |h3| over |h1| to |h0|. - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - MojoHandle h3_value; - h3_value = h3.release().value(); - EXPECT_NE(kInvalidHandleValue, h3_value); - EXPECT_FALSE(h3.get().is_valid()); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h1.get(), - kHello, - kHelloSize, - &h3_value, - 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - // |h3_value| should actually be invalid now. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); - } - - // Do this in a different order: make the enqueued message pipe handle only - // half-alive. - { - ScopedMessagePipeHandle h0; - ScopedMessagePipeHandle h1; - CreateMessagePipe(nullptr, &h0, &h1); - - // Send a handle over the previously-establish message pipe. - ScopedMessagePipeHandle h2; - ScopedMessagePipeHandle h3; - if (CreateMessagePipe(nullptr, &h2, &h3) != MOJO_RESULT_OK) - CreateMessagePipe(nullptr, &h2, &h3); // Must be old EDK. - - // Write a message to |h2|, before we send |h3|. - const char kWorld[] = "world!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h2.get(), - kWorld, - kWorldSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - // And also a message to |h3|. - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h3.get(), - kWorld, - kWorldSize, - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Send |h3| over |h1| to |h0|. - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - MojoHandle h3_value; - h3_value = h3.release().value(); - EXPECT_NE(kInvalidHandleValue, h3_value); - EXPECT_FALSE(h3.get().is_valid()); - EXPECT_EQ(MOJO_RESULT_OK, - WriteMessageRaw(h1.get(), - kHello, - kHelloSize, - &h3_value, - 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - // |h3_value| should actually be invalid now. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); - } -} - -TEST(CoreCppTest, ScopedHandleMoveCtor) { - ScopedSharedBufferHandle buffer1 = SharedBufferHandle::Create(1024); - EXPECT_TRUE(buffer1.is_valid()); - - ScopedSharedBufferHandle buffer2 = SharedBufferHandle::Create(1024); - EXPECT_TRUE(buffer2.is_valid()); - - // If this fails to close buffer1, ScopedHandleBase::CloseIfNecessary() will - // assert. - buffer1 = std::move(buffer2); - - EXPECT_TRUE(buffer1.is_valid()); - EXPECT_FALSE(buffer2.is_valid()); -} - -TEST(CoreCppTest, BasicSharedBuffer) { - ScopedSharedBufferHandle h0 = SharedBufferHandle::Create(100); - ASSERT_TRUE(h0.is_valid()); - - // Map everything. - ScopedSharedBufferMapping mapping = h0->Map(100); - ASSERT_TRUE(mapping); - static_cast<char*>(mapping.get())[50] = 'x'; - - // Duplicate |h0| to |h1|. - ScopedSharedBufferHandle h1 = - h0->Clone(SharedBufferHandle::AccessMode::READ_ONLY); - ASSERT_TRUE(h1.is_valid()); - - // Close |h0|. - h0.reset(); - - // The mapping should still be good. - static_cast<char*>(mapping.get())[51] = 'y'; - - // Unmap it. - mapping.reset(); - - // Map half of |h1|. - mapping = h1->MapAtOffset(50, 50); - ASSERT_TRUE(mapping); - - // It should have what we wrote. - EXPECT_EQ('x', static_cast<char*>(mapping.get())[0]); - EXPECT_EQ('y', static_cast<char*>(mapping.get())[1]); - - // Unmap it. - mapping.reset(); - h1.reset(); - - // Creating a 1 EB shared buffer should fail without crashing. - EXPECT_FALSE(SharedBufferHandle::Create(1ULL << 60).is_valid()); -} - -// TODO(vtl): Write data pipe tests. - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/system/tests/handle_signals_state_unittest.cc b/mojo/public/cpp/system/tests/handle_signals_state_unittest.cc deleted file mode 100644 index 82f538e..0000000 --- a/mojo/public/cpp/system/tests/handle_signals_state_unittest.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/handle_signals_state.h" - -#include "mojo/public/c/system/types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -using HandleSignalsStateTest = testing::Test; - -TEST_F(HandleSignalsStateTest, SanityCheck) { - // There's not much to test here. Just a quick sanity check to make sure the - // code compiles and the helper methods do what they're supposed to do. - - HandleSignalsState empty_signals(MOJO_HANDLE_SIGNAL_NONE, - MOJO_HANDLE_SIGNAL_NONE); - EXPECT_FALSE(empty_signals.readable()); - EXPECT_FALSE(empty_signals.writable()); - EXPECT_FALSE(empty_signals.peer_closed()); - EXPECT_TRUE(empty_signals.never_readable()); - EXPECT_TRUE(empty_signals.never_writable()); - EXPECT_TRUE(empty_signals.never_peer_closed()); - - HandleSignalsState all_signals( - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - EXPECT_TRUE(all_signals.readable()); - EXPECT_TRUE(all_signals.writable()); - EXPECT_TRUE(all_signals.peer_closed()); - EXPECT_FALSE(all_signals.never_readable()); - EXPECT_FALSE(all_signals.never_writable()); - EXPECT_FALSE(all_signals.never_peer_closed()); -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/system/tests/simple_watcher_unittest.cc b/mojo/public/cpp/system/tests/simple_watcher_unittest.cc deleted file mode 100644 index 795f262..0000000 --- a/mojo/public/cpp/system/tests/simple_watcher_unittest.cc +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/simple_watcher.h" - -#include <memory> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -template <typename Handler> -void RunResultHandler(Handler f, MojoResult result) { - f(result); -} - -template <typename Handler> -SimpleWatcher::ReadyCallback OnReady(Handler f) { - return base::Bind(&RunResultHandler<Handler>, f); -} - -SimpleWatcher::ReadyCallback NotReached() { - return OnReady([](MojoResult) { NOTREACHED(); }); -} - -class SimpleWatcherTest : public testing::Test { - public: - SimpleWatcherTest() {} - ~SimpleWatcherTest() override {} - - private: - base::MessageLoop message_loop_; - - DISALLOW_COPY_AND_ASSIGN(SimpleWatcherTest); -}; - -TEST_F(SimpleWatcherTest, WatchBasic) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - bool notified = false; - base::RunLoop run_loop; - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, - OnReady([&](MojoResult result) { - EXPECT_EQ(MOJO_RESULT_OK, result); - notified = true; - run_loop.Quit(); - }))); - EXPECT_TRUE(b_watcher.IsWatching()); - - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - run_loop.Run(); - EXPECT_TRUE(notified); - - b_watcher.Cancel(); -} - -TEST_F(SimpleWatcherTest, WatchUnsatisfiable) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - a.reset(); - - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); - EXPECT_EQ( - MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, b_watcher.Arm()); -} - -TEST_F(SimpleWatcherTest, WatchInvalidHandle) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - a.reset(); - b.reset(); - - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); - EXPECT_FALSE(b_watcher.IsWatching()); -} - -TEST_F(SimpleWatcherTest, Cancel) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - base::RunLoop run_loop; - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ( - MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); - EXPECT_TRUE(b_watcher.IsWatching()); - b_watcher.Cancel(); - EXPECT_FALSE(b_watcher.IsWatching()); - - // This should never trigger the watcher. - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - run_loop.QuitClosure()); - run_loop.Run(); -} - -TEST_F(SimpleWatcherTest, CancelOnClose) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - base::RunLoop run_loop; - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, - OnReady([&](MojoResult result) { - EXPECT_EQ(MOJO_RESULT_CANCELLED, result); - run_loop.Quit(); - }))); - EXPECT_TRUE(b_watcher.IsWatching()); - - // This should trigger the watcher above. - b.reset(); - - run_loop.Run(); - - EXPECT_FALSE(b_watcher.IsWatching()); -} - -TEST_F(SimpleWatcherTest, CancelOnDestruction) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - base::RunLoop run_loop; - { - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ( - MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, NotReached())); - EXPECT_TRUE(b_watcher.IsWatching()); - - // |b_watcher| should be cancelled when it goes out of scope. - } - - // This should never trigger the watcher above. - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - run_loop.QuitClosure()); - run_loop.Run(); -} - -TEST_F(SimpleWatcherTest, CloseAndCancel) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, - OnReady([](MojoResult result) { FAIL(); }))); - EXPECT_TRUE(b_watcher.IsWatching()); - - // This should trigger the watcher above... - b.reset(); - // ...but the watcher is cancelled first. - b_watcher.Cancel(); - - EXPECT_FALSE(b_watcher.IsWatching()); - - base::RunLoop().RunUntilIdle(); -} - -TEST_F(SimpleWatcherTest, UnarmedCancel) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); - base::RunLoop loop; - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind( - [](base::RunLoop* loop, MojoResult result) { - EXPECT_EQ(result, MOJO_RESULT_CANCELLED); - loop->Quit(); - }, - &loop))); - - // This message write will not wake up the watcher since the watcher isn't - // armed. Instead, the cancellation will dispatch due to the reset below. - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - b.reset(); - loop.Run(); -} - -TEST_F(SimpleWatcherTest, ManualArming) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - SimpleWatcher b_watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); - base::RunLoop loop; - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher.Watch(b.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind( - [](base::RunLoop* loop, MojoResult result) { - EXPECT_EQ(result, MOJO_RESULT_OK); - loop->Quit(); - }, - &loop))); - EXPECT_EQ(MOJO_RESULT_OK, b_watcher.Arm()); - - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - loop.Run(); -} - -TEST_F(SimpleWatcherTest, ManualArmOrNotifyWhileSignaled) { - ScopedMessagePipeHandle a, b; - CreateMessagePipe(nullptr, &a, &b); - - base::RunLoop loop1; - SimpleWatcher b_watcher1(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); - bool notified1 = false; - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher1.Watch( - b.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind( - [](base::RunLoop* loop, bool* notified, MojoResult result) { - EXPECT_EQ(result, MOJO_RESULT_OK); - *notified = true; - loop->Quit(); - }, - &loop1, ¬ified1))); - - base::RunLoop loop2; - SimpleWatcher b_watcher2(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL); - bool notified2 = false; - EXPECT_EQ(MOJO_RESULT_OK, - b_watcher2.Watch( - b.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind( - [](base::RunLoop* loop, bool* notified, MojoResult result) { - EXPECT_EQ(result, MOJO_RESULT_OK); - *notified = true; - loop->Quit(); - }, - &loop2, ¬ified2))); - - // First ensure that |b| is readable. - EXPECT_EQ(MOJO_RESULT_OK, b_watcher1.Arm()); - EXPECT_EQ(MOJO_RESULT_OK, WriteMessageRaw(a.get(), "hello", 5, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - loop1.Run(); - - EXPECT_TRUE(notified1); - EXPECT_FALSE(notified2); - notified1 = false; - - // Now verify that ArmOrNotify results in a notification. - b_watcher2.ArmOrNotify(); - loop2.Run(); - - EXPECT_FALSE(notified1); - EXPECT_TRUE(notified2); -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/system/tests/wait_set_unittest.cc b/mojo/public/cpp/system/tests/wait_set_unittest.cc deleted file mode 100644 index d60cb45..0000000 --- a/mojo/public/cpp/system/tests/wait_set_unittest.cc +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/wait_set.h" - -#include <set> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/ptr_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/platform_thread.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -using WaitSetTest = testing::Test; - -void WriteMessage(const ScopedMessagePipeHandle& handle, - const base::StringPiece& message) { - MojoResult rv = WriteMessageRaw(handle.get(), message.data(), - static_cast<uint32_t>(message.size()), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_OK, rv); -} - -std::string ReadMessage(const ScopedMessagePipeHandle& handle) { - uint32_t num_bytes = 0; - uint32_t num_handles = 0; - MojoResult rv = ReadMessageRaw(handle.get(), nullptr, &num_bytes, nullptr, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, rv); - CHECK_EQ(0u, num_handles); - - std::vector<char> buffer(num_bytes); - rv = ReadMessageRaw(handle.get(), buffer.data(), &num_bytes, nullptr, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_OK, rv); - return std::string(buffer.data(), buffer.size()); -} - -class ThreadedRunner : public base::SimpleThread { - public: - explicit ThreadedRunner(const base::Closure& callback) - : SimpleThread("ThreadedRunner"), callback_(callback) {} - ~ThreadedRunner() override { Join(); } - - void Run() override { callback_.Run(); } - - private: - const base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(ThreadedRunner); -}; - -TEST_F(WaitSetTest, Satisfied) { - WaitSet wait_set; - MessagePipe p; - - const char kTestMessage1[] = "hello wake up"; - - // Watch only one handle and write to the other. - - wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - WriteMessage(p.handle0, kTestMessage1); - - size_t num_ready_handles = 2; - Handle ready_handles[2]; - MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; - HandleSignalsState hss[2]; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); - - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(p.handle1.get(), ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); - - wait_set.RemoveHandle(p.handle1.get()); - - // Now watch only the other handle and write to the first one. - - wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - WriteMessage(p.handle1, kTestMessage1); - - num_ready_handles = 2; - ready_results[0] = MOJO_RESULT_UNKNOWN; - ready_results[1] = MOJO_RESULT_UNKNOWN; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); - - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(p.handle0.get(), ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); - - // Now wait on both of them. - wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - - num_ready_handles = 2; - ready_results[0] = MOJO_RESULT_UNKNOWN; - ready_results[1] = MOJO_RESULT_UNKNOWN; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); - EXPECT_EQ(2u, num_ready_handles); - EXPECT_TRUE((ready_handles[0] == p.handle0.get() && - ready_handles[1] == p.handle1.get()) || - (ready_handles[0] == p.handle1.get() && - ready_handles[1] == p.handle0.get())); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]); - EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); - EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed()); - - // Wait on both again, but with only enough output space for one result. - num_ready_handles = 1; - ready_results[0] = MOJO_RESULT_UNKNOWN; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_TRUE(ready_handles[0] == p.handle0.get() || - ready_handles[0] == p.handle1.get()); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - // Remove the ready handle from the set and wait one more time. - EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); - - num_ready_handles = 1; - ready_results[0] = MOJO_RESULT_UNKNOWN; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_TRUE(ready_handles[0] == p.handle0.get() || - ready_handles[0] == p.handle1.get()); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); - - // The wait set should be empty now. Nothing to wait on. - num_ready_handles = 2; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); - EXPECT_EQ(0u, num_ready_handles); -} - -TEST_F(WaitSetTest, Unsatisfiable) { - MessagePipe p, q; - WaitSet wait_set; - - wait_set.AddHandle(q.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddHandle(q.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - - size_t num_ready_handles = 2; - Handle ready_handles[2]; - MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; - - p.handle1.reset(); - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(p.handle0.get(), ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); -} - -TEST_F(WaitSetTest, CloseWhileWaiting) { - MessagePipe p; - WaitSet wait_set; - - wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - - const Handle handle0_value = p.handle0.get(); - ThreadedRunner close_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then close the handle. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - handle->reset(); - }, - &p.handle0)); - close_after_delay.Start(); - - size_t num_ready_handles = 2; - Handle ready_handles[2]; - MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(handle0_value, ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]); - - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); -} - -TEST_F(WaitSetTest, CloseBeforeWaiting) { - MessagePipe p; - WaitSet wait_set; - - wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - - Handle handle0_value = p.handle0.get(); - Handle handle1_value = p.handle1.get(); - - p.handle0.reset(); - p.handle1.reset(); - - // Ensure that the WaitSet user is always made aware of all cancellations even - // if they happen while not waiting, or they have to be returned over the span - // of multiple Wait() calls due to insufficient output storage. - - size_t num_ready_handles = 1; - Handle ready_handle; - MojoResult ready_result = MOJO_RESULT_UNKNOWN; - wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); - EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); - - wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); - EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); - - // Nothing more to wait on. - wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(0u, num_ready_handles); -} - -TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) { - MessagePipe p; - WaitSet wait_set; - - wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - - const char kTestMessage1[] = "testing testing testing"; - WriteMessage(p.handle0, kTestMessage1); - - size_t num_ready_handles = 2; - Handle ready_handles[2]; - MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(p.handle1.get(), ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1)); - - ThreadedRunner write_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then write a message. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - WriteMessage(*handle, "wakey wakey"); - }, - &p.handle1)); - write_after_delay.Start(); - - num_ready_handles = 2; - wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(p.handle0.get(), ready_handles[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); -} - -TEST_F(WaitSetTest, EventOnly) { - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::SIGNALED); - WaitSet wait_set; - wait_set.AddEvent(&event); - - base::WaitableEvent* ready_event = nullptr; - size_t num_ready_handles = 1; - Handle ready_handle; - MojoResult ready_result = MOJO_RESULT_UNKNOWN; - wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(0u, num_ready_handles); - EXPECT_EQ(&event, ready_event); -} - -TEST_F(WaitSetTest, EventAndHandle) { - const char kTestMessage[] = "hello hello"; - - MessagePipe p; - WriteMessage(p.handle0, kTestMessage); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - WaitSet wait_set; - wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddEvent(&event); - - base::WaitableEvent* ready_event = nullptr; - size_t num_ready_handles = 1; - Handle ready_handle; - MojoResult ready_result = MOJO_RESULT_UNKNOWN; - wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(nullptr, ready_event); - EXPECT_EQ(p.handle1.get(), ready_handle); - EXPECT_EQ(MOJO_RESULT_OK, ready_result); - - EXPECT_EQ(kTestMessage, ReadMessage(p.handle1)); - - ThreadedRunner signal_after_delay(base::Bind( - [](base::WaitableEvent* event) { - // Wait a little while, then close the handle. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - event->Signal(); - }, - &event)); - signal_after_delay.Start(); - - wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); - EXPECT_EQ(0u, num_ready_handles); - EXPECT_EQ(&event, ready_event); -} - -TEST_F(WaitSetTest, NoStarvation) { - const char kTestMessage[] = "wait for it"; - const size_t kNumTestPipes = 50; - const size_t kNumTestEvents = 10; - - // Create a bunch of handles and events which are always ready and add them - // to a shared WaitSet. - - WaitSet wait_set; - - MessagePipe pipes[kNumTestPipes]; - for (size_t i = 0; i < kNumTestPipes; ++i) { - WriteMessage(pipes[i].handle0, kTestMessage); - Wait(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - - WriteMessage(pipes[i].handle1, kTestMessage); - Wait(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - - wait_set.AddHandle(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); - wait_set.AddHandle(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); - } - - std::vector<std::unique_ptr<base::WaitableEvent>> events(kNumTestEvents); - for (auto& event_ptr : events) { - event_ptr = base::MakeUnique<base::WaitableEvent>( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - event_ptr->Signal(); - wait_set.AddEvent(event_ptr.get()); - } - - // Now verify that all handle and event signals are deteceted within a finite - // number of consecutive Wait() calls. Do it a few times for good measure. - for (size_t i = 0; i < 3; ++i) { - std::set<base::WaitableEvent*> ready_events; - std::set<Handle> ready_handles; - while (ready_events.size() < kNumTestEvents || - ready_handles.size() < kNumTestPipes * 2) { - base::WaitableEvent* ready_event = nullptr; - size_t num_ready_handles = 1; - Handle ready_handle; - MojoResult ready_result = MOJO_RESULT_UNKNOWN; - wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, - &ready_result); - if (ready_event) - ready_events.insert(ready_event); - - if (num_ready_handles) { - EXPECT_EQ(1u, num_ready_handles); - EXPECT_EQ(MOJO_RESULT_OK, ready_result); - ready_handles.insert(ready_handle); - } - } - } -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/system/tests/wait_unittest.cc b/mojo/public/cpp/system/tests/wait_unittest.cc deleted file mode 100644 index 1d9d3c6..0000000 --- a/mojo/public/cpp/system/tests/wait_unittest.cc +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/wait.h" - -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/strings/string_piece.h" -#include "base/threading/platform_thread.h" -#include "base/threading/simple_thread.h" -#include "base/time/time.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/handle_signals_state.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -using WaitTest = testing::Test; -using WaitManyTest = testing::Test; - -void WriteMessage(const ScopedMessagePipeHandle& handle, - const base::StringPiece& message) { - MojoResult rv = WriteMessageRaw(handle.get(), message.data(), - static_cast<uint32_t>(message.size()), - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_OK, rv); -} - -std::string ReadMessage(const ScopedMessagePipeHandle& handle) { - uint32_t num_bytes = 0; - uint32_t num_handles = 0; - MojoResult rv = ReadMessageRaw(handle.get(), nullptr, &num_bytes, nullptr, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, rv); - CHECK_EQ(0u, num_handles); - - std::vector<char> buffer(num_bytes); - rv = ReadMessageRaw(handle.get(), buffer.data(), &num_bytes, nullptr, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); - CHECK_EQ(MOJO_RESULT_OK, rv); - return std::string(buffer.data(), buffer.size()); -} - -class ThreadedRunner : public base::SimpleThread { - public: - explicit ThreadedRunner(const base::Closure& callback) - : SimpleThread("ThreadedRunner"), callback_(callback) {} - ~ThreadedRunner() override { Join(); } - - void Run() override { callback_.Run(); } - - private: - const base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(ThreadedRunner); -}; - -TEST_F(WaitTest, InvalidArguments) { - Handle invalid_handle; - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - Wait(invalid_handle, MOJO_HANDLE_SIGNAL_READABLE)); - - MessagePipe p; - Handle valid_handles[2] = {p.handle0.get(), p.handle1.get()}; - Handle invalid_handles[2]; - MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_NONE, - MOJO_HANDLE_SIGNAL_NONE}; - size_t result_index = 0; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - WaitMany(invalid_handles, signals, 2, &result_index)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - WaitMany(nullptr, signals, 2, &result_index)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - WaitMany(valid_handles, nullptr, 2, &result_index)); -} - -TEST_F(WaitTest, Basic) { - MessagePipe p; - - // Write to one end of the pipe and wait on the other. - const char kTestMessage1[] = "how about a nice game of chess?"; - WriteMessage(p.handle0, kTestMessage1); - EXPECT_EQ(MOJO_RESULT_OK, Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE)); - - // And make sure we can also grab the handle signals state (with both the C - // and C++ library structs.) - - MojoHandleSignalsState c_hss = {0, 0}; - EXPECT_EQ(MOJO_RESULT_OK, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &c_hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - c_hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - c_hss.satisfiable_signals); - - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_OK, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE(hss.readable() && hss.writable() && !hss.peer_closed()); - EXPECT_FALSE(hss.never_readable() || hss.never_writable() || - hss.never_peer_closed()); - - // Now close the writing end and wait for peer closure. - - p.handle0.reset(); - EXPECT_EQ(MOJO_RESULT_OK, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - - // Still readable as there's still a message queued. No longer writable as - // peer closure has been detected. - EXPECT_TRUE(hss.readable() && hss.peer_closed() && !hss.writable()); - EXPECT_TRUE(hss.never_writable() && !hss.never_readable() && - !hss.never_peer_closed()); - - // Read the message and wait for readable again. Waiting should fail since - // there are no more messages and the peer is closed. - EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1)); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - - // Sanity check the signals state again. - EXPECT_TRUE(hss.peer_closed() && !hss.readable() && !hss.writable()); - EXPECT_TRUE(hss.never_readable() && hss.never_writable() && - !hss.never_peer_closed()); -} - -TEST_F(WaitTest, DelayedWrite) { - MessagePipe p; - - ThreadedRunner write_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then write a message. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - WriteMessage(*handle, "wakey wakey"); - }, - &p.handle0)); - write_after_delay.Start(); - - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_OK, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE(hss.readable() && hss.writable() && !hss.peer_closed()); - EXPECT_TRUE(!hss.never_readable() && !hss.never_writable() && - !hss.never_peer_closed()); -} - -TEST_F(WaitTest, DelayedPeerClosure) { - MessagePipe p; - - ThreadedRunner close_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then close the handle. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - handle->reset(); - }, - &p.handle0)); - close_after_delay.Start(); - - HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE(!hss.readable() && !hss.writable() && hss.peer_closed()); - EXPECT_TRUE(hss.never_readable() && hss.never_writable() && - !hss.never_peer_closed()); -} - -TEST_F(WaitTest, CloseWhileWaiting) { - MessagePipe p; - ThreadedRunner close_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - handle->reset(); - }, - &p.handle0)); - close_after_delay.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, - Wait(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE)); -} - -TEST_F(WaitManyTest, Basic) { - MessagePipe p; - - const char kTestMessage1[] = "hello"; - WriteMessage(p.handle0, kTestMessage1); - - // Wait for either handle to become readable. Wait twice, just to verify that - // we can use either the C or C++ signaling state structure for the last - // argument. - - Handle handles[2] = {p.handle0.get(), p.handle1.get()}; - MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - size_t result_index = 0; - MojoHandleSignalsState c_hss[2]; - HandleSignalsState hss[2]; - - EXPECT_EQ(MOJO_RESULT_OK, - WaitMany(handles, signals, 2, &result_index, c_hss)); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, c_hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - c_hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - c_hss[1].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - c_hss[1].satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, WaitMany(handles, signals, 2, &result_index, hss)); - EXPECT_EQ(1u, result_index); - EXPECT_TRUE(!hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); - EXPECT_TRUE(!hss[0].never_readable() && !hss[0].never_writable() && - !hss[0].never_peer_closed()); - EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed()); - EXPECT_TRUE(!hss[1].never_readable() && !hss[1].never_writable() && - !hss[1].never_peer_closed()); - - // Close the writer and read the message. Try to wait again, and it should - // fail due to the conditions being unsatisfiable. - - EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1)); - p.handle0.reset(); - - // handles[0] is invalid. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - WaitMany(handles, signals, 2, &result_index, hss)); - handles[0] = handles[1]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitMany(handles, signals, 1, &result_index, hss)); - EXPECT_EQ(0u, result_index); - EXPECT_TRUE(!hss[0].readable() && !hss[0].writable() && hss[0].peer_closed()); - EXPECT_TRUE(hss[0].never_readable() && hss[0].never_writable() && - !hss[0].never_peer_closed()); -} - -TEST_F(WaitManyTest, CloseWhileWaiting) { - MessagePipe p, q; - - Handle handles[3] = {q.handle0.get(), q.handle1.get(), p.handle1.get()}; - MojoHandleSignals signals[3] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - - ThreadedRunner close_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - handle->reset(); - }, - &p.handle1)); - close_after_delay.Start(); - - size_t result_index = 0; - EXPECT_EQ(MOJO_RESULT_CANCELLED, - WaitMany(handles, signals, 3, &result_index)); - EXPECT_EQ(2u, result_index); -} - -TEST_F(WaitManyTest, DelayedWrite) { - MessagePipe p; - - ThreadedRunner write_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then write a message. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - WriteMessage(*handle, "wakey wakey"); - }, - &p.handle0)); - write_after_delay.Start(); - - Handle handles[2] = {p.handle0.get(), p.handle1.get()}; - MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - size_t result_index = 0; - HandleSignalsState hss[2]; - EXPECT_EQ(MOJO_RESULT_OK, WaitMany(handles, signals, 2, &result_index, hss)); - EXPECT_EQ(1u, result_index); - EXPECT_TRUE(!hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); - EXPECT_TRUE(!hss[0].never_readable() && !hss[0].never_writable() && - !hss[0].never_peer_closed()); - EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed()); - EXPECT_TRUE(!hss[1].never_readable() && !hss[1].never_writable() && - !hss[1].never_peer_closed()); -} - -TEST_F(WaitManyTest, DelayedPeerClosure) { - MessagePipe p, q; - - ThreadedRunner close_after_delay(base::Bind( - [](ScopedMessagePipeHandle* handle) { - // Wait a little while, then close the handle. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); - handle->reset(); - }, - &p.handle0)); - close_after_delay.Start(); - - Handle handles[3] = {q.handle0.get(), q.handle1.get(), p.handle1.get()}; - MojoHandleSignals signals[3] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - size_t result_index = 0; - HandleSignalsState hss[3]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitMany(handles, signals, 3, &result_index, hss)); - EXPECT_EQ(2u, result_index); - EXPECT_TRUE(!hss[2].readable() && !hss[2].writable() && hss[2].peer_closed()); - EXPECT_TRUE(hss[2].never_readable() && hss[2].never_writable() && - !hss[2].never_peer_closed()); -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/cpp/system/wait.cc b/mojo/public/cpp/system/wait.cc deleted file mode 100644 index e4e124f..0000000 --- a/mojo/public/cpp/system/wait.cc +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/wait.h" - -#include <memory> -#include <vector> - -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/waitable_event.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/watcher.h" - -namespace mojo { -namespace { - -class WatchContext : public base::RefCountedThreadSafe<WatchContext> { - public: - WatchContext() - : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} - - base::WaitableEvent& event() { return event_; } - MojoResult wait_result() const { return wait_result_; } - MojoHandleSignalsState wait_state() const { return wait_state_; } - uintptr_t context_value() const { return reinterpret_cast<uintptr_t>(this); } - - static void OnNotification(uintptr_t context_value, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - auto* context = reinterpret_cast<WatchContext*>(context_value); - context->Notify(result, state); - if (result == MOJO_RESULT_CANCELLED) { - // Balanced in Wait() or WaitMany(). - context->Release(); - } - } - - private: - friend class base::RefCountedThreadSafe<WatchContext>; - - ~WatchContext() {} - - void Notify(MojoResult result, MojoHandleSignalsState state) { - if (wait_result_ == MOJO_RESULT_UNKNOWN) { - wait_result_ = result; - wait_state_ = state; - } - event_.Signal(); - } - - base::WaitableEvent event_; - - // NOTE: Although these are modified in Notify() which may be called from any - // thread, Notify() is guaranteed to never run concurrently with itself. - // Furthermore, they are only modified once, before |event_| signals; so there - // is no need for a WatchContext user to synchronize access to these fields - // apart from waiting on |event()|. - MojoResult wait_result_ = MOJO_RESULT_UNKNOWN; - MojoHandleSignalsState wait_state_ = {0, 0}; - - DISALLOW_COPY_AND_ASSIGN(WatchContext); -}; - -} // namespace - -MojoResult Wait(Handle handle, - MojoHandleSignals signals, - MojoHandleSignalsState* signals_state) { - ScopedWatcherHandle watcher; - MojoResult rv = CreateWatcher(&WatchContext::OnNotification, &watcher); - DCHECK_EQ(MOJO_RESULT_OK, rv); - - scoped_refptr<WatchContext> context = new WatchContext; - - // Balanced in WatchContext::OnNotification if MojoWatch() is successful. - // Otherwise balanced immediately below. - context->AddRef(); - - rv = MojoWatch(watcher.get().value(), handle.value(), signals, - context->context_value()); - if (rv == MOJO_RESULT_INVALID_ARGUMENT) { - // Balanced above. - context->Release(); - return rv; - } - DCHECK_EQ(MOJO_RESULT_OK, rv); - - uint32_t num_ready_contexts = 1; - uintptr_t ready_context; - MojoResult ready_result; - MojoHandleSignalsState ready_state; - rv = MojoArmWatcher(watcher.get().value(), &num_ready_contexts, - &ready_context, &ready_result, &ready_state); - if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - DCHECK_EQ(1u, num_ready_contexts); - if (signals_state) - *signals_state = ready_state; - return ready_result; - } - - // Wait for the first notification only. - context->event().Wait(); - - ready_result = context->wait_result(); - DCHECK_NE(MOJO_RESULT_UNKNOWN, ready_result); - - if (signals_state) - *signals_state = context->wait_state(); - - return ready_result; -} - -MojoResult WaitMany(const Handle* handles, - const MojoHandleSignals* signals, - size_t num_handles, - size_t* result_index, - MojoHandleSignalsState* signals_states) { - if (!handles || !signals) - return MOJO_RESULT_INVALID_ARGUMENT; - - ScopedWatcherHandle watcher; - MojoResult rv = CreateWatcher(&WatchContext::OnNotification, &watcher); - DCHECK_EQ(MOJO_RESULT_OK, rv); - - std::vector<scoped_refptr<WatchContext>> contexts(num_handles); - std::vector<base::WaitableEvent*> events(num_handles); - for (size_t i = 0; i < num_handles; ++i) { - contexts[i] = new WatchContext(); - - // Balanced in WatchContext::OnNotification if MojoWatch() is successful. - // Otherwise balanced immediately below. - contexts[i]->AddRef(); - - MojoResult rv = MojoWatch(watcher.get().value(), handles[i].value(), - signals[i], contexts[i]->context_value()); - if (rv == MOJO_RESULT_INVALID_ARGUMENT) { - if (result_index) - *result_index = i; - - // Balanced above. - contexts[i]->Release(); - - return MOJO_RESULT_INVALID_ARGUMENT; - } - - events[i] = &contexts[i]->event(); - } - - uint32_t num_ready_contexts = 1; - uintptr_t ready_context = 0; - MojoResult ready_result = MOJO_RESULT_UNKNOWN; - MojoHandleSignalsState ready_state{0, 0}; - rv = MojoArmWatcher(watcher.get().value(), &num_ready_contexts, - &ready_context, &ready_result, &ready_state); - - size_t index = num_handles; - if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - DCHECK_EQ(1u, num_ready_contexts); - - // Most commonly we only watch a small number of handles. Just scan for - // the right index. - for (size_t i = 0; i < num_handles; ++i) { - if (contexts[i]->context_value() == ready_context) { - index = i; - break; - } - } - } else { - DCHECK_EQ(MOJO_RESULT_OK, rv); - - // Wait for one of the contexts to signal. First one wins. - index = base::WaitableEvent::WaitMany(events.data(), events.size()); - ready_result = contexts[index]->wait_result(); - ready_state = contexts[index]->wait_state(); - } - - DCHECK_NE(MOJO_RESULT_UNKNOWN, ready_result); - DCHECK_LT(index, num_handles); - - if (result_index) - *result_index = index; - - if (signals_states) { - for (size_t i = 0; i < num_handles; ++i) { - if (i == index) { - signals_states[i] = ready_state; - } else { - signals_states[i] = handles[i].QuerySignalsState(); - } - } - } - - return ready_result; -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/wait.h b/mojo/public/cpp/system/wait.h deleted file mode 100644 index 808e44f..0000000 --- a/mojo/public/cpp/system/wait.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_WAIT_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_WAIT_H_ - -#include <stddef.h> - -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace mojo { - -// Blocks the calling thread, waiting for one or more signals in |signals| to be -// become satisfied -- or for all of them to become unsatisfiable -- on the -// given Handle. -// -// If |signals_state| is non-null, |handle| is valid, the wait is not cancelled -// (see return values below), the last known signaling state of |handle| is -// written to |*signals_state| before returning. -// -// Return values: -// |MOJO_RESULT_OK| if one or more signals in |signals| has been raised on -// |handle| . -// |MOJO_RESULT_FAILED_PRECONDITION| if the state of |handle| changes such -// that no signals in |signals| can ever be raised again. -// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle. -// |MOJO_RESULT_CANCELLED| if the wait was cancelled because |handle| was -// closed by some other thread while waiting. -MOJO_CPP_SYSTEM_EXPORT MojoResult -Wait(Handle handle, - MojoHandleSignals signals, - MojoHandleSignalsState* signals_state = nullptr); - -// Waits on |handles[0]|, ..., |handles[num_handles-1]| until: -// - At least one handle satisfies a signal indicated in its respective -// |signals[0]|, ..., |signals[num_handles-1]|. -// - It becomes known that no signal in some |signals[i]| will ever be -// satisfied. -// -// This means that |WaitMany()| behaves as if |Wait()| were called on each -// handle/signals pair simultaneously, completing when the first |Wait()| would -// complete. -// -// If |signals_states| is non-null, all other arguments are valid, and the wait -// is not cancelled (see return values below), the last known signaling state of -// each Handle |handles[i]| is written to its corresponding entry in -// |signals_states[i]| before returning. -// -// Returns values: -// |MOJO_RESULT_OK| if one of the Handles in |handles| had one or more of its -// correpsonding signals satisfied. |*result_index| contains the index -// of the Handle in question if |result_index| is non-null. -// |MOJO_RESULT_FAILED_PRECONDITION| if one of the Handles in |handles| -// changes state such that its corresponding signals become permanently -// unsatisfiable. |*result_index| contains the index of the handle in -// question if |result_index| is non-null. -// |MOJO_RESULT_INVALID_ARGUMENT| if any Handle in |handles| is invalid, -// or if either |handles| or |signals| is null. -// |MOJO_RESULT_CANCELLED| if the wait was cancelled because a handle in -// |handles| was closed by some other thread while waiting. -// |*result_index| contains the index of the closed Handle if -// |result_index| is non-null. -MOJO_CPP_SYSTEM_EXPORT MojoResult -WaitMany(const Handle* handles, - const MojoHandleSignals* signals, - size_t num_handles, - size_t* result_index = nullptr, - MojoHandleSignalsState* signals_states = nullptr); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_WAIT_H_ diff --git a/mojo/public/cpp/system/wait_set.cc b/mojo/public/cpp/system/wait_set.cc deleted file mode 100644 index 1728f81..0000000 --- a/mojo/public/cpp/system/wait_set.cc +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/wait_set.h" - -#include <algorithm> -#include <limits> -#include <map> -#include <set> -#include <vector> - -#include "base/containers/stack_container.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "mojo/public/cpp/system/watcher.h" - -namespace mojo { - -class WaitSet::State : public base::RefCountedThreadSafe<State> { - public: - State() - : handle_event_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED) { - MojoResult rv = CreateWatcher(&Context::OnNotification, &watcher_handle_); - DCHECK_EQ(MOJO_RESULT_OK, rv); - } - - void ShutDown() { - // NOTE: This may immediately invoke Notify for every context. - watcher_handle_.reset(); - } - - MojoResult AddEvent(base::WaitableEvent* event) { - auto result = user_events_.insert(event); - if (result.second) - return MOJO_RESULT_OK; - return MOJO_RESULT_ALREADY_EXISTS; - } - - MojoResult RemoveEvent(base::WaitableEvent* event) { - auto it = user_events_.find(event); - if (it == user_events_.end()) - return MOJO_RESULT_NOT_FOUND; - user_events_.erase(it); - return MOJO_RESULT_OK; - } - - MojoResult AddHandle(Handle handle, MojoHandleSignals signals) { - DCHECK(watcher_handle_.is_valid()); - - scoped_refptr<Context> context = new Context(this, handle); - - { - base::AutoLock lock(lock_); - - if (handle_to_context_.count(handle)) - return MOJO_RESULT_ALREADY_EXISTS; - DCHECK(!contexts_.count(context->context_value())); - - handle_to_context_[handle] = context; - contexts_[context->context_value()] = context; - } - - // Balanced in State::Notify() with MOJO_RESULT_CANCELLED if - // MojoWatch() succeeds. Otherwise balanced immediately below. - context->AddRef(); - - // This can notify immediately if the watcher is already armed. Don't hold - // |lock_| while calling it. - MojoResult rv = MojoWatch(watcher_handle_.get().value(), handle.value(), - signals, context->context_value()); - if (rv == MOJO_RESULT_INVALID_ARGUMENT) { - base::AutoLock lock(lock_); - handle_to_context_.erase(handle); - contexts_.erase(context->context_value()); - - // Balanced above. - context->Release(); - return rv; - } - DCHECK_EQ(MOJO_RESULT_OK, rv); - - return rv; - } - - MojoResult RemoveHandle(Handle handle) { - DCHECK(watcher_handle_.is_valid()); - - scoped_refptr<Context> context; - { - base::AutoLock lock(lock_); - auto it = handle_to_context_.find(handle); - if (it == handle_to_context_.end()) - return MOJO_RESULT_NOT_FOUND; - - context = std::move(it->second); - handle_to_context_.erase(it); - - // Ensure that we never return this handle as a ready result again. Note - // that it's removal from |handle_to_context_| above ensures it will never - // be added back to this map. - ready_handles_.erase(handle); - } - - // NOTE: This may enter the notification callback immediately, so don't hold - // |lock_| while calling it. - MojoResult rv = MojoCancelWatch(watcher_handle_.get().value(), - context->context_value()); - - // We don't really care whether or not this succeeds. In either case, the - // context was or will imminently be cancelled and moved from |contexts_| - // to |cancelled_contexts_|. - DCHECK(rv == MOJO_RESULT_OK || rv == MOJO_RESULT_NOT_FOUND); - - { - // Always clear |cancelled_contexts_| in case it's accumulated any more - // entries since the last time we ran. - base::AutoLock lock(lock_); - cancelled_contexts_.clear(); - } - - return rv; - } - - void Wait(base::WaitableEvent** ready_event, - size_t* num_ready_handles, - Handle* ready_handles, - MojoResult* ready_results, - MojoHandleSignalsState* signals_states) { - DCHECK(watcher_handle_.is_valid()); - DCHECK(num_ready_handles); - DCHECK(ready_handles); - DCHECK(ready_results); - { - base::AutoLock lock(lock_); - if (ready_handles_.empty()) { - // No handles are currently in the ready set. Make sure the event is - // reset and try to arm the watcher. - handle_event_.Reset(); - - DCHECK_LE(*num_ready_handles, std::numeric_limits<uint32_t>::max()); - uint32_t num_ready_contexts = static_cast<uint32_t>(*num_ready_handles); - - base::StackVector<uintptr_t, 4> ready_contexts; - ready_contexts.container().resize(num_ready_contexts); - base::StackVector<MojoHandleSignalsState, 4> ready_states; - MojoHandleSignalsState* out_states = signals_states; - if (!out_states) { - // If the caller didn't provide a buffer for signal states, we provide - // our own locally. MojoArmWatcher() requires one if we want to handle - // arming failure properly. - ready_states.container().resize(num_ready_contexts); - out_states = ready_states.container().data(); - } - MojoResult rv = MojoArmWatcher( - watcher_handle_.get().value(), &num_ready_contexts, - ready_contexts.container().data(), ready_results, out_states); - - if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - // Simulate the handles becoming ready. We do this in lieu of - // returning the results immediately so as to avoid potentially - // starving user events. i.e., we always want to call WaitMany() - // below. - handle_event_.Signal(); - for (size_t i = 0; i < num_ready_contexts; ++i) { - auto it = contexts_.find(ready_contexts.container()[i]); - DCHECK(it != contexts_.end()); - ready_handles_[it->second->handle()] = {ready_results[i], - out_states[i]}; - } - } else if (rv == MOJO_RESULT_NOT_FOUND) { - // Nothing to watch. If there are no user events, always signal to - // avoid deadlock. - if (user_events_.empty()) - handle_event_.Signal(); - } else { - // Watcher must be armed now. No need to manually signal. - DCHECK_EQ(MOJO_RESULT_OK, rv); - } - } - } - - // Build a local contiguous array of events to wait on. These are rotated - // across Wait() calls to avoid starvation, by virtue of the fact that - // WaitMany guarantees left-to-right priority when multiple events are - // signaled. - - base::StackVector<base::WaitableEvent*, 4> events; - events.container().resize(user_events_.size() + 1); - if (waitable_index_shift_ > user_events_.size()) - waitable_index_shift_ = 0; - - size_t dest_index = waitable_index_shift_++; - events.container()[dest_index] = &handle_event_; - for (auto* e : user_events_) { - dest_index = (dest_index + 1) % events.container().size(); - events.container()[dest_index] = e; - } - - size_t index = base::WaitableEvent::WaitMany(events.container().data(), - events.container().size()); - base::AutoLock lock(lock_); - - // Pop as many handles as we can out of the ready set and return them. Note - // that we do this regardless of which event signaled, as there may be - // ready handles in any case and they may be interesting to the caller. - *num_ready_handles = std::min(*num_ready_handles, ready_handles_.size()); - for (size_t i = 0; i < *num_ready_handles; ++i) { - auto it = ready_handles_.begin(); - ready_handles[i] = it->first; - ready_results[i] = it->second.result; - if (signals_states) - signals_states[i] = it->second.signals_state; - ready_handles_.erase(it); - } - - // If the caller cares, let them know which user event unblocked us, if any. - if (ready_event) { - if (events.container()[index] == &handle_event_) - *ready_event = nullptr; - else - *ready_event = events.container()[index]; - } - } - - private: - friend class base::RefCountedThreadSafe<State>; - - class Context : public base::RefCountedThreadSafe<Context> { - public: - Context(scoped_refptr<State> state, Handle handle) - : state_(state), handle_(handle) {} - - Handle handle() const { return handle_; } - - uintptr_t context_value() const { - return reinterpret_cast<uintptr_t>(this); - } - - static void OnNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - reinterpret_cast<Context*>(context)->Notify(result, signals_state); - } - - private: - friend class base::RefCountedThreadSafe<Context>; - - ~Context() {} - - void Notify(MojoResult result, MojoHandleSignalsState signals_state) { - state_->Notify(handle_, result, signals_state, this); - } - - const scoped_refptr<State> state_; - const Handle handle_; - - DISALLOW_COPY_AND_ASSIGN(Context); - }; - - ~State() {} - - void Notify(Handle handle, - MojoResult result, - MojoHandleSignalsState signals_state, - Context* context) { - base::AutoLock lock(lock_); - - // This could be a cancellation notification following an explicit - // RemoveHandle(), in which case we really don't care and don't want to - // add it to the ready set. Only update and signal if that's not the case. - if (!handle_to_context_.count(handle)) { - DCHECK_EQ(MOJO_RESULT_CANCELLED, result); - } else { - ready_handles_[handle] = {result, signals_state}; - handle_event_.Signal(); - } - - // Whether it's an implicit or explicit cancellation, erase from |contexts_| - // and append to |cancelled_contexts_|. - if (result == MOJO_RESULT_CANCELLED) { - contexts_.erase(context->context_value()); - handle_to_context_.erase(handle); - - // NOTE: We retain a context ref in |cancelled_contexts_| to ensure that - // this Context's heap address is not reused too soon. For example, it - // would otherwise be possible for the user to call AddHandle() from the - // WaitSet's thread immediately after this notification has fired on - // another thread, potentially reusing the same heap address for the newly - // added Context; and then they may call RemoveHandle() for this handle - // (not knowing its context has just been implicitly cancelled) and - // cause the new Context to be incorrectly removed from |contexts_|. - // - // This vector is cleared on the WaitSet's own thread every time - // RemoveHandle is called. - cancelled_contexts_.emplace_back(make_scoped_refptr(context)); - - // Balanced in State::AddHandle(). - context->Release(); - } - } - - struct ReadyState { - ReadyState() = default; - ReadyState(MojoResult result, MojoHandleSignalsState signals_state) - : result(result), signals_state(signals_state) {} - ~ReadyState() = default; - - MojoResult result = MOJO_RESULT_UNKNOWN; - MojoHandleSignalsState signals_state = {0, 0}; - }; - - // Not guarded by lock. Must only be accessed from the WaitSet's owning - // thread. - ScopedWatcherHandle watcher_handle_; - - base::Lock lock_; - std::map<uintptr_t, scoped_refptr<Context>> contexts_; - std::map<Handle, scoped_refptr<Context>> handle_to_context_; - std::map<Handle, ReadyState> ready_handles_; - std::vector<scoped_refptr<Context>> cancelled_contexts_; - std::set<base::WaitableEvent*> user_events_; - - // Event signaled any time a handle notification is received. - base::WaitableEvent handle_event_; - - // Offset by which to rotate the current set of waitable objects. This is used - // to guard against event starvation, as base::WaitableEvent::WaitMany gives - // preference to events in left-to-right order. - size_t waitable_index_shift_ = 0; - - DISALLOW_COPY_AND_ASSIGN(State); -}; - -WaitSet::WaitSet() : state_(new State) {} - -WaitSet::~WaitSet() { - state_->ShutDown(); -} - -MojoResult WaitSet::AddEvent(base::WaitableEvent* event) { - return state_->AddEvent(event); -} - -MojoResult WaitSet::RemoveEvent(base::WaitableEvent* event) { - return state_->RemoveEvent(event); -} - -MojoResult WaitSet::AddHandle(Handle handle, MojoHandleSignals signals) { - return state_->AddHandle(handle, signals); -} - -MojoResult WaitSet::RemoveHandle(Handle handle) { - return state_->RemoveHandle(handle); -} - -void WaitSet::Wait(base::WaitableEvent** ready_event, - size_t* num_ready_handles, - Handle* ready_handles, - MojoResult* ready_results, - MojoHandleSignalsState* signals_states) { - state_->Wait(ready_event, num_ready_handles, ready_handles, ready_results, - signals_states); -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/wait_set.h b/mojo/public/cpp/system/wait_set.h deleted file mode 100644 index 5047a86..0000000 --- a/mojo/public/cpp/system/wait_set.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace base { -class WaitableEvent; -} - -namespace mojo { - -// WaitSet provides an efficient means of blocking a thread on any number of -// events and Mojo handle state changes. -// -// Unlike WaitMany(), which incurs some extra setup cost for every call, a -// WaitSet maintains some persistent accounting of the handles added or removed -// from the set. A blocking wait operation (see the Wait() method below) can -// then be performed multiple times for the same set of events and handles with -// minimal additional setup per call. -// -// WaitSet is NOT thread-safe, so naturally handles and events may not be added -// to or removed from the set while waiting. -class MOJO_CPP_SYSTEM_EXPORT WaitSet { - public: - WaitSet(); - ~WaitSet(); - - // Adds |event| to the set of events to wait on. If successful, any future - // Wait() on this WaitSet will wake up if the event is signaled. - // - // |event| is not owned. - // - // Return values: - // |MOJO_RESULT_OK| if |event| has been successfully added. - // |MOJO_RESULT_ALREADY_EXISTS| if |event| is already in this WaitSet. - MojoResult AddEvent(base::WaitableEvent* event); - - // Removes |event| from the set of events to wait on. - // - // Return values: - // |MOJO_RESULT_OK| if |event| has been successfully added. - // |MOJO_RESULT_NOT_FOUND| if |event| was not in the set. - MojoResult RemoveEvent(base::WaitableEvent* event); - - // Adds |handle| to the set of handles to wait on. If successful, any future - // Wait() on this WaitSet will wake up in the event that one or more signals - // in |signals| becomes satisfied on |handle| or all of them become - // permanently unsatisfiable. - // - // Return values: - // |MOJO_RESULT_OK| if |handle| has been successfully added. - // |MOJO_RESULT_ALREADY_EXISTS| if |handle| is already in this WaitSet. - // |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle. - MojoResult AddHandle(Handle handle, MojoHandleSignals signals); - - // Removes |handle| from the set of handles to wait on. Future calls to - // Wait() will be unaffected by the state of this handle. - // - // Return values: - // |MOJO_RESULT_OK| if |handle| has been successfully removed. - // |MOJO_RESULT_NOT_FOUND| if |handle| was not in the set. - MojoResult RemoveHandle(Handle handle); - - // Waits on the current set of handles, waking up when one more of them meets - // the signaling conditions which were specified when they were added via - // AddHandle() above. - // - // |*num_ready_handles| on input must specify the number of entries available - // for output storage in |ready_handles| and |ready_result| (which must both - // be non-null). If |signals_states| is non-null it must also point to enough - // storage for |*num_ready_handles| MojoHandleSignalsState structures. - // - // Upon return, |*num_ready_handles| will contain the total number of handles - // whose information is stored in the given output buffers. - // - // If |ready_event| is non-null and the Wait() was unblocked by a user event - // signaling, the address of the event which signaled will be placed in - // |*ready_event|. Note that this is not necessarily exclusive to one or more - // handles also being ready. If |ready_event| is non-null and no user event - // was signaled for this Wait(), |*ready_event| will be null upon return. - // - // Every entry in |ready_handles| on output corresponds to one of the handles - // whose signaling state termianted the Wait() operation. Every corresponding - // entry in |ready_results| indicates the status of a ready handle according - // to the following result codes: - // |MOJO_RESULT_OK| one or more signals for the handle has been satisfied. - // |MOJO_RESULT_FAILED_PRECONDITION| all of the signals for the handle have - // become permanently unsatisfiable. - // |MOJO_RESULT_CANCELLED| if the handle has been closed from another - // thread. NOTE: It is important to recognize that this means the - // corresponding value in |ready_handles| is either invalid, or valid - // but referring to a different handle (i.e. has already been reused) by - // the time Wait() returns. The handle in question is automatically - // removed from the WaitSet. - void Wait(base::WaitableEvent** ready_event, - size_t* num_ready_handles, - Handle* ready_handles, - MojoResult* ready_results, - MojoHandleSignalsState* signals_states = nullptr); - - private: - class State; - - // Thread-safe state associated with this WaitSet. Used to aggregate - // notifications from watched handles. - scoped_refptr<State> state_; - - DISALLOW_COPY_AND_ASSIGN(WaitSet); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_WAIT_SET_H_ diff --git a/mojo/public/cpp/system/watcher.cc b/mojo/public/cpp/system/watcher.cc deleted file mode 100644 index 0c62ba8..0000000 --- a/mojo/public/cpp/system/watcher.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/system/watcher.h" - -#include "mojo/public/c/system/functions.h" - -namespace mojo { - -MojoResult CreateWatcher(MojoWatcherCallback callback, - ScopedWatcherHandle* watcher_handle) { - MojoHandle handle; - MojoResult rv = MojoCreateWatcher(callback, &handle); - if (rv == MOJO_RESULT_OK) - watcher_handle->reset(WatcherHandle(handle)); - return rv; -} - -} // namespace mojo diff --git a/mojo/public/cpp/system/watcher.h b/mojo/public/cpp/system/watcher.h deleted file mode 100644 index d0a2578..0000000 --- a/mojo/public/cpp/system/watcher.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ -#define MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ - -#include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/system_export.h" - -namespace mojo { - -// A strongly-typed representation of a |MojoHandle| for a watcher. -class WatcherHandle : public Handle { - public: - WatcherHandle() = default; - explicit WatcherHandle(MojoHandle value) : Handle(value) {} - - // Copying and assignment allowed. -}; - -static_assert(sizeof(WatcherHandle) == sizeof(Handle), - "Bad size for C++ WatcherHandle"); - -typedef ScopedHandleBase<WatcherHandle> ScopedWatcherHandle; -static_assert(sizeof(ScopedWatcherHandle) == sizeof(WatcherHandle), - "Bad size for C++ ScopedWatcherHandle"); - -MOJO_CPP_SYSTEM_EXPORT MojoResult -CreateWatcher(MojoWatcherCallback callback, - ScopedWatcherHandle* watcher_handle); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_SYSTEM_WATCHER_H_ diff --git a/mojo/public/cpp/test_support/BUILD.gn b/mojo/public/cpp/test_support/BUILD.gn deleted file mode 100644 index efa1712..0000000 --- a/mojo/public/cpp/test_support/BUILD.gn +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -static_library("test_utils") { - testonly = true - - sources = [ - "lib/test_support.cc", - "lib/test_utils.cc", - "test_utils.h", - ] - - deps = [ - "//mojo/public/c/test_support", - "//mojo/public/cpp/system", - "//testing/gtest", - ] -} diff --git a/mojo/public/cpp/test_support/lib/test_support.cc b/mojo/public/cpp/test_support/lib/test_support.cc deleted file mode 100644 index 0b6035b..0000000 --- a/mojo/public/cpp/test_support/lib/test_support.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/test_support/test_support.h" - -#include <stdlib.h> - -namespace mojo { -namespace test { - -std::vector<std::string> EnumerateSourceRootRelativeDirectory( - const std::string& relative_path) { - char** names = MojoTestSupportEnumerateSourceRootRelativeDirectory( - relative_path.c_str()); - std::vector<std::string> results; - for (char** ptr = names; *ptr != nullptr; ++ptr) { - results.push_back(*ptr); - free(*ptr); - } - free(names); - return results; -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/test_support/lib/test_utils.cc b/mojo/public/cpp/test_support/lib/test_utils.cc deleted file mode 100644 index 7fe6f02..0000000 --- a/mojo/public/cpp/test_support/lib/test_utils.cc +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#include "mojo/public/cpp/test_support/test_utils.h" - -#include <stddef.h> -#include <stdint.h> - -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/wait.h" -#include "mojo/public/cpp/test_support/test_support.h" - -namespace mojo { -namespace test { - -bool WriteTextMessage(const MessagePipeHandle& handle, - const std::string& text) { - MojoResult rv = WriteMessageRaw(handle, - text.data(), - static_cast<uint32_t>(text.size()), - nullptr, - 0, - MOJO_WRITE_MESSAGE_FLAG_NONE); - return rv == MOJO_RESULT_OK; -} - -bool ReadTextMessage(const MessagePipeHandle& handle, std::string* text) { - MojoResult rv; - bool did_wait = false; - - uint32_t num_bytes = 0, num_handles = 0; - for (;;) { - rv = ReadMessageRaw(handle, - nullptr, - &num_bytes, - nullptr, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - if (rv == MOJO_RESULT_SHOULD_WAIT) { - if (did_wait) { - assert(false); // Looping endlessly!? - return false; - } - rv = Wait(handle, MOJO_HANDLE_SIGNAL_READABLE); - if (rv != MOJO_RESULT_OK) - return false; - did_wait = true; - } else { - assert(!num_handles); - break; - } - } - - text->resize(num_bytes); - rv = ReadMessageRaw(handle, - &text->at(0), - &num_bytes, - nullptr, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - return rv == MOJO_RESULT_OK; -} - -bool DiscardMessage(const MessagePipeHandle& handle) { - MojoResult rv = ReadMessageRaw(handle, - nullptr, - nullptr, - nullptr, - nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); - return rv == MOJO_RESULT_OK; -} - -void IterateAndReportPerf(const char* test_name, - const char* sub_test_name, - PerfTestSingleIteration single_iteration, - void* closure) { - // TODO(vtl): These should be specifiable using command-line flags. - static const size_t kGranularity = 100; - static const MojoTimeTicks kPerftestTimeMicroseconds = 3 * 1000000; - - const MojoTimeTicks start_time = GetTimeTicksNow(); - MojoTimeTicks end_time; - size_t iterations = 0; - do { - for (size_t i = 0; i < kGranularity; i++) - (*single_iteration)(closure); - iterations += kGranularity; - - end_time = GetTimeTicksNow(); - } while (end_time - start_time < kPerftestTimeMicroseconds); - - MojoTestSupportLogPerfResult(test_name, sub_test_name, - 1000000.0 * iterations / (end_time - start_time), - "iterations/second"); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/public/cpp/test_support/test_support.h b/mojo/public/cpp/test_support/test_support.h deleted file mode 100644 index 9a536e6..0000000 --- a/mojo/public/cpp/test_support/test_support.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_ -#define MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_ - -#include <string> -#include <vector> - -#include "mojo/public/c/test_support/test_support.h" - -namespace mojo { -namespace test { - -inline void LogPerfResult(const char* test_name, - const char* sub_test_name, - double value, - const char* units) { - MojoTestSupportLogPerfResult(test_name, sub_test_name, value, units); -} - -// Opens text file relative to the source root for reading. -inline FILE* OpenSourceRootRelativeFile(const std::string& relative_path) { - return MojoTestSupportOpenSourceRootRelativeFile(relative_path.c_str()); -} - -// Returns the list of regular files in a directory relative to the source root. -std::vector<std::string> EnumerateSourceRootRelativeDirectory( - const std::string& relative_path); - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_ diff --git a/mojo/public/cpp/test_support/test_utils.h b/mojo/public/cpp/test_support/test_utils.h deleted file mode 100644 index 6fd5a9e..0000000 --- a/mojo/public/cpp/test_support/test_utils.h +++ /dev/null @@ -1,40 +0,0 @@ -// 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_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_ -#define MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_ - -#include <string> - -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace test { - -// Writes a message to |handle| with message data |text|. Returns true on -// success. -bool WriteTextMessage(const MessagePipeHandle& handle, const std::string& text); - -// Reads a message from |handle|, putting its contents into |*text|. Returns -// true on success. (This blocks if necessary and will call |MojoReadMessage()| -// multiple times, e.g., to query the size of the message.) -bool ReadTextMessage(const MessagePipeHandle& handle, std::string* text); - -// Discards a message from |handle|. Returns true on success. (This does not -// block. It will fail if no message is available to discard.) -bool DiscardMessage(const MessagePipeHandle& handle); - -// Run |single_iteration| an appropriate number of times and report its -// performance appropriately. (This actually runs |single_iteration| for a fixed -// amount of time and reports the number of iterations per unit time.) -typedef void (*PerfTestSingleIteration)(void* closure); -void IterateAndReportPerf(const char* test_name, - const char* sub_test_name, - PerfTestSingleIteration single_iteration, - void* closure); - -} // namespace test -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_ |