diff options
Diffstat (limited to 'utils/ipc/mojo/public/tools/bindings')
19 files changed, 0 insertions, 5156 deletions
diff --git a/utils/ipc/mojo/public/tools/bindings/BUILD.gn b/utils/ipc/mojo/public/tools/bindings/BUILD.gn deleted file mode 100644 index eeca73ea..00000000 --- a/utils/ipc/mojo/public/tools/bindings/BUILD.gn +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2016 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") -import("//third_party/jinja2/jinja2.gni") - -action("precompile_templates") { - sources = mojom_generator_sources - sources += [ - "$mojom_generator_root/generators/cpp_templates/cpp_macros.tmpl", - "$mojom_generator_root/generators/cpp_templates/enum_macros.tmpl", - "$mojom_generator_root/generators/cpp_templates/enum_serialization_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/feature_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/feature_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_feature_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_macros.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_proxy_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_request_validator_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_response_validator_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/interface_stub_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-features.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-forward.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-import-headers.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-params-data.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-shared-internal.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-shared-message-ids.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-shared.cc.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-shared.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module-test-utils.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/module.cc.tmpl", - "$mojom_generator_root/generators/cpp_templates/module.h.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_data_view_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_data_view_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_macros.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_traits_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_traits_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/struct_unserialized_message_context.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_data_view_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_data_view_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_serialization_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_traits_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/union_traits_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/validation_macros.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_class_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_class_template_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_declaration.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_definition.tmpl", - "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_template_definition.tmpl", - "$mojom_generator_root/generators/java_templates/constant_definition.tmpl", - "$mojom_generator_root/generators/java_templates/constants.java.tmpl", - "$mojom_generator_root/generators/java_templates/data_types_definition.tmpl", - "$mojom_generator_root/generators/java_templates/enum.java.tmpl", - "$mojom_generator_root/generators/java_templates/enum_definition.tmpl", - "$mojom_generator_root/generators/java_templates/header.java.tmpl", - "$mojom_generator_root/generators/java_templates/interface.java.tmpl", - "$mojom_generator_root/generators/java_templates/interface_definition.tmpl", - "$mojom_generator_root/generators/java_templates/interface_internal.java.tmpl", - "$mojom_generator_root/generators/java_templates/struct.java.tmpl", - "$mojom_generator_root/generators/java_templates/union.java.tmpl", - "$mojom_generator_root/generators/js_templates/enum_definition.tmpl", - "$mojom_generator_root/generators/js_templates/fuzzing.tmpl", - "$mojom_generator_root/generators/js_templates/interface_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/enum_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/enum_definition_for_module.tmpl", - "$mojom_generator_root/generators/js_templates/lite/interface_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/interface_definition_for_module.tmpl", - "$mojom_generator_root/generators/js_templates/lite/module_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/mojom-lite.js.tmpl", - "$mojom_generator_root/generators/js_templates/lite/mojom.m.js.tmpl", - "$mojom_generator_root/generators/js_templates/lite/struct_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/struct_definition_for_module.tmpl", - "$mojom_generator_root/generators/js_templates/lite/union_definition.tmpl", - "$mojom_generator_root/generators/js_templates/lite/union_definition_for_module.tmpl", - "$mojom_generator_root/generators/js_templates/module.amd.tmpl", - "$mojom_generator_root/generators/js_templates/module_definition.tmpl", - "$mojom_generator_root/generators/js_templates/struct_definition.tmpl", - "$mojom_generator_root/generators/js_templates/union_definition.tmpl", - "$mojom_generator_root/generators/js_templates/validation_macros.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm.cc.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm.h.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm.proto.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm_from_proto_macros.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm_macros.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm_to_proto_macros.tmpl", - "$mojom_generator_root/generators/mojolpm_templates/mojolpm_traits_specialization_macros.tmpl", - "$mojom_generator_root/generators/ts_templates/enum_definition.tmpl", - "$mojom_generator_root/generators/ts_templates/interface_definition.tmpl", - "$mojom_generator_root/generators/ts_templates/module_definition.tmpl", - "$mojom_generator_root/generators/ts_templates/struct_definition.tmpl", - "$mojom_generator_root/generators/ts_templates/union_definition.tmpl", - ] - script = mojom_generator_script - - inputs = jinja2_sources - outputs = [ - "$target_gen_dir/cpp_templates.zip", - "$target_gen_dir/java_templates.zip", - "$target_gen_dir/js_templates.zip", - "$target_gen_dir/mojolpm_templates.zip", - "$target_gen_dir/ts_templates.zip", - ] - args = [ - "-o", - rebase_path(target_gen_dir, root_build_dir), - "--use_bundled_pylibs", - "precompile", - ] -} - -group("tests") { - data = [ - mojom_generator_script, - "checks/mojom_attributes_check_unittest.py", - "checks/mojom_interface_feature_check_unittest.py", - "checks/mojom_restrictions_checks_unittest.py", - "mojom_bindings_generator_unittest.py", - "//tools/diagnosis/crbug_1001171.py", - "//third_party/markupsafe/", - ] - data += mojom_generator_sources - data += jinja2_sources -} diff --git a/utils/ipc/mojo/public/tools/bindings/README.md b/utils/ipc/mojo/public/tools/bindings/README.md deleted file mode 100644 index b27b2d01..00000000 --- a/utils/ipc/mojo/public/tools/bindings/README.md +++ /dev/null @@ -1,1014 +0,0 @@ -# Mojom Interface Definition Language (IDL) -This document is a subset of the [Mojo documentation](/mojo/README.md). - -[TOC] - -## Overview - -Mojom is the IDL for Mojo interfaces. Given a `.mojom` file, the -[bindings -generator](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/) can -output bindings for any supported language: **C++**, **JavaScript**, or -**Java**. - -For a trivial example consider the following hypothetical Mojom file we write to -`//services/widget/public/mojom/frobinator.mojom`: - -``` -module widget.mojom; - -interface Frobinator { - Frobinate(); -}; -``` - -This defines a single [interface](#Interfaces) named `Frobinator` in a -[module](#Modules) named `widget.mojom` (and thus fully qualified in Mojom as -`widget.mojom.Frobinator`.) Note that many interfaces and/or other types of -definitions (structs, enums, *etc.*) may be included in a single Mojom file. - -If we add a corresponding GN target to -`//services/widget/public/mojom/BUILD.gn`: - -``` -import("mojo/public/tools/bindings/mojom.gni") - -mojom("mojom") { - sources = [ - "frobinator.mojom", - ] -} -``` - -and then build this target: - -``` -ninja -C out/r services/widget/public/mojom -``` - -we'll find several generated sources in our output directory: - -``` -out/r/gen/services/widget/public/mojom/frobinator.mojom.cc -out/r/gen/services/widget/public/mojom/frobinator.mojom.h -out/r/gen/services/widget/public/mojom/frobinator.mojom-shared.h -etc... -``` - -Each of these generated source modules includes a set of definitions -representing the Mojom contents in C++. You can also build or depend on suffixed -target names to get bindings for other languages. For example, - -``` -ninja -C out/r services/widget/public/mojom:mojom_js -ninja -C out/r services/widget/public/mojom:mojom_java -``` - -would generate JavaScript and Java bindings respectively, in the same generated -output directory. - -For more details regarding the generated -outputs please see -[documentation for individual target languages](#Generated-Code-For-Target-Languages). - -## Mojom Syntax - -Mojom IDL allows developers to define **structs**, **unions**, **interfaces**, -**constants**, and **enums**, all within the context of a **module**. These -definitions are used to generate code in the supported target languages at build -time. - -Mojom files may **import** other Mojom files in order to reference their -definitions. - -### Primitive Types -Mojom supports a few basic data types which may be composed into structs or used -for message parameters. - -| Type | Description -|-------------------------------|-------------------------------------------------------| -| `bool` | Boolean type (`true` or `false`.) -| `int8`, `uint8` | Signed or unsigned 8-bit integer. -| `int16`, `uint16` | Signed or unsigned 16-bit integer. -| `int32`, `uint32` | Signed or unsigned 32-bit integer. -| `int64`, `uint64` | Signed or unsigned 64-bit integer. -| `float`, `double` | 32- or 64-bit floating point number. -| `string` | UTF-8 encoded string. -| `array<T>` | Array of any Mojom type *T*; for example, `array<uint8>` or `array<array<string>>`. -| `array<T, N>` | Fixed-length array of any Mojom type *T*. The parameter *N* must be an integral constant. -| `map<S, T>` | Associated array mapping values of type *S* to values of type *T*. *S* may be a `string`, `enum`, or numeric type. -| `handle` | Generic Mojo handle. May be any type of handle, including a wrapped native platform handle. -| `handle<message_pipe>` | Generic message pipe handle. -| `handle<shared_buffer>` | Shared buffer handle. -| `handle<data_pipe_producer>` | Data pipe producer handle. -| `handle<data_pipe_consumer>` | Data pipe consumer handle. -| `handle<platform>` | A native platform/OS handle. -| *`pending_remote<InterfaceType>`* | Any user-defined Mojom interface type. This is sugar for a strongly-typed message pipe handle which should eventually be used to make outgoing calls on the interface. -| *`pending_receiver<InterfaceType>`* | A pending receiver for any user-defined Mojom interface type. This is sugar for a more strongly-typed message pipe handle which is expected to receive request messages and should therefore eventually be bound to an implementation of the interface. -| *`pending_associated_remote<InterfaceType>`* | An associated interface handle. See [Associated Interfaces](#Associated-Interfaces) -| *`pending_associated_receiver<InterfaceType>`* | A pending associated receiver. See [Associated Interfaces](#Associated-Interfaces) -| *T*? | An optional (nullable) value. Primitive numeric types (integers, floats, booleans, and enums) are not nullable. All other types are nullable. - -### Modules - -Every Mojom file may optionally specify a single **module** to which it belongs. - -This is used strictly for aggregating all defined symbols therein within a -common Mojom namespace. The specific impact this has on generated bindings code -varies for each target language. For example, if the following Mojom is used to -generate bindings: - -``` -module business.stuff; - -interface MoneyGenerator { - GenerateMoney(); -}; -``` - -Generated C++ bindings will define a class interface `MoneyGenerator` in the -`business::stuff` namespace, while Java bindings will define an interface -`MoneyGenerator` in the `org.chromium.business.stuff` package. JavaScript -bindings at this time are unaffected by module declarations. - -**NOTE:** By convention in the Chromium codebase, **all** Mojom files should -declare a module name with at least (and preferably exactly) one top-level name -as well as an inner `mojom` module suffix. *e.g.*, `chrome.mojom`, -`business.mojom`, *etc.* - -This convention makes it easy to tell which symbols are generated by Mojom when -reading non-Mojom code, and it also avoids namespace collisions in the fairly -common scenario where you have a real C++ or Java `Foo` along with a -corresponding Mojom `Foo` for its serialized representation. - -### Imports - -If your Mojom references definitions from other Mojom files, you must **import** -those files. Import syntax is as follows: - -``` -import "services/widget/public/mojom/frobinator.mojom"; -``` - -Import paths are always relative to the top-level directory. - -Note that circular imports are **not** supported. - -### Structs - -Structs are defined using the **struct** keyword, and they provide a way to -group related fields together: - -``` cpp -struct StringPair { - string first; - string second; -}; -``` - -Struct fields may be comprised of any of the types listed above in the -[Primitive Types](#Primitive-Types) section. - -Default values may be specified as long as they are constant: - -``` cpp -struct Request { - int32 id = -1; - string details; -}; -``` - -What follows is a fairly -comprehensive example using the supported field types: - -``` cpp -struct StringPair { - string first; - string second; -}; - -enum AnEnum { - kYes, - kNo -}; - -interface SampleInterface { - DoStuff(); -}; - -struct AllTheThings { - // Note that these types can never be marked nullable! - bool boolean_value; - int8 signed_8bit_value = 42; - uint8 unsigned_8bit_value; - int16 signed_16bit_value; - uint16 unsigned_16bit_value; - int32 signed_32bit_value; - uint32 unsigned_32bit_value; - int64 signed_64bit_value; - uint64 unsigned_64bit_value; - float float_value_32bit; - double float_value_64bit; - AnEnum enum_value = AnEnum.kYes; - - // Strings may be nullable. - string? maybe_a_string_maybe_not; - - // Structs may contain other structs. These may also be nullable. - StringPair some_strings; - StringPair? maybe_some_more_strings; - - // In fact structs can also be nested, though in practice you must always make - // such fields nullable -- otherwise messages would need to be infinitely long - // in order to pass validation! - AllTheThings? more_things; - - // Arrays may be templated over any Mojom type, and are always nullable: - array<int32> numbers; - array<int32>? maybe_more_numbers; - - // Arrays of arrays of arrays... are fine. - array<array<array<AnEnum>>> this_works_but_really_plz_stop; - - // The element type may be nullable if it's a type which is allowed to be - // nullable. - array<AllTheThings?> more_maybe_things; - - // Fixed-size arrays get some extra validation on the receiving end to ensure - // that the correct number of elements is always received. - array<uint64, 2> uuid; - - // Maps follow many of the same rules as arrays. Key types may be any - // non-handle, non-collection type, and value types may be any supported - // struct field type. Maps may also be nullable. - map<string, int32> one_map; - map<AnEnum, string>? maybe_another_map; - map<StringPair, AllTheThings?>? maybe_a_pretty_weird_but_valid_map; - map<StringPair, map<int32, array<map<string, string>?>?>?> ridiculous; - - // And finally, all handle types are valid as struct fields and may be - // nullable. Note that interfaces and interface requests (the "Foo" and - // "Foo&" type syntax respectively) are just strongly-typed message pipe - // handles. - handle generic_handle; - handle<data_pipe_consumer> reader; - handle<data_pipe_producer>? maybe_writer; - handle<shared_buffer> dumping_ground; - handle<message_pipe> raw_message_pipe; - pending_remote<SampleInterface>? maybe_a_sample_interface_client_pipe; - pending_receiver<SampleInterface> non_nullable_sample_pending_receiver; - pending_receiver<SampleInterface>? nullable_sample_pending_receiver; - pending_associated_remote<SampleInterface> associated_interface_client; - pending_associated_receiver<SampleInterface> associated_pending_receiver; - pending_associated_receiver<SampleInterface>? maybe_another_pending_receiver; -}; -``` - -For details on how all of these different types translate to usable generated -code, see -[documentation for individual target languages](#Generated-Code-For-Target-Languages). - -### Unions - -Mojom supports tagged unions using the **union** keyword. A union is a -collection of fields which may take the value of any single one of those fields -at a time. Thus they provide a way to represent a variant value type while -minimizing storage requirements. - -Union fields may be of any type supported by [struct](#Structs) fields. For -example: - -```cpp -union ExampleUnion { - string str; - StringPair pair; - int64 id; - array<uint64, 2> guid; - SampleInterface iface; -}; -``` - -For details on how unions like this translate to generated bindings code, see -[documentation for individual target languages](#Generated-Code-For-Target-Languages). - -### Enumeration Types - -Enumeration types may be defined using the **enum** keyword either directly -within a module or nested within the namespace of some struct or interface: - -``` -module business.mojom; - -enum Department { - kSales = 0, - kDev, -}; - -struct Employee { - enum Type { - kFullTime, - kPartTime, - }; - - Type type; - // ... -}; -``` - -C++ constant-style enum value names are preferred as specified in the -[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html#Enumerator_Names). - -Similar to C-style enums, individual values may be explicitly assigned within an -enum definition. By default, values are based at zero and increment by -1 sequentially. - -The effect of nested definitions on generated bindings varies depending on the -target language. See [documentation for individual target languages](#Generated-Code-For-Target-Languages). - -### Constants - -Constants may be defined using the **const** keyword either directly within a -module or nested within the namespace of some struct or interface: - -``` -module business.mojom; - -const string kServiceName = "business"; - -struct Employee { - const uint64 kInvalidId = 0; - - enum Type { - kFullTime, - kPartTime, - }; - - uint64 id = kInvalidId; - Type type; -}; -``` - -The effect of nested definitions on generated bindings varies depending on the -target language. See [documentation for individual target languages](#Generated-Code-For-Target-Languages). - -### Features - -Features can be declared with a `name` and `default_state` and can be attached -in mojo to interfaces or methods using the `RuntimeFeature` attribute. If the -feature is disabled at runtime, the method will crash and the interface will -refuse to be bound / instantiated. Features cannot be serialized to be sent over -IPC at this time. - -``` -module experimental.mojom; - -feature kUseElevators { - const string name = "UseElevators"; - const bool default_state = false; -} - -[RuntimeFeature=kUseElevators] -interface Elevator { - // This interface cannot be bound or called if the feature is disabled. -} - -interface Building { - // This method cannot be called if the feature is disabled. - [RuntimeFeature=kUseElevators] - CallElevator(int floor); - - // This method can be called. - RingDoorbell(int volume); -} -``` - -### Interfaces - -An **interface** is a logical bundle of parameterized request messages. Each -request message may optionally define a parameterized response message. Here's -an example to define an interface `Foo` with various kinds of requests: - -``` -interface Foo { - // A request which takes no arguments and expects no response. - MyMessage(); - - // A request which has some arguments and expects no response. - MyOtherMessage(string name, array<uint8> bytes); - - // A request which expects a single-argument response. - MyMessageWithResponse(string command) => (bool success); - - // A request which expects a response with multiple arguments. - MyMessageWithMoarResponse(string a, string b) => (int8 c, int8 d); -}; -``` - -Anything which is a valid struct field type (see [Structs](#Structs)) is also a -valid request or response argument type. The type notation is the same for both. - -### Attributes - -Mojom definitions may have their meaning altered by **attributes**, specified -with a syntax similar to Java or C# attributes. There are a handle of -interesting attributes supported today. - -* **`[Sync]`**: - The `Sync` attribute may be specified for any interface method which expects a - response. This makes it so that callers of the method can wait synchronously - for a response. See [Synchronous - Calls](/mojo/public/cpp/bindings/README.md#Synchronous-Calls) in the C++ - bindings documentation. Note that sync methods are only actually synchronous - when called from C++. - -* **`[NoInterrupt]`**: - When a thread is waiting for a reply to a `Sync` message, it's possible to be - woken up to dispatch other unrelated incoming `Sync` messages. This measure - helps to avoid deadlocks. If a `Sync` message is also marked as `NoInterrupt` - however, this behavior is disabled: instead the calling thread will only wake - up for the precise message being waited upon. This attribute must be used with - extreme caution, because it can lead to deadlocks otherwise. - -* **`[Default]`**: - The `Default` attribute may be used to specify an enumerator value or union - field that will be used if an `Extensible` enumeration or union does not - deserialize to a known value on the receiver side, i.e. the sender is using a - newer version of the enum or union. This allows unknown values to be mapped to - a well-defined value that can be appropriately handled. - - Note: The `Default` field for a union must be of nullable or integral type. - When a union is defaulted to this field, the field takes on the default value - for its type: null for nullable types, and zero/false for integral types. - -* **`[Extensible]`**: - The `Extensible` attribute may be specified for any enum or union definition. - For enums, this essentially disables builtin range validation when receiving - values of the enum type in a message, allowing older bindings to tolerate - unrecognized values from newer versions of the enum. - - If an enum value within an extensible enum definition is affixed with the - `Default` attribute, out-of-range values for the enum will deserialize to that - default value. Only one enum value may be designated as the `Default`. - - Similarly, a union marked `Extensible` will deserialize to its `Default` field - when an unrecognized field is received. Extensible unions MUST specify exactly - one `Default` field, and the field must be of nullable or integral type. When - defaulted to this field, the value is always null/zero/false as appropriate. - - An `Extensible` enumeration REQUIRES that a `Default` value be specified, - so all new extensible enums should specify one. - -* **`[Native]`**: - The `Native` attribute may be specified for an empty struct declaration to - provide a nominal bridge between Mojo IPC and legacy `IPC::ParamTraits` or - `IPC_STRUCT_TRAITS*` macros. See [Repurposing Legacy IPC - Traits](/docs/mojo_ipc_conversion.md#repurposing-and-invocations) for more - details. Note support for this attribute is strictly limited to C++ bindings - generation. - -* **`[MinVersion=N]`**: - The `MinVersion` attribute is used to specify the version at which a given - field, enum value, interface method, or method parameter was introduced. - See [Versioning](#Versioning) for more details. `MinVersion` does not apply - to interfaces, structs or enums, but to the fields of those types. - `MinVersion` is not a module-global value, but it is ok to pretend it is by - skipping versions when adding fields or parameters. - -* **`[Stable]`**: - The `Stable` attribute specifies that a given mojom type or interface - definition can be considered stable over time, meaning it is safe to use for - things like persistent storage or communication between independent - version-skewed binaries. Stable definitions may only depend on builtin mojom - types or other stable definitions, and changes to such definitions MUST - preserve backward-compatibility through appropriate use of versioning. - Backward-compatibility of changes is enforced in the Chromium tree using a - strict presubmit check. See [Versioning](#Versioning) for more details on - backward-compatibility constraints. - -* **`[Uuid=<UUID>]`**: - Specifies a UUID to be associated with a given interface. The UUID is intended - to remain stable across all changes to the interface definition, including - name changes. The value given for this attribute should be a standard UUID - string representation as specified by RFC 4122. New UUIDs can be generated - with common tools such as `uuidgen`. - -* **`[RuntimeFeature=feature]`** - The `RuntimeFeature` attribute should reference a mojo `feature`. If this - feature is enabled (e.g. using `--enable-features={feature.name}`) then the - interface behaves entirely as expected. If the feature is not enabled the - interface cannot be bound to a concrete receiver or remote - attempting to do - so will result in the receiver or remote being reset() to an unbound state. - Note that this is a different concept to the build-time `EnableIf` directive. - `RuntimeFeature` is currently only supported for C++ bindings and has no - effect for, say, Java or TypeScript bindings (see https://crbug.com/1278253). - -* **`[EnableIf=value]`**: - The `EnableIf` attribute is used to conditionally enable definitions when the - mojom is parsed. If the `mojom` target in the GN file does not include the - matching `value` in the list of `enabled_features`, the definition will be - disabled. This is useful for mojom definitions that only make sense on one - platform. Note that the `EnableIf` attribute can only be set once per - definition and cannot be set at the same time as `EnableIfNot`. Also be aware - that only one condition can be tested, `EnableIf=value,xyz` introduces a new - `xyz` attribute. `xyz` is not part of the `EnableIf` condition that depends - only on the feature `value`. Complex conditions can be introduced via - enabled_features in `build.gn` files. - -* **`[EnableIfNot=value]`**: - The `EnableIfNot` attribute is used to conditionally enable definitions when - the mojom is parsed. If the `mojom` target in the GN file includes the - matching `value` in the list of `enabled_features`, the definition will be - disabled. This is useful for mojom definitions that only make sense on all but - one platform. Note that the `EnableIfNot` attribute can only be set once per - definition and cannot be set at the same time as `EnableIf`. - -* **`[ServiceSandbox=value]`**: - The `ServiceSandbox` attribute is used in Chromium to tag which sandbox a - service hosting an implementation of interface will be launched in. This only - applies to `C++` bindings. `value` should match a constant defined in an - imported `sandbox.mojom.Sandbox` enum (for Chromium this is - `//sandbox/policy/mojom/sandbox.mojom`), such as `kService`. - -* **`[RequireContext=enum]`**: - The `RequireContext` attribute is used in Chromium to tag interfaces that - should be passed (as remotes or receivers) only to privileged process - contexts. The process context must be an enum that is imported into the - mojom that defines the tagged interface. `RequireContext` may be used in - future to DCHECK or CHECK if remotes are made available in contexts that - conflict with the one provided in the interface definition. Process contexts - are not the same as the sandbox a process is running in, but will reflect - the set of capabilities provided to the service. - -* **`[AllowedContext=enum]`**: - The `AllowedContext` attribute is used in Chromium to tag methods that pass - remotes or receivers of interfaces that are marked with a `RequireContext` - attribute. The enum provided on the method must be equal or better (lower - numerically) than the one required on the interface being passed. At present - failing to specify an adequate `AllowedContext` value will cause mojom - generation to fail at compile time. In future DCHECKs or CHECKs might be - added to enforce that method is only called from a process context that meets - the given `AllowedContext` value. The enum must of the same type as that - specified in the interface's `RequireContext` attribute. Adding an - `AllowedContext` attribute to a method is a strong indication that you need - a detailed security review of your design - please reach out to the security - team. - -* **`[SupportsUrgent]`**: - The `SupportsUrgent` attribute is used in conjunction with - `mojo::UrgentMessageScope` in Chromium to tag messages as having high - priority. The IPC layer notifies the underlying scheduler upon both receiving - and processing an urgent message. At present, this attribute only affects - channel associated messages in the renderer process. - -## Generated Code For Target Languages - -When the bindings generator successfully processes an input Mojom file, it emits -corresponding code for each supported target language. For more details on how -Mojom concepts translate to a given target language, please refer to the -bindings API documentation for that language: - -* [C++ Bindings](/mojo/public/cpp/bindings/README.md) -* [JavaScript Bindings](/mojo/public/js/README.md) -* [Java Bindings](/mojo/public/java/bindings/README.md) - -## Message Validation - -Regardless of target language, all interface messages are validated during -deserialization before they are dispatched to a receiving implementation of the -interface. This helps to ensure consistent validation across interfaces without -leaving the burden to developers and security reviewers every time a new message -is added. - -If a message fails validation, it is never dispatched. Instead a **connection -error** is raised on the binding object (see -[C++ Connection Errors](/mojo/public/cpp/bindings/README.md#Connection-Errors), -[Java Connection Errors](/mojo/public/java/bindings/README.md#Connection-Errors), -or -[JavaScript Connection Errors](/mojo/public/js/README.md#Connection-Errors) for -details.) - -Some baseline level of validation is done automatically for primitive Mojom -types. - -### Non-Nullable Objects - -Mojom fields or parameter values (*e.g.*, structs, interfaces, arrays, *etc.*) -may be marked nullable in Mojom definitions (see -[Primitive Types](#Primitive-Types).) If a field or parameter is **not** marked -nullable but a message is received with a null value in its place, that message -will fail validation. - -### Enums - -Enums declared in Mojom are automatically validated against the range of legal -values. For example if a Mojom declares the enum: - -``` cpp -enum AdvancedBoolean { - kTrue = 0, - kFalse = 1, - kFileNotFound = 2, -}; -``` - -and a message is received with the integral value 3 (or anything other than 0, -1, or 2) in place of some `AdvancedBoolean` field or parameter, the message will -fail validation. - -*** note -NOTE: It's possible to avoid this type of validation error by explicitly marking -an enum as [Extensible](#Attributes) if you anticipate your enum being exchanged -between two different versions of the binding interface. See -[Versioning](#Versioning). -*** - -### Other failures - -There are a host of internal validation errors that may occur when a malformed -message is received, but developers should not be concerned with these -specifically; in general they can only result from internal bindings bugs, -compromised processes, or some remote endpoint making a dubious effort to -manually encode their own bindings messages. - -### Custom Validation - -It's also possible for developers to define custom validation logic for specific -Mojom struct types by exploiting the -[type mapping](/mojo/public/cpp/bindings/README.md#Type-Mapping) system for C++ -bindings. Messages rejected by custom validation logic trigger the same -validation failure behavior as the built-in type validation routines. - -## Associated Interfaces - -As mentioned in the [Primitive Types](#Primitive-Types) section above, pending_remote -and pending_receiver fields and parameters may be marked as `associated`. This -essentially means that they are piggy-backed on some other interface's message -pipe. - -Because individual interface message pipes operate independently there can be no -relative ordering guarantees among them. Associated interfaces are useful when -one interface needs to guarantee strict FIFO ordering with respect to one or -more other interfaces, as they allow interfaces to share a single pipe. - -Currently associated interfaces are only supported in generated C++ bindings. -See the documentation for -[C++ Associated Interfaces](/mojo/public/cpp/bindings/README.md#Associated-Interfaces). - -## Versioning - -### Overview - -*** note -**NOTE:** You don't need to worry about versioning if you don't care about -backwards compatibility. Today, all parts of the Chrome browser are -updated atomically and there is not yet any possibility of any two -Chrome processes communicating with two different versions of any given Mojom -interface. On Chrome OS, there are several places where versioning is required. -For example, -[ARC++](https://developer.android.com/chrome-os/intro) -uses versioned mojo to send IPC to the Android container. -Likewise, the -[Lacros](/docs/lacros.md) -browser uses versioned mojo to talk to the ash system UI. -*** - -Services extend their interfaces to support new features over time, and clients -want to use those new features when they are available. If services and clients -are not updated at the same time, it's important for them to be able to -communicate with each other using different snapshots (versions) of their -interfaces. - -This document shows how to extend Mojom interfaces in a backwards-compatible -way. Changing interfaces in a non-backwards-compatible way is not discussed, -because in that case communication between different interface versions is -impossible anyway. - -### Versioned Structs - -You can use the `MinVersion` [attribute](#Attributes) to indicate from which -version a struct field is introduced. Assume you have the following struct: - -``` cpp -struct Employee { - uint64 employee_id; - string name; -}; -``` - -and you would like to add birthday and nickname fields. You can add them as -optional types with a `MinVersion` like so: - -``` cpp -struct Employee { - uint64 employee_id; - string name; - [MinVersion=1] Date? birthday; - [MinVersion=1] string? nickname; -}; -``` - -*** note -**NOTE:** Mojo object or handle types added with a `MinVersion` **MUST** be -optional (nullable) or primitive. See [Primitive Types](#Primitive-Types) for -details on nullable values. -*** - -By default, fields belong to version 0. New fields must be appended to the -struct definition (*i.e*., existing fields must not change **ordinal value**) -with the `MinVersion` attribute set to a number greater than any previous -existing versions. - -The value of `MinVersion` is unrelated to ordinals. The choice of a particular -version number is arbitrary. All its usage means is that a field isn't present -before the numbered version. - -*** note -**NOTE:** do not change existing fields in versioned structs, as this is -not backwards-compatible. Instead, rename the old field to make its -deprecation clear and add a new field with a new `MinVersion` number. -*** - -**Ordinal value** refers to the relative positional layout of a struct's fields -(and an interface's methods) when encoded in a message. Implicitly, ordinal -numbers are assigned to fields according to lexical position. In the example -above, `employee_id` has an ordinal value of 0 and `name` has an ordinal value -of 1. - -Ordinal values can be specified explicitly using `**@**` notation, subject to -the following hard constraints: - -* For any given struct or interface, if any field or method explicitly specifies - an ordinal value, all fields or methods must explicitly specify an ordinal - value. -* For an *N*-field struct, the set of explicitly assigned ordinal values must be - limited to the range *[0, N-1]*. Structs should include placeholder fields - to fill the ordinal positions of removed fields (for example "Unused_Field" - or "RemovedField", etc). - -You may reorder fields, but you must ensure that the ordinal values of existing -fields remain unchanged. For example, the following struct remains -backwards-compatible: - -``` cpp -struct Employee { - uint64 employee_id@0; - [MinVersion=1] Date? birthday@2; - string name@1; - [MinVersion=1] string? nickname@3; -}; -``` - -### Versioned Interfaces - -There are two dimensions on which an interface can be extended - -**Appending New Parameters To Existing Methods** -: Parameter lists are treated as structs internally, so all the rules of - versioned structs apply to method parameter lists. The only difference is - that the version number is scoped to the whole interface rather than to any - individual parameter list. - -``` cpp -// Old version: -interface HumanResourceDatabase { - QueryEmployee(uint64 id) => (Employee? employee); -}; - -// New version: -interface HumanResourceDatabase { - QueryEmployee(uint64 id, [MinVersion=1] bool retrieve_finger_print) - => (Employee? employee, - [MinVersion=1] array<uint8>? finger_print); -}; -``` - -Similar to [versioned structs](#Versioned-Structs), when you pass the parameter -list of a request or response method to a destination using an older version of -an interface, unrecognized fields are silently discarded. - - Please note that adding a response to a message which did not previously - expect a response is a not a backwards-compatible change. - -**Appending New Methods** -: Similarly, you can reorder methods with explicit ordinal values as long as - the ordinal values of existing methods are unchanged. - -For example: - -``` cpp -// Old version: -interface HumanResourceDatabase { - QueryEmployee(uint64 id) => (Employee? employee); -}; - -// New version: -interface HumanResourceDatabase { - QueryEmployee(uint64 id) => (Employee? employee); - - [MinVersion=1] - AttachFingerPrint(uint64 id, array<uint8> finger_print) - => (bool success); -}; -``` - -If a method call is not recognized, it is considered a validation error and the -receiver will close its end of the interface pipe. For example, if a client on -version 1 of the above interface sends an `AttachFingerPrint` request to an -implementation of version 0, the client will be disconnected. - -Bindings target languages that support versioning expose means to query or -assert the remote version from a client handle (*e.g.*, an -`mojo::Remote<T>` in C++ bindings.) - -See -[C++ Versioning Considerations](/mojo/public/cpp/bindings/README.md#Versioning-Considerations) -and -[Java Versioning Considerations](/mojo/public/java/bindings/README.md#Versioning-Considerations) - -### Versioned Enums - -**By default, enums are non-extensible**, which means that generated message -validation code does not expect to see new values in the future. When an unknown -value is seen for a non-extensible enum field or parameter, a validation error -is raised. - -If you want an enum to be extensible in the future, you can apply the -`[Extensible]` [attribute](#Attributes): - -``` cpp -[Extensible] -enum Department { - kSales, - kDev, -}; -``` - -And later you can extend this enum without breaking backwards compatibility: - -``` cpp -[Extensible] -enum Department { - kSales, - kDev, - [MinVersion=1] kResearch, -}; -``` - -*** note -**NOTE:** For versioned enum definitions, the use of a `[MinVersion]` attribute -is strictly for documentation purposes. It has no impact on the generated code. -*** - -With extensible enums, bound interface implementations may receive unknown enum -values and will need to deal with them gracefully. See -[C++ Versioning Considerations](/mojo/public/cpp/bindings/README.md#Versioning-Considerations) -for details. - -### Renaming versioned structs -It's possible to rename versioned structs by using the `[RenamedFrom]` attribute. -RenamedFrom - -``` cpp -module asdf.mojom; - -// Old version: -[Stable] -struct OldStruct { -}; - -// New version: -[Stable, RenamedFrom="asdf.mojom.OldStruct"] -struct NewStruct { -}; -``` - -## Component targets - -If there are multiple components depending on the same mojom target within one binary, -the target will need to be defined as `mojom_component` instead of `mojom`. -Since `mojom` targets are generated `source_set` targets and `mojom_component` targets -are generated `component` targets, you would use `mojom_component` in the same cases -where you would use `component` for non-mojom files. -*** note -**NOTE**: by default, components for both blink and non-blink bindings are generated. -Use the `disable_variants` target parameter to generate only non-blink bindings. -You can also generate a `source_set` for one of the variants by defining -[export_*](https://source.chromium.org/chromium/chromium/src/+/main:mojo/public/tools/bindings/mojom.gni;drc=739b9fbce50310c1dd2b59c279cd90a9319cb6e8;l=318) -parameters for the `mojom_component` target. -*** - -## Grammar Reference - -Below is the (BNF-ish) context-free grammar of the Mojom language: - -``` -MojomFile = StatementList -StatementList = Statement StatementList | Statement -Statement = ModuleStatement | ImportStatement | Definition - -ModuleStatement = AttributeSection "module" Identifier ";" -ImportStatement = "import" StringLiteral ";" -Definition = Struct Union Interface Enum Feature Const - -AttributeSection = <empty> | "[" AttributeList "]" -AttributeList = <empty> | NonEmptyAttributeList -NonEmptyAttributeList = Attribute - | Attribute "," NonEmptyAttributeList -Attribute = Name - | Name "=" Name - | Name "=" Literal - -Struct = AttributeSection "struct" Name "{" StructBody "}" ";" - | AttributeSection "struct" Name ";" -StructBody = <empty> - | StructBody Const - | StructBody Enum - | StructBody StructField -StructField = AttributeSection TypeSpec Name Ordinal Default ";" - -Union = AttributeSection "union" Name "{" UnionBody "}" ";" -UnionBody = <empty> | UnionBody UnionField -UnionField = AttributeSection TypeSpec Name Ordinal ";" - -Interface = AttributeSection "interface" Name "{" InterfaceBody "}" ";" -InterfaceBody = <empty> - | InterfaceBody Const - | InterfaceBody Enum - | InterfaceBody Method -Method = AttributeSection Name Ordinal "(" ParameterList ")" Response ";" -ParameterList = <empty> | NonEmptyParameterList -NonEmptyParameterList = Parameter - | Parameter "," NonEmptyParameterList -Parameter = AttributeSection TypeSpec Name Ordinal -Response = <empty> | "=>" "(" ParameterList ")" - -TypeSpec = TypeName "?" | TypeName -TypeName = BasicTypeName - | Array - | FixedArray - | Map - | InterfaceRequest -BasicTypeName = Identifier | "associated" Identifier | HandleType | NumericType -NumericType = "bool" | "int8" | "uint8" | "int16" | "uint16" | "int32" - | "uint32" | "int64" | "uint64" | "float" | "double" -HandleType = "handle" | "handle" "<" SpecificHandleType ">" -SpecificHandleType = "message_pipe" - | "shared_buffer" - | "data_pipe_consumer" - | "data_pipe_producer" - | "platform" -Array = "array" "<" TypeSpec ">" -FixedArray = "array" "<" TypeSpec "," IntConstDec ">" -Map = "map" "<" Identifier "," TypeSpec ">" -InterfaceRequest = Identifier "&" | "associated" Identifier "&" - -Ordinal = <empty> | OrdinalValue - -Default = <empty> | "=" Constant - -Enum = AttributeSection "enum" Name "{" NonEmptyEnumValueList "}" ";" - | AttributeSection "enum" Name "{" NonEmptyEnumValueList "," "}" ";" -NonEmptyEnumValueList = EnumValue | NonEmptyEnumValueList "," EnumValue -EnumValue = AttributeSection Name - | AttributeSection Name "=" Integer - | AttributeSection Name "=" Identifier - -; Note: `feature` is a weak keyword and can appear as, say, a struct field name. -Feature = AttributeSection "feature" Name "{" FeatureBody "}" ";" - | AttributeSection "feature" Name ";" -FeatureBody = <empty> - | FeatureBody FeatureField -FeatureField = AttributeSection TypeSpec Name Default ";" - -Const = "const" TypeSpec Name "=" Constant ";" - -Constant = Literal | Identifier ";" - -Identifier = Name | Name "." Identifier - -Literal = Integer | Float | "true" | "false" | "default" | StringLiteral - -Integer = IntConst | "+" IntConst | "-" IntConst -IntConst = IntConstDec | IntConstHex - -Float = FloatConst | "+" FloatConst | "-" FloatConst - -; The rules below are for tokens matched strictly according to the given regexes - -Identifier = /[a-zA-Z_][0-9a-zA-Z_]*/ -IntConstDec = /0|(1-9[0-9]*)/ -IntConstHex = /0[xX][0-9a-fA-F]+/ -OrdinalValue = /@(0|(1-9[0-9]*))/ -FloatConst = ... # Imagine it's close enough to C-style float syntax. -StringLiteral = ... # Imagine it's close enough to C-style string literals, including escapes. -``` - -## Additional Documentation - -[Mojom Message Format](https://docs.google.com/document/d/13pv9cFh5YKuBggDBQ1-AL8VReF-IYpFOFpRfvWFrwio/edit) -: Describes the wire format used by Mojo bindings interfaces over message - pipes. - -[Input Format of Mojom Message Validation Tests](https://docs.google.com/document/d/1-y-2IYctyX2NPaLxJjpJfzVNWCC2SR2MJAD9MpIytHQ/edit) -: Describes a text format used to facilitate bindings message validation - tests. diff --git a/utils/ipc/mojo/public/tools/bindings/checks/__init__.py b/utils/ipc/mojo/public/tools/bindings/checks/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/__init__.py +++ /dev/null diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check.py deleted file mode 100644 index e6e4f2c9..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Validate mojo attributes are allowed in Chrome before generation.""" - -import mojom.generate.check as check -import mojom.generate.module as module - -_COMMON_ATTRIBUTES = { - 'EnableIf', - 'EnableIfNot', -} - -# For struct, union & parameter lists. -_COMMON_FIELD_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'MinVersion', - 'RenamedFrom', -} - -# Note: `Default`` goes on the default _value_, not on the enum. -# Note: [Stable] without [Extensible] is not allowed. -_ENUM_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'Extensible', - 'Native', - 'Stable', - 'RenamedFrom', - 'Uuid', -} - -# TODO(crbug.com/1234883) MinVersion is not needed for EnumVal. -_ENUMVAL_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'Default', - 'MinVersion', -} - -_INTERFACE_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'RenamedFrom', - 'RequireContext', - 'RuntimeFeature', - 'ServiceSandbox', - 'Stable', - 'Uuid', -} - -_METHOD_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'AllowedContext', - 'MinVersion', - 'NoInterrupt', - 'RuntimeFeature', - 'SupportsUrgent', - 'Sync', - 'UnlimitedSize', -} - -_MODULE_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'JavaConstantsClassName', - 'JavaPackage', -} - -_PARAMETER_ATTRIBUTES = _COMMON_FIELD_ATTRIBUTES - -_STRUCT_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'CustomSerializer', - 'JavaClassName', - 'Native', - 'Stable', - 'RenamedFrom', - 'Uuid', -} - -_STRUCT_FIELD_ATTRIBUTES = _COMMON_FIELD_ATTRIBUTES - -_UNION_ATTRIBUTES = _COMMON_ATTRIBUTES | { - 'Extensible', - 'Stable', - 'RenamedFrom', - 'Uuid', -} - -_UNION_FIELD_ATTRIBUTES = _COMMON_FIELD_ATTRIBUTES | { - 'Default', -} - -# TODO(https://crbug.com/1193875) empty this set and remove the allowlist. -_STABLE_ONLY_ALLOWLISTED_ENUMS = { - 'crosapi.mojom.OptionalBool', - 'crosapi.mojom.TriState', -} - - -class Check(check.Check): - def __init__(self, *args, **kwargs): - super(Check, self).__init__(*args, **kwargs) - - def _Respell(self, allowed, attribute): - for a in allowed: - if a.lower() == attribute.lower(): - return f" - Did you mean: {a}?" - return "" - - def _CheckAttributes(self, context, allowed, attributes): - if not attributes: - return - for attribute in attributes: - if not attribute in allowed: - # Is there a close misspelling? - hint = self._Respell(allowed, attribute) - raise check.CheckException( - self.module, - f"attribute {attribute} not allowed on {context}{hint}") - - def _CheckEnumAttributes(self, enum): - if enum.attributes: - self._CheckAttributes("enum", _ENUM_ATTRIBUTES, enum.attributes) - if 'Stable' in enum.attributes and not 'Extensible' in enum.attributes: - full_name = f"{self.module.mojom_namespace}.{enum.mojom_name}" - if full_name not in _STABLE_ONLY_ALLOWLISTED_ENUMS: - raise check.CheckException( - self.module, - f"[Extensible] required on [Stable] enum {full_name}") - for enumval in enum.fields: - self._CheckAttributes("enum value", _ENUMVAL_ATTRIBUTES, - enumval.attributes) - - def _CheckInterfaceAttributes(self, interface): - self._CheckAttributes("interface", _INTERFACE_ATTRIBUTES, - interface.attributes) - for method in interface.methods: - self._CheckAttributes("method", _METHOD_ATTRIBUTES, method.attributes) - for param in method.parameters: - self._CheckAttributes("parameter", _PARAMETER_ATTRIBUTES, - param.attributes) - if method.response_parameters: - for param in method.response_parameters: - self._CheckAttributes("parameter", _PARAMETER_ATTRIBUTES, - param.attributes) - for enum in interface.enums: - self._CheckEnumAttributes(enum) - - def _CheckModuleAttributes(self): - self._CheckAttributes("module", _MODULE_ATTRIBUTES, self.module.attributes) - - def _CheckStructAttributes(self, struct): - self._CheckAttributes("struct", _STRUCT_ATTRIBUTES, struct.attributes) - for field in struct.fields: - self._CheckAttributes("struct field", _STRUCT_FIELD_ATTRIBUTES, - field.attributes) - for enum in struct.enums: - self._CheckEnumAttributes(enum) - - def _CheckUnionAttributes(self, union): - self._CheckAttributes("union", _UNION_ATTRIBUTES, union.attributes) - for field in union.fields: - self._CheckAttributes("union field", _UNION_FIELD_ATTRIBUTES, - field.attributes) - - def CheckModule(self): - """Note that duplicate attributes are forbidden at the parse phase. - We also do not need to look at the types of any parameters, as they will be - checked where they are defined. Consts do not have attributes so can be - skipped.""" - self._CheckModuleAttributes() - for interface in self.module.interfaces: - self._CheckInterfaceAttributes(interface) - for enum in self.module.enums: - self._CheckEnumAttributes(enum) - for struct in self.module.structs: - self._CheckStructAttributes(struct) - for union in self.module.unions: - self._CheckUnionAttributes(union) diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py deleted file mode 100644 index f1a50a4a..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -import mojom.generate.check as check -from mojom_bindings_generator import LoadChecks, _Generate -from mojom_parser_test_case import MojomParserTestCase - - -class FakeArgs: - """Fakes args to _Generate - intention is to do just enough to run checks""" - - def __init__(self, tester, files=None): - """ `tester` is MojomParserTestCase for paths. - `files` will have tester path added.""" - self.checks_string = 'attributes' - self.depth = tester.GetPath('') - self.filelist = None - self.filename = [tester.GetPath(x) for x in files] - self.gen_directories = tester.GetPath('gen') - self.generators_string = '' - self.import_directories = [] - self.output_dir = tester.GetPath('out') - self.scrambled_message_id_salt_paths = None - self.typemaps = [] - self.variant = 'none' - - -class MojoBindingsCheckTest(MojomParserTestCase): - def _ParseAndGenerate(self, mojoms): - self.ParseMojoms(mojoms) - args = FakeArgs(self, files=mojoms) - _Generate(args, {}) - - def _testValid(self, filename, content): - self.WriteFile(filename, content) - self._ParseAndGenerate([filename]) - - def _testThrows(self, filename, content, regexp): - mojoms = [] - self.WriteFile(filename, content) - mojoms.append(filename) - with self.assertRaisesRegexp(check.CheckException, regexp): - self._ParseAndGenerate(mojoms) - - def testLoads(self): - """Validate that the check is registered under the expected name.""" - check_modules = LoadChecks('attributes') - self.assertTrue(check_modules['attributes']) - - def testNoAnnotations(self): - # Undecorated mojom should be fine. - self._testValid( - "a.mojom", """ - module a; - struct Bar { int32 a; }; - enum Hello { kValue }; - union Thingy { Bar b; Hello hi; }; - interface Foo { - Foo(int32 a, Hello hi, Thingy t) => (Bar b); - }; - """) - - def testValidAnnotations(self): - # Obviously this is meaningless and won't generate, but it should pass - # the attribute check's validation. - self._testValid( - "a.mojom", """ - [JavaConstantsClassName="FakeClass",JavaPackage="org.chromium.Fake"] - module a; - [Stable, Extensible] - enum Hello { [Default] kValue, kValue2, [MinVersion=2] kValue3 }; - [Native] - enum NativeEnum {}; - [Stable,Extensible] - union Thingy { Bar b; [Default]int32 c; Hello hi; }; - - [Stable,RenamedFrom="module.other.Foo", - Uuid="4C178401-4B07-4C2E-9255-5401A943D0C7"] - struct Structure { Hello hi; }; - - [ServiceSandbox=Hello.kValue,RequireContext=Hello.kValue,Stable, - Uuid="2F17D7DD-865A-4B1C-9394-9C94E035E82F"] - interface Foo { - [AllowedContext=Hello.kValue] - Foo@0(int32 a) => (int32 b); - [MinVersion=2,Sync,UnlimitedSize,NoInterrupt] - Bar@1(int32 b, [MinVersion=2]Structure? s) => (bool c); - }; - - [RuntimeFeature=test.mojom.FeatureName] - interface FooFeatureControlled {}; - - interface FooMethodFeatureControlled { - [RuntimeFeature=test.mojom.FeatureName] - MethodWithFeature() => (bool c); - }; - """) - - def testWrongModuleStable(self): - contents = """ - // err: module cannot be Stable - [Stable] - module a; - enum Hello { kValue, kValue2, kValue3 }; - enum NativeEnum {}; - struct Structure { Hello hi; }; - - interface Foo { - Foo(int32 a) => (int32 b); - Bar(int32 b, Structure? s) => (bool c); - }; - """ - self._testThrows('b.mojom', contents, - 'attribute Stable not allowed on module') - - def testWrongEnumDefault(self): - contents = """ - module a; - // err: default should go on EnumValue not Enum. - [Default=kValue] - enum Hello { kValue, kValue2, kValue3 }; - enum NativeEnum {}; - struct Structure { Hello hi; }; - - interface Foo { - Foo(int32 a) => (int32 b); - Bar(int32 b, Structure? s) => (bool c); - }; - """ - self._testThrows('b.mojom', contents, - 'attribute Default not allowed on enum') - - def testWrongStructMinVersion(self): - contents = """ - module a; - enum Hello { kValue, kValue2, kValue3 }; - enum NativeEnum {}; - // err: struct cannot have MinVersion. - [MinVersion=2] - struct Structure { Hello hi; }; - - interface Foo { - Foo(int32 a) => (int32 b); - Bar(int32 b, Structure? s) => (bool c); - }; - """ - self._testThrows('b.mojom', contents, - 'attribute MinVersion not allowed on struct') - - def testWrongMethodRequireContext(self): - contents = """ - module a; - enum Hello { kValue, kValue2, kValue3 }; - enum NativeEnum {}; - struct Structure { Hello hi; }; - - interface Foo { - // err: RequireContext is for interfaces. - [RequireContext=Hello.kValue] - Foo(int32 a) => (int32 b); - Bar(int32 b, Structure? s) => (bool c); - }; - """ - self._testThrows('b.mojom', contents, - 'RequireContext not allowed on method') - - def testWrongMethodRequireContext(self): - # crbug.com/1230122 - contents = """ - module a; - interface Foo { - // err: sync not Sync. - [sync] - Foo(int32 a) => (int32 b); - }; - """ - self._testThrows('b.mojom', contents, - 'attribute sync not allowed.*Did you mean: Sync') - - def testStableExtensibleEnum(self): - # crbug.com/1193875 - contents = """ - module a; - [Stable] - enum Foo { - kDefaultVal, - kOtherVal = 2, - }; - """ - self._testThrows('a.mojom', contents, - 'Extensible.*?required.*?Stable.*?enum') diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_definitions_check.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_definitions_check.py deleted file mode 100644 index 702d41c3..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_definitions_check.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Ensure no duplicate type definitions before generation.""" - -import mojom.generate.check as check -import mojom.generate.module as module - - -class Check(check.Check): - def __init__(self, *args, **kwargs): - super(Check, self).__init__(*args, **kwargs) - - def CheckModule(self): - kinds = dict() - for module in self.module.imports: - for kind in module.enums + module.structs + module.unions: - kind_name = f'{kind.module.mojom_namespace}.{kind.mojom_name}' - if kind_name in kinds: - previous_module = kinds[kind_name] - if previous_module.path != module.path: - raise check.CheckException( - self.module, f"multiple-definition for type {kind_name}" + - f"(defined in both {previous_module} and {module})") - kinds[kind_name] = kind.module - - for kind in self.module.enums + self.module.structs + self.module.unions: - kind_name = f'{kind.module.mojom_namespace}.{kind.mojom_name}' - if kind_name in kinds: - previous_module = kinds[kind_name] - raise check.CheckException( - self.module, f"multiple-definition for type {kind_name}" + - f"(previous definition in {previous_module})") - return True diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check.py deleted file mode 100644 index 07f51a64..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Validate mojo runtime feature guarded interfaces are nullable.""" - -import mojom.generate.check as check -import mojom.generate.module as module - - -class Check(check.Check): - def __init__(self, *args, **kwargs): - super(Check, self).__init__(*args, **kwargs) - - # `param` is an Interface of some sort. - def _CheckNonNullableFeatureGuardedInterface(self, kind): - # Only need to validate interface if it has a RuntimeFeature - if not kind.kind.runtime_feature: - return - # Nullable (optional) is ok as the interface expects they might not be sent. - if kind.is_nullable: - return - interface = kind.kind.mojom_name - raise check.CheckException( - self.module, - f"interface {interface} has a RuntimeFeature but is not nullable") - - # `param` can be a lot of things so check if it is a remote/receiver. - # Array/Map must be recursed into. - def _CheckFieldOrParam(self, kind): - if module.IsAnyInterfaceKind(kind): - self._CheckNonNullableFeatureGuardedInterface(kind) - if module.IsArrayKind(kind): - self._CheckFieldOrParam(kind.kind) - if module.IsMapKind(kind): - self._CheckFieldOrParam(kind.key_kind) - self._CheckFieldOrParam(kind.value_kind) - - def _CheckInterfaceFeatures(self, interface): - for method in interface.methods: - for param in method.parameters: - self._CheckFieldOrParam(param.kind) - if method.response_parameters: - for param in method.response_parameters: - self._CheckFieldOrParam(param.kind) - - def _CheckStructFeatures(self, struct): - for field in struct.fields: - self._CheckFieldOrParam(field.kind) - - def _CheckUnionFeatures(self, union): - for field in union.fields: - self._CheckFieldOrParam(field.kind) - - def CheckModule(self): - """Validate that any runtime feature guarded interfaces that might be passed - over mojo are nullable.""" - for interface in self.module.interfaces: - self._CheckInterfaceFeatures(interface) - for struct in self.module.structs: - self._CheckStructFeatures(struct) - for union in self.module.unions: - self._CheckUnionFeatures(union) diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check_unittest.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check_unittest.py deleted file mode 100644 index e96152fd..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check_unittest.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -import mojom.generate.check as check -from mojom_bindings_generator import LoadChecks, _Generate -from mojom_parser_test_case import MojomParserTestCase - - -class FakeArgs: - """Fakes args to _Generate - intention is to do just enough to run checks""" - def __init__(self, tester, files=None): - """ `tester` is MojomParserTestCase for paths. - `files` will have tester path added.""" - self.checks_string = 'features' - self.depth = tester.GetPath('') - self.filelist = None - self.filename = [tester.GetPath(x) for x in files] - self.gen_directories = tester.GetPath('gen') - self.generators_string = '' - self.import_directories = [] - self.output_dir = tester.GetPath('out') - self.scrambled_message_id_salt_paths = None - self.typemaps = [] - self.variant = 'none' - - -class MojoBindingsCheckTest(MojomParserTestCase): - def _ParseAndGenerate(self, mojoms): - self.ParseMojoms(mojoms) - args = FakeArgs(self, files=mojoms) - _Generate(args, {}) - - def assertValid(self, filename, content): - self.WriteFile(filename, content) - self._ParseAndGenerate([filename]) - - def assertThrows(self, filename, content, regexp): - mojoms = [] - self.WriteFile(filename, content) - mojoms.append(filename) - with self.assertRaisesRegexp(check.CheckException, regexp): - self._ParseAndGenerate(mojoms) - - def testLoads(self): - """Validate that the check is registered under the expected name.""" - check_modules = LoadChecks('features') - self.assertTrue(check_modules['features']) - - def testNullableOk(self): - self.assertValid( - "a.mojom", """ - module a; - // Scaffolding. - feature kFeature { - const string name = "Hello"; - const bool enabled_state = false; - }; - [RuntimeFeature=kFeature] - interface Guarded { - }; - - // Unguarded interfaces should be ok everywhere. - interface NotGuarded { }; - - // Optional (nullable) interfaces should be ok everywhere: - struct Bar { - pending_remote<Guarded>? remote; - pending_receiver<Guarded>? receiver; - }; - union Thingy { - pending_remote<Guarded>? remote; - pending_receiver<Guarded>? receiver; - }; - interface Foo { - Foo( - pending_remote<Guarded>? remote, - pending_receiver<Guarded>? receiver, - pending_associated_remote<Guarded>? a_remote, - pending_associated_receiver<Guarded>? a_receiver, - // Unguarded interfaces do not have to be nullable. - pending_remote<NotGuarded> remote, - pending_receiver<NotGuarded> receiver, - pending_associated_remote<NotGuarded> a_remote, - pending_associated_receiver<NotGuarded> a_receiver - ) => ( - pending_remote<Guarded>? remote, - pending_receiver<Guarded>? receiver - ); - Bar(array<pending_remote<Guarded>?> remote) - => (map<string, pending_receiver<Guarded>?> a); - }; - """) - - def testMethodParamsMustBeNullable(self): - prelude = """ - module a; - // Scaffolding. - feature kFeature { - const string name = "Hello"; - const bool enabled_state = false; - }; - [RuntimeFeature=kFeature] - interface Guarded { }; - """ - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(pending_remote<Guarded> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(bool foo) => (pending_receiver<Guarded> a); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(pending_receiver<Guarded> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(pending_associated_remote<Guarded> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(pending_associated_receiver<Guarded> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(array<pending_associated_receiver<Guarded>> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - interface Trial { - Method(map<string, pending_associated_receiver<Guarded>> a) => (); - }; - """, 'interface Guarded has a RuntimeFeature') - - def testStructUnionMembersMustBeNullable(self): - prelude = """ - module a; - // Scaffolding. - feature kFeature { - const string name = "Hello"; - const bool enabled_state = false; - }; - [RuntimeFeature=kFeature] - interface Guarded { }; - """ - self.assertThrows( - 'a.mojom', prelude + """ - struct Trial { - pending_remote<Guarded> a; - }; - """, 'interface Guarded has a RuntimeFeature') - self.assertThrows( - 'a.mojom', prelude + """ - union Trial { - pending_remote<Guarded> a; - }; - """, 'interface Guarded has a RuntimeFeature') diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_check.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_check.py deleted file mode 100644 index d570e26c..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_check.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Validate RequireContext and AllowedContext annotations before generation.""" - -import mojom.generate.check as check -import mojom.generate.module as module - - -class Check(check.Check): - def __init__(self, *args, **kwargs): - self.kind_to_interfaces = dict() - super(Check, self).__init__(*args, **kwargs) - - def _IsPassedInterface(self, candidate): - if isinstance( - candidate.kind, - (module.PendingReceiver, module.PendingRemote, - module.PendingAssociatedReceiver, module.PendingAssociatedRemote)): - return True - return False - - def _CheckInterface(self, method, param): - # |param| is a pending_x<Interface> so need .kind.kind to get Interface. - interface = param.kind.kind - if interface.require_context: - if method.allowed_context is None: - raise check.CheckException( - self.module, "method `{}` has parameter `{}` which passes interface" - " `{}` that requires an AllowedContext annotation but none exists.". - format( - method.mojom_name, - param.mojom_name, - interface.mojom_name, - )) - # If a string was provided, or if an enum was not imported, this will - # be a string and we cannot validate that it is in range. - if not isinstance(method.allowed_context, module.EnumValue): - raise check.CheckException( - self.module, - "method `{}` has AllowedContext={} which is not a valid enum value." - .format(method.mojom_name, method.allowed_context)) - # EnumValue must be from the same enum to be compared. - if interface.require_context.enum != method.allowed_context.enum: - raise check.CheckException( - self.module, "method `{}` has parameter `{}` which passes interface" - " `{}` that requires AllowedContext={} but one of kind `{}` was " - "provided.".format( - method.mojom_name, - param.mojom_name, - interface.mojom_name, - interface.require_context.enum, - method.allowed_context.enum, - )) - # RestrictContext enums have most privileged field first (lowest value). - interface_value = interface.require_context.field.numeric_value - method_value = method.allowed_context.field.numeric_value - if interface_value < method_value: - raise check.CheckException( - self.module, "RequireContext={} > AllowedContext={} for method " - "`{}` which passes interface `{}`.".format( - interface.require_context.GetSpec(), - method.allowed_context.GetSpec(), method.mojom_name, - interface.mojom_name)) - return True - - def _GatherReferencedInterfaces(self, field): - key = field.kind.spec - # structs/unions can nest themselves so we need to bookkeep. - if not key in self.kind_to_interfaces: - # Might reference ourselves so have to create the list first. - self.kind_to_interfaces[key] = set() - for param in field.kind.fields: - if self._IsPassedInterface(param): - self.kind_to_interfaces[key].add(param) - elif isinstance(param.kind, (module.Struct, module.Union)): - for iface in self._GatherReferencedInterfaces(param): - self.kind_to_interfaces[key].add(iface) - return self.kind_to_interfaces[key] - - def _CheckParams(self, method, params): - # Note: we have to repeat _CheckParams for each method as each might have - # different AllowedContext= attributes. We cannot memoize this function, - # but can do so for gathering referenced interfaces as their RequireContext - # attributes do not change. - for param in params: - if self._IsPassedInterface(param): - self._CheckInterface(method, param) - elif isinstance(param.kind, (module.Struct, module.Union)): - for interface in self._GatherReferencedInterfaces(param): - self._CheckInterface(method, interface) - - def _CheckMethod(self, method): - if method.parameters: - self._CheckParams(method, method.parameters) - if method.response_parameters: - self._CheckParams(method, method.response_parameters) - - def CheckModule(self): - for interface in self.module.interfaces: - for method in interface.methods: - self._CheckMethod(method) diff --git a/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_checks_unittest.py b/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_checks_unittest.py deleted file mode 100644 index a6cd71e2..00000000 --- a/utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_checks_unittest.py +++ /dev/null @@ -1,254 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -import mojom.generate.check as check -from mojom_bindings_generator import LoadChecks, _Generate -from mojom_parser_test_case import MojomParserTestCase - -# Mojoms that we will use in multiple tests. -basic_mojoms = { - 'level.mojom': - """ - module level; - enum Level { - kHighest, - kMiddle, - kLowest, - }; - """, - 'interfaces.mojom': - """ - module interfaces; - import "level.mojom"; - struct Foo {int32 bar;}; - [RequireContext=level.Level.kHighest] - interface High { - DoFoo(Foo foo); - }; - [RequireContext=level.Level.kMiddle] - interface Mid { - DoFoo(Foo foo); - }; - [RequireContext=level.Level.kLowest] - interface Low { - DoFoo(Foo foo); - }; - """ -} - - -class FakeArgs: - """Fakes args to _Generate - intention is to do just enough to run checks""" - - def __init__(self, tester, files=None): - """ `tester` is MojomParserTestCase for paths. - `files` will have tester path added.""" - self.checks_string = 'restrictions' - self.depth = tester.GetPath('') - self.filelist = None - self.filename = [tester.GetPath(x) for x in files] - self.gen_directories = tester.GetPath('gen') - self.generators_string = '' - self.import_directories = [] - self.output_dir = tester.GetPath('out') - self.scrambled_message_id_salt_paths = None - self.typemaps = [] - self.variant = 'none' - - -class MojoBindingsCheckTest(MojomParserTestCase): - def _WriteBasicMojoms(self): - for filename, contents in basic_mojoms.items(): - self.WriteFile(filename, contents) - return list(basic_mojoms.keys()) - - def _ParseAndGenerate(self, mojoms): - self.ParseMojoms(mojoms) - args = FakeArgs(self, files=mojoms) - _Generate(args, {}) - - def testLoads(self): - """Validate that the check is registered under the expected name.""" - check_modules = LoadChecks('restrictions') - self.assertTrue(check_modules['restrictions']) - - def testValidAnnotations(self): - mojoms = self._WriteBasicMojoms() - - a = 'a.mojom' - self.WriteFile( - a, """ - module a; - import "level.mojom"; - import "interfaces.mojom"; - - interface PassesHigh { - [AllowedContext=level.Level.kHighest] - DoHigh(pending_receiver<interfaces.High> hi); - }; - interface PassesMedium { - [AllowedContext=level.Level.kMiddle] - DoMedium(pending_receiver<interfaces.Mid> hi); - [AllowedContext=level.Level.kMiddle] - DoMediumRem(pending_remote<interfaces.Mid> hi); - [AllowedContext=level.Level.kMiddle] - DoMediumAssoc(pending_associated_receiver<interfaces.Mid> hi); - [AllowedContext=level.Level.kMiddle] - DoMediumAssocRem(pending_associated_remote<interfaces.Mid> hi); - }; - interface PassesLow { - [AllowedContext=level.Level.kLowest] - DoLow(pending_receiver<interfaces.Low> hi); - }; - - struct One { pending_receiver<interfaces.High> hi; }; - struct Two { One one; }; - interface PassesNestedHigh { - [AllowedContext=level.Level.kHighest] - DoNestedHigh(Two two); - }; - - // Allowed as PassesHigh is not itself restricted. - interface PassesPassesHigh { - DoPass(pending_receiver<PassesHigh> hiho); - }; - """) - mojoms.append(a) - self._ParseAndGenerate(mojoms) - - def _testThrows(self, filename, content, regexp): - mojoms = self._WriteBasicMojoms() - self.WriteFile(filename, content) - mojoms.append(filename) - with self.assertRaisesRegexp(check.CheckException, regexp): - self._ParseAndGenerate(mojoms) - - def testMissingAnnotation(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - - interface PassesHigh { - // err: missing annotation. - DoHigh(pending_receiver<interfaces.High> hi); - }; - """ - self._testThrows('b.mojom', contents, 'require.*?AllowedContext') - - def testAllowTooLow(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - - interface PassesHigh { - // err: level is worse than required. - [AllowedContext=level.Level.kMiddle] - DoHigh(pending_receiver<interfaces.High> hi); - }; - """ - self._testThrows('b.mojom', contents, - 'RequireContext=.*?kHighest > AllowedContext=.*?kMiddle') - - def testWrongEnumInAllow(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - enum Blah { - kZero, - }; - interface PassesHigh { - // err: different enums. - [AllowedContext=Blah.kZero] - DoHigh(pending_receiver<interfaces.High> hi); - }; - """ - self._testThrows('b.mojom', contents, 'but one of kind') - - def testNotAnEnumInAllow(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - interface PassesHigh { - // err: not an enum. - [AllowedContext=doopdedoo.mojom.kWhatever] - DoHigh(pending_receiver<interfaces.High> hi); - }; - """ - self._testThrows('b.mojom', contents, 'not a valid enum value') - - def testMissingAllowedForNestedStructs(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - struct One { pending_receiver<interfaces.High> hi; }; - struct Two { One one; }; - interface PassesNestedHigh { - // err: missing annotation. - DoNestedHigh(Two two); - }; - """ - self._testThrows('b.mojom', contents, 'require.*?AllowedContext') - - def testMissingAllowedForNestedUnions(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - struct One { pending_receiver<interfaces.High> hi; }; - struct Two { One one; }; - union Three {One one; Two two; }; - interface PassesNestedHigh { - // err: missing annotation. - DoNestedHigh(Three three); - }; - """ - self._testThrows('b.mojom', contents, 'require.*?AllowedContext') - - def testMultipleInterfacesThrows(self): - contents = """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - struct One { pending_receiver<interfaces.High> hi; }; - interface PassesMultipleInterfaces { - [AllowedContext=level.Level.kMiddle] - DoMultiple( - pending_remote<interfaces.Mid> mid, - pending_receiver<interfaces.High> hi, - One one - ); - }; - """ - self._testThrows('b.mojom', contents, - 'RequireContext=.*?kHighest > AllowedContext=.*?kMiddle') - - def testMultipleInterfacesAllowed(self): - """Multiple interfaces can be passed, all satisfy the level.""" - mojoms = self._WriteBasicMojoms() - - b = "b.mojom" - self.WriteFile( - b, """ - module b; - import "level.mojom"; - import "interfaces.mojom"; - struct One { pending_receiver<interfaces.High> hi; }; - interface PassesMultipleInterfaces { - [AllowedContext=level.Level.kHighest] - DoMultiple( - pending_receiver<interfaces.High> hi, - pending_remote<interfaces.Mid> mid, - One one - ); - }; - """) - mojoms.append(b) - self._ParseAndGenerate(mojoms) diff --git a/utils/ipc/mojo/public/tools/bindings/concatenate-files.py b/utils/ipc/mojo/public/tools/bindings/concatenate-files.py deleted file mode 100755 index 4dd26d4a..00000000 --- a/utils/ipc/mojo/public/tools/bindings/concatenate-files.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# Copyright 2019 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# This utility concatenates several files into one. On Unix-like systems -# it is equivalent to: -# cat file1 file2 file3 ...files... > target -# -# The reason for writing a separate utility is that 'cat' is not available -# on all supported build platforms, but Python is, and hence this provides -# us with an easy and uniform way of doing this on all platforms. - -# for py2/py3 compatibility -from __future__ import print_function - -import optparse -import sys - - -def Concatenate(filenames): - """Concatenate files. - - Args: - files: Array of file names. - The last name is the target; all earlier ones are sources. - - Returns: - True, if the operation was successful. - """ - if len(filenames) < 2: - print("An error occurred generating %s:\nNothing to do." % filenames[-1]) - return False - - try: - with open(filenames[-1], "wb") as target: - for filename in filenames[:-1]: - with open(filename, "rb") as current: - target.write(current.read()) - return True - except IOError as e: - print("An error occurred when writing %s:\n%s" % (filenames[-1], e)) - return False - - -def main(): - parser = optparse.OptionParser() - parser.set_usage("""Concatenate several files into one. - Equivalent to: cat file1 ... > target.""") - (_options, args) = parser.parse_args() - sys.exit(0 if Concatenate(args) else 1) - - -if __name__ == "__main__": - main() diff --git a/utils/ipc/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py b/utils/ipc/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py deleted file mode 100755 index 7d56c9f9..00000000 --- a/utils/ipc/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Simple utility which concatenates a set of files into a single output file -while also stripping any goog.provide or goog.require lines. This allows us to -provide a very primitive sort of "compilation" without any extra toolchain -support and without having to modify otherwise compilable sources in the tree -which use these directives. - -goog.provide lines are replaced with an equivalent invocation of -mojo.internal.exportModule, which accomplishes essentially the same thing in an -uncompiled context. A singular exception is made for the 'mojo.internal' export, -which is instead replaced with an inlined assignment to initialize the -namespace. -""" - -from __future__ import print_function - -import optparse -import re -import sys - - -_MOJO_INTERNAL_MODULE_NAME = "mojo.internal" -_MOJO_EXPORT_MODULE_SYMBOL = "mojo.internal.exportModule" - - -def FilterLine(filename, line, output): - if line.startswith("goog.require"): - return - - if line.startswith("goog.provide"): - match = re.match(r"goog.provide\('([^']+)'\);", line) - if not match: - print("Invalid goog.provide line in %s:\n%s" % (filename, line)) - sys.exit(1) - - module_name = match.group(1) - if module_name == _MOJO_INTERNAL_MODULE_NAME: - output.write("self.mojo = { internal: {} };") - else: - output.write("%s('%s');\n" % (_MOJO_EXPORT_MODULE_SYMBOL, module_name)) - return - - output.write(line) - -def ConcatenateAndReplaceExports(filenames): - if (len(filenames) < 2): - print("At least two filenames (one input and the output) are required.") - return False - - try: - with open(filenames[-1], "w") as target: - for filename in filenames[:-1]: - with open(filename, "r") as current: - for line in current.readlines(): - FilterLine(filename, line, target) - return True - except IOError as e: - print("Error generating %s\n: %s" % (filenames[-1], e)) - return False - -def main(): - parser = optparse.OptionParser() - parser.set_usage("""file1 [file2...] outfile - Concatenate several files into one, stripping Closure provide and - require directives along the way.""") - (_, args) = parser.parse_args() - sys.exit(0 if ConcatenateAndReplaceExports(args) else 1) - - -if __name__ == "__main__": - main() diff --git a/utils/ipc/mojo/public/tools/bindings/gen_data_files_list.py b/utils/ipc/mojo/public/tools/bindings/gen_data_files_list.py deleted file mode 100644 index c6daff03..00000000 --- a/utils/ipc/mojo/public/tools/bindings/gen_data_files_list.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2017 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Generates a list of all files in a directory. - -This script takes in a directory and an output file name as input. -It then reads the directory and creates a list of all file names -in that directory. The list is written to the output file. -There is also an option to pass in '-p' or '--pattern' -which will check each file name against a regular expression -pattern that is passed in. Only files which match the regex -will be written to the list. -""" - -from __future__ import print_function - -import os -import re -import sys - -from optparse import OptionParser - -sys.path.insert( - 0, - os.path.join( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "mojom")) - -from mojom.generate.generator import WriteFile - - -def main(): - parser = OptionParser() - parser.add_option('-d', '--directory', help='Read files from DIRECTORY') - parser.add_option('-o', '--output', help='Write list to FILE') - parser.add_option('-p', - '--pattern', - help='Only reads files that name matches PATTERN', - default=".") - (options, _) = parser.parse_args() - pattern = re.compile(options.pattern) - files = [f for f in os.listdir(options.directory) if pattern.match(f)] - - contents = '\n'.join(f for f in files) + '\n' - WriteFile(contents, options.output) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/utils/ipc/mojo/public/tools/bindings/generate_type_mappings.py b/utils/ipc/mojo/public/tools/bindings/generate_type_mappings.py deleted file mode 100755 index 4a53e2bf..00000000 --- a/utils/ipc/mojo/public/tools/bindings/generate_type_mappings.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Generates a JSON typemap from its command-line arguments and dependencies. - -Each typemap should be specified in an command-line argument of the form -key=value, with an argument of "--start-typemap" preceding each typemap. - -For example, -generate_type_mappings.py --output=foo.typemap --start-typemap \\ - public_headers=foo.h traits_headers=foo_traits.h \\ - type_mappings=mojom.Foo=FooImpl - -generates a foo.typemap containing -{ - "c++": { - "mojom.Foo": { - "typename": "FooImpl", - "traits_headers": [ - "foo_traits.h" - ], - "public_headers": [ - "foo.h" - ] - } - } -} - -Then, -generate_type_mappings.py --dependency foo.typemap --output=bar.typemap \\ - --start-typemap public_headers=bar.h traits_headers=bar_traits.h \\ - type_mappings=mojom.Bar=BarImpl - -generates a bar.typemap containing -{ - "c++": { - "mojom.Bar": { - "typename": "BarImpl", - "traits_headers": [ - "bar_traits.h" - ], - "public_headers": [ - "bar.h" - ] - }, - "mojom.Foo": { - "typename": "FooImpl", - "traits_headers": [ - "foo_traits.h" - ], - "public_headers": [ - "foo.h" - ] - } - } -} -""" - -import argparse -import json -import os -import re -import sys - -sys.path.insert( - 0, - os.path.join( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "mojom")) - -from mojom.generate.generator import WriteFile - -def ReadTypemap(path): - with open(path) as f: - return json.load(f)['c++'] - - -def LoadCppTypemapConfig(path): - configs = {} - with open(path) as f: - for config in json.load(f): - for entry in config['types']: - configs[entry['mojom']] = { - 'typename': entry['cpp'], - 'forward_declaration': entry.get('forward_declaration', None), - 'public_headers': config.get('traits_headers', []), - 'traits_headers': config.get('traits_private_headers', []), - 'copyable_pass_by_value': entry.get('copyable_pass_by_value', - False), - 'default_constructible': entry.get('default_constructible', True), - 'force_serialize': entry.get('force_serialize', False), - 'hashable': entry.get('hashable', False), - 'move_only': entry.get('move_only', False), - 'nullable_is_same_type': entry.get('nullable_is_same_type', False), - 'non_copyable_non_movable': False, - } - return configs - -def main(): - parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument( - '--dependency', - type=str, - action='append', - default=[], - help=('A path to another JSON typemap to merge into the output. ' - 'This may be repeated to merge multiple typemaps.')) - parser.add_argument( - '--cpp-typemap-config', - type=str, - action='store', - dest='cpp_config_path', - help=('A path to a single JSON-formatted typemap config as emitted by' - 'GN when processing a mojom_cpp_typemap build rule.')) - parser.add_argument('--output', - type=str, - required=True, - help='The path to which to write the generated JSON.') - params, _ = parser.parse_known_args() - typemaps = {} - if params.cpp_config_path: - typemaps = LoadCppTypemapConfig(params.cpp_config_path) - missing = [path for path in params.dependency if not os.path.exists(path)] - if missing: - raise IOError('Missing dependencies: %s' % ', '.join(missing)) - for path in params.dependency: - typemaps.update(ReadTypemap(path)) - - WriteFile(json.dumps({'c++': typemaps}, indent=2), params.output) - - -if __name__ == '__main__': - main() diff --git a/utils/ipc/mojo/public/tools/bindings/minify_with_terser.py b/utils/ipc/mojo/public/tools/bindings/minify_with_terser.py deleted file mode 100755 index cefee7a4..00000000 --- a/utils/ipc/mojo/public/tools/bindings/minify_with_terser.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# This utility minifies JS files with terser. -# -# Instance of 'node' has no 'RunNode' member (no-member) -# pylint: disable=no-member - -import argparse -import os -import sys - -_HERE_PATH = os.path.dirname(__file__) -_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..', '..')) -_CWD = os.getcwd() -sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node')) -import node -import node_modules - - -def MinifyFile(input_file, output_file): - node.RunNode([ - node_modules.PathToTerser(), input_file, '--mangle', '--compress', - '--comments', 'false', '--output', output_file - ]) - - -def main(argv): - parser = argparse.ArgumentParser() - parser.add_argument('--input', required=True) - parser.add_argument('--output', required=True) - args = parser.parse_args(argv) - - # Delete the output file if it already exists. It may be a sym link to the - # input, because in non-optimized/pre-Terser builds the input file is copied - # to the output location with gn copy(). - out_path = os.path.join(_CWD, args.output) - if (os.path.exists(out_path)): - os.remove(out_path) - - MinifyFile(os.path.join(_CWD, args.input), out_path) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/utils/ipc/mojo/public/tools/bindings/mojom.gni b/utils/ipc/mojo/public/tools/bindings/mojom.gni deleted file mode 100644 index 3f6e54e0..00000000 --- a/utils/ipc/mojo/public/tools/bindings/mojom.gni +++ /dev/null @@ -1,2118 +0,0 @@ -# Copyright 2014 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/closure_args.gni") -import("//third_party/closure_compiler/compile_js.gni") -import("//third_party/protobuf/proto_library.gni") -import("//ui/webui/resources/tools/generate_grd.gni") -import("//ui/webui/webui_features.gni") - -import("//build/config/cast.gni") - -# TODO(rockot): Maybe we can factor these dependencies out of //mojo. They're -# used to conditionally enable message ID scrambling in a way which is -# consistent across toolchains and which is affected by branded vs non-branded -# Chrome builds. Ideally we could create some generic knobs here that could be -# flipped elsewhere though. -import("//build/config/chrome_build.gni") -import("//build/config/chromeos/ui_mode.gni") -import("//build/config/features.gni") -import("//build/config/nacl/config.gni") -import("//build/toolchain/kythe.gni") -import("//components/nacl/features.gni") -import("//third_party/jinja2/jinja2.gni") -import("//third_party/ply/ply.gni") -import("//tools/ipc_fuzzer/ipc_fuzzer.gni") -declare_args() { - # Indicates whether typemapping should be supported in this build - # configuration. This may be disabled when building external projects which - # depend on //mojo but which do not need/want all of the Chromium tree - # dependencies that come with typemapping. - # - # Note that (perhaps obviously) a huge amount of Chromium code will not build - # with typemapping disabled, so it is never valid to set this to |false| in - # any Chromium build configuration. - enable_mojom_typemapping = true - - # Controls message ID scrambling behavior. If |true|, message IDs are - # scrambled (i.e. randomized based on the contents of //chrome/VERSION) on - # non-Chrome OS desktop platforms. Enabled on official builds by default. - # Set to |true| to enable message ID scrambling on a specific build. - # See also `enable_scrambled_message_ids` below for more details. - enable_mojom_message_id_scrambling = is_official_build - - # Enables generating javascript fuzzing-related code and the bindings for the - # MojoLPM fuzzer targets. Off by default. - enable_mojom_fuzzer = false - - # Enables Closure compilation of generated JS lite bindings. In environments - # where compilation is supported, any mojom target "foo" will also have a - # corresponding "foo_js_library_for_compile" target generated. - if (is_chromeos_ash) { - enable_mojom_closure_compile = enable_js_type_check && optimize_webui - } -} - -# Closure libraries are needed for mojom_closure_compile, and when -# js_type_check is enabled on Ash. -if (is_chromeos_ash) { - generate_mojom_closure_libraries = - enable_mojom_closure_compile || enable_js_type_check -} else { - generate_mojom_closure_libraries = false -} - -# NOTE: We would like to avoid scrambling message IDs where it doesn't add -# value, so we limit the behavior to desktop builds for now. There is some -# redundancy in the conditions here, but it is tolerated for clarity: -# We're explicit about Mac, Windows, and Linux desktop support, but it's -# also necessary to ensure that bindings in alternate toolchains (e.g. -# NaCl IRT) are always consistent with the default toolchain; for that -# reason we always enable scrambling within NaCl toolchains when possible, -# as well as within the default toolchain when NaCl is enabled. -# -# Finally, because we *cannot* enable scrambling on Chrome OS (it would break -# ARC) we have to explicitly opt out there even when NaCl is enabled (and -# consequently also when building for NaCl toolchains.) For this reason we -# check |target_os| explicitly, as it's consistent across all toolchains. -# -# TODO(crbug.com/1052397): Remove !chromeos_is_browser_only once -# lacros-chrome switches to target_os="chromeos" -enable_scrambled_message_ids = - enable_mojom_message_id_scrambling && - (is_mac || is_win || (is_linux && !is_castos) || - ((enable_nacl || is_nacl) && - (target_os != "chromeos" && !chromeos_is_browser_only))) - -_mojom_tools_root = "//mojo/public/tools" -_mojom_library_root = "$_mojom_tools_root/mojom/mojom" -mojom_parser_script = "$_mojom_tools_root/mojom/mojom_parser.py" -mojom_parser_sources = [ - "$_mojom_library_root/__init__.py", - "$_mojom_library_root/error.py", - "$_mojom_library_root/fileutil.py", - "$_mojom_library_root/generate/__init__.py", - "$_mojom_library_root/generate/check.py", - "$_mojom_library_root/generate/generator.py", - "$_mojom_library_root/generate/module.py", - "$_mojom_library_root/generate/pack.py", - "$_mojom_library_root/generate/template_expander.py", - "$_mojom_library_root/generate/translate.py", - "$_mojom_library_root/parse/__init__.py", - "$_mojom_library_root/parse/ast.py", - "$_mojom_library_root/parse/conditional_features.py", - "$_mojom_library_root/parse/lexer.py", - "$_mojom_library_root/parse/parser.py", - "//tools/diagnosis/crbug_1001171.py", -] - -mojom_generator_root = "$_mojom_tools_root/bindings" -mojom_generator_script = "$mojom_generator_root/mojom_bindings_generator.py" -mojom_generator_sources = - mojom_parser_sources + [ - "$mojom_generator_root/checks/__init__.py", - "$mojom_generator_root/checks/mojom_attributes_check.py", - "$mojom_generator_root/checks/mojom_definitions_check.py", - "$mojom_generator_root/checks/mojom_interface_feature_check.py", - "$mojom_generator_root/checks/mojom_restrictions_check.py", - "$mojom_generator_root/generators/__init__.py", - "$mojom_generator_root/generators/cpp_util.py", - "$mojom_generator_root/generators/mojom_cpp_generator.py", - "$mojom_generator_root/generators/mojom_java_generator.py", - "$mojom_generator_root/generators/mojom_js_generator.py", - "$mojom_generator_root/generators/mojom_mojolpm_generator.py", - "$mojom_generator_root/generators/mojom_ts_generator.py", - "$mojom_generator_script", - "//build/action_helpers.py", - "//build/gn_helpers.py", - "//build/zip_helpers.py", - ] - -if (enable_scrambled_message_ids) { - declare_args() { - # The path to a file whose contents can be used as the basis for a message - # ID scrambling salt. - mojom_message_id_salt_path = "//chrome/VERSION" - } - - assert(mojom_message_id_salt_path != "") - message_scrambling_args = [ - "--scrambled_message_id_salt_path", - rebase_path(mojom_message_id_salt_path, root_build_dir), - ] - message_scrambling_inputs = [ mojom_message_id_salt_path ] -} else { - message_scrambling_args = [] - message_scrambling_inputs = [] -} - -# Generates targets for building C++, JavaScript and Java bindings from mojom -# files. The output files will go under the generated file directory tree with -# the same path as each input file. -# -# Other targets should depend on one of these generated targets (where "foo" -# is the target name): -# -# foo -# C++ bindings. -# -# foo_blink -# C++ bindings using Blink standard types. -# -# foo_java -# Java bindings. -# -# foo_js -# JavaScript bindings; used as compile-time dependency. -# -# foo_js_data_deps -# JavaScript bindings; used as run-time dependency. -# -# Parameters: -# -# sources (optional if one of the deps sets listed below is present) -# List of source .mojom files to compile. -# -# deps (optional) -# Note: this can contain only other mojom targets. -# -# DEPRECATED: This is synonymous with public_deps because all mojom -# dependencies must be public by design. Please use public_deps. -# -# public_deps (optional) -# Note: this can contain only other mojom targets. -# -# parser_deps (optional) -# List of non-mojom targets required for the mojom sources to be parsed. -# -# import_dirs (optional) -# List of import directories that will get added when processing sources. -# -# input_root_override (optional) -# Root path for the .mojom files used to generate the namespaces for -# interfaces. Useful with targets outside //, e.g. in parent directories -# above "//". The default input root is // -# Example: Vivaldi's source root is "//vivaldi/", -# and "//vivaldi/chromium/" is "//" -# In such cases, not using this argument lead to the output files being -# located in different directories than expected. -# -# testonly (optional) -# -# visibility (optional) -# -# visibility_blink (optional) -# The value to use for visibility for the blink variant. If unset, -# |visibility| is used. -# -# cpp_only (optional) -# If set to true, only the C++ bindings targets will be generated. -# -# NOTE: If the global |enable_mojom_fuzzer| build arg is true, JS bindings -# will still be generated even when |cpp_only| is set to |true|, unless -# you also set |enable_fuzzing| to |false| in your mojom target. -# -# cpp_typemaps (optional) -# A list of typemaps to be applied to the generated C++ bindings for this -# mojom target. Note that this only applies to the non-Blink variant of -# generated C++ bindings. -# -# Every typemap is a GN scope describing how one or more mojom types maps -# to a non-mojom C++ type, including necessary deps and headers required -# for the mapping to work. See the Typemaps section below. -# -# blink_cpp_typemaps (optional) -# Same as above, but for the Blink variant of generated C++ bindings. -# -# cpp_proxy_target (optional) -# The name of a target which all C++ dependencies will link against -# instead of linking directly against this mojom target's generated C++ -# sources. Normally when declaring invoking the mojom("foo") target, GN -# emits a source_set or component target named "foo" which encompasses the -# default variant of generated C++ bindings. This changes that to instead -# emit a group("foo") which merely forwards public_deps to the named -# `cpp_proxy_target`. That target must in turn depend on -# "foo_cpp_sources". -# -# This is useful primarily in conjunction with export_define et al to -# embed generated C++ bindings within an existing component target. -# -# blink_cpp_proxy_target (optional) -# Same concept as `cpp_proxy_target` above, but affects the generated -# "foo_blink" Blink-variant C++ bindings. -# -# cpp_configs (optional) -# A list of extra configs to apply to the default variant of generated C++ -# bindings. -# -# blink_cpp_configs (optional) -# A list of extra configs to apply to the Blink variant of generated C++ -# bindings. -# -# mojom_source_deps (optional) -# A list of mojoms this target depends upon. This is equivalent to -# public_deps except that the C++ bindings depend on each of the named -# "foo" targets' "foo_cpp_sources" rather than on foo's -# `cpp_proxy_target`. It only makes sense to use this for dependencies -# that set `cpp_proxy_target`, and only when the dependent mojom() would -# otherwise have circular dependencies with that proxy target. -# -# mojom_blink_source_deps (optional) -# Same as above but depends on "foo_blink_cpp_sources" and is used for -# dependencies that specify a `blink_cpp_proxy_target`. -# -# generate_java (optional) -# If set to true, Java bindings are generated for Android builds. If -# |cpp_only| is set to true, it overrides this to prevent generation of -# Java bindings. -# -# enable_js_fuzzing (optional) -# Enables generation of javascript fuzzing sources for the target if the -# global build arg |enable_mojom_fuzzer| is also set to |true|. -# Defaults to |true|. If JS fuzzing generation is enabled for a target, -# the target will always generate JS bindings even if |cpp_only| is set to -# |true|. See note above. -# -# enable_mojolpm_fuzzing (optional) -# Enables generation of fuzzing sources for the target if the global build -# arg |enable_mojom_fuzzer| is also set to |true|. Defaults to |true|. -# -# support_lazy_serialization (optional) -# If set to |true|, generated C++ bindings will effectively prefer to -# transmit messages in an unserialized form when going between endpoints -# in the same process. This avoids the runtime cost of serialization, -# deserialization, and validation logic at the expensive of increased -# code size. Defaults to |false|. -# -# disable_variants (optional) -# If |true|, no variant sources will be generated for the target. Defaults -# to |false|. -# -# disallow_native_types (optional) -# If set to |true|, mojoms in this target may not apply the [Native] -# attribute to struct or enum declarations. This avoids emitting code -# which depends on legacy IPC serialization. Default is |false|, meaning -# [Native] types are allowed. -# -# disallow_interfaces (optional) -# If set to |true|, mojoms in this target may not define interfaces. -# Generates bindings with a smaller set of dependencies. Defaults to -# |false|. -# -# scramble_message_ids (optional) -# If set to |true| (the default), generated mojom interfaces will use -# scrambled ordinal identifiers in encoded messages. -# -# component_output_prefix (optional) -# The prefix to use for the output_name of any component library emitted -# for generated C++ bindings. If this is omitted, C++ bindings targets are -# emitted as source_sets instead. Because this controls the name of the -# output shared library binary in the root output directory, it must be -# unique across the entire build configuration. -# -# This is required if |component_macro_prefix| is specified. -# -# component_macro_prefix (optional) -# This specifies a macro prefix to use for component export macros and -# should therefore be globally unique in the project. For example if this -# is "FOO_BAR", then the generated C++ sources will be built with -# IS_FOO_BAR_{suffix}_IMPL defined, and the generated public headers will -# annotate public symbol definitions with -# COMPONENT_EXPORT(FOO_BAR_{suffix}). "suffix" in this case depends on -# which internal subtarget is generating the code (e.g. "SHARED", or a -# variant name like "BLINK"). -# -# enabled_features (optional) -# Definitions in a mojom file can be guarded by an EnableIf attribute. If -# the value specified by the attribute does not match any items in the -# list of enabled_features, the definition will be disabled, with no code -# emitted for it. -# -# generate_closure_exports (optional) -# Generates JS lite bindings will use goog.provide and goog.require -# annotations to export its symbols and import core Mojo bindings support -# and other mojom dependency modules. Use this if you plan to compile your -# bindings into a larger JS binary. Defaults to |false|, instead -# generating JS lite bindings which assume they will be manually loaded in -# correct dependency order. Note that this only has an effect if -# the |enable_mojom_closure_compile| global arg is set to |true| as well. -# -# generate_webui_js_bindings (optional) -# Generate WebUI bindings in JavaScript rather than TypeScript. Defaults -# to false. ChromeOS only parameter. -# -# generate_legacy_js_bindings (optional) -# Generate js_data_deps target containing legacy JavaScript bindings files -# for Blink tests and other non-WebUI users when generating TypeScript -# bindings for WebUI. Ignored if generate_webui_js_bindings is set to -# true. -# -# js_generate_struct_deserializers (optional) -# Generates JS deerialize methods for structs. -# -# extra_cpp_template_paths (optional) -# List of extra C++ templates that are used to generate additional source -# and/or header files. The templates should end with extension ".tmpl". -# -# webui_module_path (optional) -# The path or URL at which modules generated by this target will be -# accessible to WebUI pages. This may either be an absolute path or -# a full URL path starting with "chrome://resources/mojo". If this path -# is not specified, WebUI bindings will not be generated. -# -# If an absolute path, a WebUI page may only import these modules if -# they are added to that page's data source (usually by adding the -# modules to the mojo_files list for build_webui(), or by listing the -# files as inputs to the page's ts_library() and/or generate_grd() build -# steps. -# -# If this is is instead a URL string starting with -# "chrome://resources/mojo", the resulting bindings files should -# be added to one of the lists in ui/webui/resources/mojo/BUILD.gn, -# at which point they will be made available to all WebUI pages at the -# given URL. -# -# Note: WebUI module bindings are generated in TypeScript by default, -# unless |generate_webui_js_bindings| is specified as true. -# -# The following parameters are used to support the component build. They are -# needed so that bindings which are linked with a component can use the same -# export settings for classes. The first three are for the chromium variant, and -# the last three are for the blink variant. These parameters can also override -# |component_macro_prefix| for a specific variant, allowing e.g. one variant -# to be linked into a larger non-mojom component target, while all other -# variants get their own unique component target. -# export_class_attribute (optional) -# The attribute to add to the class declaration. e.g. "CONTENT_EXPORT" -# export_define (optional) -# A define to be added to the source_set which is needed by the export -# header. e.g. "CONTENT_IMPLEMENTATION=1" -# export_header (optional) -# A header to be added to the generated bindings to support the component -# build. e.g. "content/common/content_export.h" -# export_class_attribute_blink (optional) -# export_define_blink (optional) -# export_header_blink (optional) -# These three parameters are the blink variants of the previous 3. -# -# The following parameters are used to correct component build dependencies. -# They are needed so mojom-mojom dependencies follow the rule that dependencies -# on a source set in another component are replaced by a dependency on the -# containing component. The first two are for the chromium variant; the other -# two are for the blink variant. -# overridden_deps (optional) -# The list of mojom deps to be overridden. -# component_deps (optional) -# The list of component deps to add to replace overridden_deps. -# overridden_deps_blink (optional) -# component_deps_blink (optional) -# These two parameters are the blink variants of the previous two. -# -# check_includes_blink (optional) -# Overrides the check_includes variable for the blink variant. -# If check_includes_blink is not defined, the check_includes variable -# retains its original value. -# -# Typemaps -# ======== -# The cpp_typemaps and blink_cpp_typemaps each specify an optional list of -# typemapping configurations. Each configuration is a GN scope with metadata -# describing what and how to map. -# -# Typemap scope parameters: -# types -# A list of type specifications for this typemap. Each type specification -# is a nested GN scope which can be expressed with the following syntax: -# -# { -# mojom = "foo.mojom.Bar" -# cpp = "::foo::LegitBar" -# move_only = true -# # etc... -# } -# -# Each type specification supports the following values: -# -# mojom (required) -# The fully qualified name of a mojom type to be mapped. This is a -# string like "foo.mojom.Bar". -# -# cpp (required) -# The fully qualified name of the C++ type to which the mojom type -# should be mapped in generated bindings. This is a string like -# "::base::Value" or "std::vector<::base::Value>". -# -# copyable_pass_by_value (optional) -# A boolean value (default false) which effectively indicates -# whether the C++ type is very cheap to copy. If so, generated -# bindings will pass by value but not use std::move() at call sites. -# -# default_constructible (optional) -# A boolean value (default true) which indicates whether the C++ -# type is default constructible. If a C++ type is not default -# constructible (e.g. the implementor of the type prefers not to -# publicly expose a default constructor that creates an object in an -# invalid state), Mojo will instead construct C++ type with an -# argument of the type `mojo::DefaultConstruct::Tag` (essentially a -# passkey-like type specifically for this use case). -# -# force_serialize (optional) -# A boolean value (default false) which disables lazy serialization -# of the typemapped type if lazy serialization is enabled for the -# mojom target applying this typemap. -# -# forward_declaration (optional) -# A forward declaration of the C++ type, which bindings that don't -# need the full type definition can use to reduce the size of -# the generated code. This is a string like -# "namespace base { class Value; }". -# -# hashable (optional) -# A boolean value (default false) indicating whether the C++ type is -# hashable. Set to true if true AND needed (i.e. you need to use the -# type as the key of a mojom map). -# -# move_only (optional) -# A boolean value (default false) which indicates whether the C++ -# type is move-only. If true, generated bindings will pass the type -# by value and use std::move() at call sites. -# -# nullable_is_same_type (optional) -# A boolean value (default false) which indicates that the C++ type -# has some baked-in semantic notion of a "null" state. If true, the -# traits for the type must define IsNull and SetToNull methods. -# -# When false, nullable fields are represented by wrapping the C++ -# type with absl::optional, and null values are simply -# absl::nullopt. -# -# Additional typemap scope parameters: -# -# traits_headers (optional) -# Headers which must be included in the generated mojom in order for -# serialization to be possible. This generally means including at least -# the header for the corresponding mojom traits definitions. -# -# traits_private_headers (optional) -# Headers which must be included in generated C++ serialization code for -# a mojom using the typemap. This should be used only when including a -# header in |traits_headers| is problematic for compilation, as is -# sometimes the case with legacy IPC message headers. -# -# traits_sources (optional) -# The references to the source files (typically a single .cc and .h file) -# defining an appropriate set of EnumTraits or StructTraits, etc for the -# the type-mapping. Using this will cause the listed sources to be -# integrated directly into the dependent mojom's generated type-mapping -# targets. -# -# Prefer using |traits_public_deps| over inlined |traits_sources|, as this -# will generally lead to easier build maintenance over time. -# -# NOTE: If a typemap is shared by Blink and non-Blink bindings, you cannot -# use this and MUST use |traits_public_deps| to reference traits built -# within a separate target. -# -# traits_deps / traits_public_deps (optional) -# Any dependencies of sources in |traits_headers| or |traits_sources| must -# be listed here. -# -template("mojom") { - assert( - defined(invoker.sources) || defined(invoker.deps) || - defined(invoker.public_deps), - "\"sources\" or \"deps\" must be defined for the $target_name template.") - - if (defined(invoker.export_class_attribute) || - defined(invoker.export_define) || defined(invoker.export_header)) { - assert(defined(invoker.export_class_attribute)) - assert(defined(invoker.export_define) || defined(invoker.cpp_configs)) - assert(defined(invoker.export_header)) - } - if (defined(invoker.export_class_attribute_blink) || - defined(invoker.export_define_blink) || - defined(invoker.export_header_blink)) { - assert(defined(invoker.export_class_attribute_blink)) - assert(defined(invoker.export_define_blink) || - defined(invoker.blink_cpp_configs)) - assert(defined(invoker.export_header_blink)) - - # Not all platforms use the Blink variant, so make sure GN doesn't complain - # about these values being inconsequential. - not_needed(invoker, - [ - "export_class_attribute_blink", - "export_define_blink", - "export_header_blink", - ]) - } - if (defined(invoker.overridden_deps) || defined(invoker.component_deps)) { - assert(defined(invoker.overridden_deps)) - assert(defined(invoker.component_deps)) - } - - if (defined(invoker.overridden_deps_blink) || - defined(invoker.component_deps_blink)) { - assert(defined(invoker.overridden_deps_blink)) - assert(defined(invoker.component_deps_blink)) - } - - # Type-mapping may be disabled or we may not generate C++ bindings. - not_needed(invoker, - [ - "cpp_typemaps", - "blink_cpp_typemaps", - ]) - - require_full_cpp_deps = - !defined(invoker.disallow_native_types) || - !invoker.disallow_native_types || !defined(invoker.disallow_interfaces) || - !invoker.disallow_interfaces - - all_deps = [] - mojom_cpp_deps = [] - if (defined(invoker.deps)) { - all_deps += invoker.deps - mojom_cpp_deps += invoker.deps - } - if (defined(invoker.public_deps)) { - all_deps += invoker.public_deps - mojom_cpp_deps += invoker.public_deps - } - if (defined(invoker.mojom_source_deps)) { - all_deps += invoker.mojom_source_deps - } - if (defined(invoker.mojom_blink_source_deps)) { - all_deps += invoker.mojom_blink_source_deps - } - not_needed([ "mojom_deps" ]) - - if (defined(invoker.component_macro_prefix)) { - assert(defined(invoker.component_output_prefix)) - } - - group("${target_name}__is_mojom") { - } - - # Explicitly ensure that all dependencies (invoker.deps and - # invoker.public_deps) are mojom targets. - group("${target_name}__check_deps_are_all_mojom") { - deps = [] - foreach(d, all_deps) { - name = get_label_info(d, "label_no_toolchain") - toolchain = get_label_info(d, "toolchain") - deps += [ "${name}__is_mojom(${toolchain})" ] - } - } - - sources_list = [] - if (defined(invoker.sources)) { - sources_list = invoker.sources - } - - # Listed sources may be relative to the current target dir, or they may be - # absolute paths, including paths to generated mojom files. While those are - # fine as-is for input references, deriving output paths can be more subtle. - # - # Here we rewrite all source paths to be relative to the root build dir and - # strip any root_gen_dir prefixes. - # - # So for a target in //foo/bar with: - # - # sources = [ - # "a.mojom", - # "b/c.mojom", - # "//baz/d.mojom", - # "$target_gen_dir/e.mojom", - # ] - # - # output_file_base_paths will be: - # - # [ - # "foo/bar/a.mojom", - # "foo/bar/b/c.mojom", - # "baz/d.mojom", - # "foo/bar/e.mojom", - # ] - # - # This result is essentially a list of base filename paths which are suitable - # for the naming of any generated output files derived from their - # corresponding input mojoms. These paths are always considered to be relative - # to root_gen_dir. - if (defined(invoker.input_root_override)) { - source_abspaths = rebase_path(sources_list, invoker.input_root_override) - } else { - source_abspaths = rebase_path(sources_list, "//") - } - output_file_base_paths = [] - foreach(path, source_abspaths) { - output_file_base_paths += - [ string_replace(path, rebase_path(root_gen_dir, "//") + "/", "") ] - } - - # Sanity check that either all input files have a .mojom extension, or - # all input files have a .test-mojom extension AND |testonly| is |true|. - sources_list_filenames = - process_file_template(sources_list, "{{source_file_part}}") - sources_list_filenames_with_mojom_extension = - process_file_template(sources_list, "{{source_name_part}}.mojom") - if (sources_list_filenames != sources_list_filenames_with_mojom_extension) { - sources_list_filenames_with_test_mojom_extension = - process_file_template(sources_list, "{{source_name_part}}.test-mojom") - if (sources_list_filenames == - sources_list_filenames_with_test_mojom_extension) { - assert( - defined(invoker.testonly) && invoker.testonly, - "mojom targets for .test-mojom files must set |testonly| to |true|") - } else { - assert( - false, - "One or more mojom files has an invalid extension. The only " + - "allowed extensions are .mojom and .test-mojom, and any given " + - "mojom target must use one or the other exclusively.") - } - } - - build_metadata_filename = "$target_gen_dir/$target_name.build_metadata" - build_metadata = { - } - build_metadata.sources = rebase_path(sources_list, target_gen_dir) - build_metadata.deps = [] - foreach(dep, all_deps) { - dep_target_gen_dir = get_label_info(dep, "target_gen_dir") - dep_name = get_label_info(dep, "name") - build_metadata.deps += - [ rebase_path("$dep_target_gen_dir/$dep_name.build_metadata", - target_gen_dir) ] - } - write_file(build_metadata_filename, build_metadata, "json") - - generate_js_fuzzing = - (!defined(invoker.enable_js_fuzzing) || invoker.enable_js_fuzzing) && - enable_mojom_fuzzer && (!defined(invoker.testonly) || !invoker.testonly) - - generate_mojolpm_fuzzing = - (!defined(invoker.enable_mojolpm_fuzzing) || - invoker.enable_mojolpm_fuzzing) && enable_mojom_fuzzer && - (!defined(invoker.testonly) || !invoker.testonly) - - parser_target_name = "${target_name}__parser" - parser_deps = [] - foreach(dep, all_deps) { - _label = get_label_info(dep, "label_no_toolchain") - parser_deps += [ "${_label}__parser" ] - } - if (defined(invoker.parser_deps)) { - parser_deps += invoker.parser_deps - } - if (sources_list == []) { - # Even without sources we generate a parser target to at least forward - # other parser dependencies. - group(parser_target_name) { - public_deps = parser_deps - } - } else { - enabled_features = [] - if (defined(invoker.enabled_features)) { - enabled_features += invoker.enabled_features - } - if (is_posix) { - enabled_features += [ "is_posix" ] - } - if (is_android) { - enabled_features += [ "is_android" ] - } else if (is_chromeos_ash) { - enabled_features += [ - "is_chromeos", - "is_chromeos_ash", - ] - } else if (is_chromeos_lacros) { - enabled_features += [ - "is_chromeos", - "is_chromeos_lacros", - ] - } else if (is_fuchsia) { - enabled_features += [ "is_fuchsia" ] - } else if (is_ios) { - enabled_features += [ "is_ios" ] - } else if (is_linux) { - enabled_features += [ "is_linux" ] - } else if (is_mac) { - enabled_features += [ "is_mac" ] - } else if (is_win) { - enabled_features += [ "is_win" ] - } - - if (is_apple) { - enabled_features += [ "is_apple" ] - } - - action(parser_target_name) { - allow_remote = true - custom_processor = "mojom_parser" - script = mojom_parser_script - inputs = mojom_parser_sources + ply_sources + [ build_metadata_filename ] - sources = sources_list - public_deps = parser_deps - outputs = [] - foreach(base_path, output_file_base_paths) { - filename = get_path_info(base_path, "file") - dirname = get_path_info(base_path, "dir") - outputs += [ "$root_gen_dir/$dirname/${filename}-module" ] - } - - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - - # Workaround for https://github.com/ninja-build/ninja/issues/1966. - rsp_file = "$target_gen_dir/${target_name}.rsp" - write_file(rsp_file, filelist) - inputs += [ rsp_file ] - - args = [ - # Resolve relative input mojom paths against both the root src dir and - # the root gen dir. - "--input-root", - rebase_path("//.", root_build_dir), - "--input-root", - rebase_path(root_gen_dir, root_build_dir), - - "--output-root", - rebase_path(root_gen_dir, root_build_dir), - - "--mojom-file-list=" + rebase_path(rsp_file, root_build_dir), - - "--check-imports", - rebase_path(build_metadata_filename, root_build_dir), - ] - - if (defined(invoker.input_root_override)) { - args += [ - "--input-root", - rebase_path(invoker.input_root_override, root_build_dir), - ] - } - - foreach(enabled_feature, enabled_features) { - args += [ - "--enable-feature", - enabled_feature, - ] - } - - if (defined(invoker.webui_module_path)) { - args += [ - "--add-module-metadata", - "webui_module_path=${invoker.webui_module_path}", - ] - if (defined(invoker.generate_webui_js_bindings) && - invoker.generate_webui_js_bindings) { - args += [ - "--add-module-metadata", - "generate_webui_js=True", - ] - } - } - } - } - - generator_cpp_message_ids_target_name = "${target_name}__generate_message_ids" - - # Generate code that is shared by different variants. - if (sources_list != []) { - base_dir = "//" - if (defined(invoker.input_root_override)) { - base_dir = invoker.input_root_override - } - - common_generator_args = [ - "--use_bundled_pylibs", - "-o", - rebase_path(root_gen_dir, root_build_dir), - "generate", - "-d", - rebase_path(base_dir, root_build_dir), - "-I", - rebase_path("//", root_build_dir), - "--bytecode_path", - rebase_path("$root_gen_dir/mojo/public/tools/bindings", root_build_dir), - ] - if (defined(invoker.input_root_override)) { - common_generator_args += [ - "-I", - rebase_path(invoker.input_root_override, root_build_dir), - ] - } - - if (defined(invoker.disallow_native_types) && - invoker.disallow_native_types) { - common_generator_args += [ "--disallow_native_types" ] - } - - if (defined(invoker.disallow_interfaces) && invoker.disallow_interfaces) { - common_generator_args += [ "--disallow_interfaces" ] - } - - if (defined(invoker.import_dirs)) { - foreach(import_dir, invoker.import_dirs) { - common_generator_args += [ - "-I", - rebase_path(import_dir, root_build_dir), - ] - } - } - - if (defined(invoker.component_macro_prefix)) { - shared_component_export_macro = - "COMPONENT_EXPORT(${invoker.component_macro_prefix}_SHARED)" - shared_component_impl_macro = - "IS_${invoker.component_macro_prefix}_SHARED_IMPL" - shared_component_output_name = "${invoker.component_output_prefix}_shared" - } else if (defined(invoker.export_class_attribute_shared) || - defined(invoker.export_class_attribute)) { - if (defined(invoker.export_class_attribute_shared)) { - assert(defined(invoker.export_header_shared)) - shared_component_export_macro = invoker.export_class_attribute_shared - shared_component_impl_macro = invoker.export_define_shared - } else { - assert(!defined(invoker.export_header_shared)) - - # If no explicit shared attribute/define was provided by the invoker, - # we derive some reasonable settings frorm the default variant. - shared_component_export_macro = "COMPONENT_EXPORT(MOJOM_SHARED_" + - invoker.export_class_attribute + ")" - shared_component_impl_macro = - "IS_MOJOM_SHARED_" + invoker.export_class_attribute + "_IMPL" - } - - if (defined(invoker.component_output_prefix)) { - shared_component_output_name = - "${invoker.component_output_prefix}_shared" - } else { - shared_component_output_name = "${target_name}_shared" - } - } - - action(generator_cpp_message_ids_target_name) { - allow_remote = true - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = sources_list + - [ "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip" ] - deps = [ - ":$parser_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - if (defined(invoker.parser_deps)) { - deps += invoker.parser_deps - } - outputs = [] - args = common_generator_args - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - foreach(base_path, output_file_base_paths) { - filename = get_path_info(base_path, "file") - dirname = get_path_info(base_path, "dir") - inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] - outputs += [ "$root_gen_dir/$base_path-shared-message-ids.h" ] - } - - # Workaround for https://github.com/ninja-build/ninja/issues/1966. - rsp_file = "$target_gen_dir/${target_name}.rsp" - write_file(rsp_file, filelist) - inputs += [ rsp_file ] - - args += [ - "--filelist=" + rebase_path(rsp_file, root_build_dir), - "--generate_non_variant_code", - "--generate_message_ids", - "-g", - "c++", - ] - - if (!defined(invoker.scramble_message_ids) || - invoker.scramble_message_ids) { - inputs += message_scrambling_inputs - args += message_scrambling_args - } - } - - generator_shared_target_name = "${target_name}_shared__generator" - - action(generator_shared_target_name) { - allow_remote = true - visibility = [ ":*" ] - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = sources_list + - [ "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip" ] - deps = [ - ":$parser_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - if (defined(invoker.parser_deps)) { - deps += invoker.parser_deps - } - - outputs = [] - args = common_generator_args - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - foreach(base_path, output_file_base_paths) { - # Need the mojom-module as an input to this action. - filename = get_path_info(base_path, "file") - dirname = get_path_info(base_path, "dir") - inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] - - outputs += [ - "$root_gen_dir/$base_path-features.h", - "$root_gen_dir/$base_path-params-data.h", - "$root_gen_dir/$base_path-shared-internal.h", - "$root_gen_dir/$base_path-shared.cc", - "$root_gen_dir/$base_path-shared.h", - ] - } - - # Workaround for https://github.com/ninja-build/ninja/issues/1966. - rsp_file = "$target_gen_dir/${target_name}.rsp" - write_file(rsp_file, filelist) - inputs += [ rsp_file ] - - args += [ - "--filelist=" + rebase_path(rsp_file, root_build_dir), - "--generate_non_variant_code", - "-g", - "c++", - ] - - if (defined(shared_component_export_macro)) { - args += [ - "--export_attribute", - shared_component_export_macro, - "--export_header", - "base/component_export.h", - ] - } - - # Enable adding annotations to generated C++ headers that are used for - # cross-references in CodeSearch. - if (enable_kythe_annotations) { - args += [ "--enable_kythe_annotations" ] - } - } - } else { - group(generator_cpp_message_ids_target_name) { - } - } - - shared_cpp_sources_target_name = "${target_name}_shared_cpp_sources" - source_set(shared_cpp_sources_target_name) { - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [] - public_deps = [] - if (output_file_base_paths != []) { - sources = [] - foreach(base_path, output_file_base_paths) { - sources += [ - "$root_gen_dir/$base_path-features.h", - "$root_gen_dir/$base_path-params-data.h", - "$root_gen_dir/$base_path-shared-internal.h", - "$root_gen_dir/$base_path-shared.cc", - "$root_gen_dir/$base_path-shared.h", - ] - } - public_deps += [ ":$generator_shared_target_name" ] - } - if (require_full_cpp_deps) { - public_deps += [ "//mojo/public/cpp/bindings" ] - } else { - public_deps += [ "//mojo/public/cpp/bindings:bindings_base" ] - } - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append shared_cpp_sources_suffix - # to get the cpp dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - public_deps += [ "${full_name}_shared" ] - } - if (defined(shared_component_impl_macro)) { - defines = [ shared_component_impl_macro ] - } - } - - shared_cpp_library_target_name = "${target_name}_shared" - if (defined(shared_component_output_name)) { - component(shared_cpp_library_target_name) { - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - output_name = "$shared_component_output_name" - public_deps = [ ":$shared_cpp_sources_target_name" ] - } - } else { - group(shared_cpp_library_target_name) { - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - public_deps = [ ":$shared_cpp_sources_target_name" ] - } - } - - if (generate_mojolpm_fuzzing) { - # This block generates the proto files used for the MojoLPM fuzzer, - # and the corresponding proto targets that will be linked in the fuzzer - # targets. These are independent of the typemappings, and can be done - # separately here. - - generator_mojolpm_proto_target_name = - "${target_name}_mojolpm_proto_generator" - - action(generator_mojolpm_proto_target_name) { - allow_remote = true - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = - invoker.sources + [ - "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip", - "$root_gen_dir/mojo/public/tools/bindings/mojolpm_templates.zip", - ] - deps = [ - ":$parser_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - - outputs = [] - args = common_generator_args - filelist = [] - - # Split the input into generated and non-generated source files. They - # need to be processed separately. - gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" - non_gen_sources = - filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) - gen_sources = filter_include(invoker.sources, [ gen_dir_path_wildcard ]) - - foreach(source, non_gen_sources) { - filelist += [ rebase_path(source, root_build_dir) ] - inputs += [ "$target_gen_dir/$source-module" ] - outputs += [ "$target_gen_dir/$source.mojolpm.proto" ] - } - - foreach(source, gen_sources) { - filelist += [ rebase_path(source, root_build_dir) ] - - # For generated files, we assume they're in the target_gen_dir or a - # sub-folder of it. Rebase the path so we can get the relative location. - source_file = rebase_path(source, target_gen_dir) - inputs += [ "$target_gen_dir/$source_file-module" ] - outputs += [ "$target_gen_dir/$source_file.mojolpm.proto" ] - } - - # Workaround for https://github.com/ninja-build/ninja/issues/1966. - rsp_file = "$target_gen_dir/${target_name}.rsp" - write_file(rsp_file, filelist) - inputs += [ rsp_file ] - - args += [ - "--filelist=" + rebase_path(rsp_file, root_build_dir), - "--generate_non_variant_code", - "-g", - "mojolpm", - ] - } - - mojolpm_proto_target_name = "${target_name}_mojolpm_proto" - if (defined(invoker.sources)) { - proto_library(mojolpm_proto_target_name) { - testonly = true - generate_python = false - - # Split the input into generated and non-generated source files. They - # need to be processed separately. - gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" - non_gen_sources = - filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) - gen_sources = filter_include(invoker.sources, [ gen_dir_path_wildcard ]) - sources = process_file_template( - non_gen_sources, - [ "{{source_gen_dir}}/{{source_file_part}}.mojolpm.proto" ]) - sources += process_file_template( - gen_sources, - [ "{{source_dir}}/{{source_file_part}}.mojolpm.proto" ]) - - import_dirs = [ "//" ] - proto_in_dir = "${root_gen_dir}" - proto_out_dir = "." - proto_deps = [ ":$generator_mojolpm_proto_target_name" ] - link_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ] - - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append mojolpm_proto_suffix - # to get the proto dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - proto_deps += [ "${full_name}_mojolpm_proto" ] - link_deps += [ "${full_name}_mojolpm_proto" ] - } - } - } else { - group(mojolpm_proto_target_name) { - testonly = true - public_deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ] - if (defined(generator_shared_target_name)) { - public_deps += [ ":$generator_shared_target_name" ] - } - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append #mojolpm_proto_suffix - # to get the proto dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - public_deps += [ "${full_name}_mojolpm_proto" ] - } - } - } - } - - # Generate code for variants. - default_variant = { - component_macro_suffix = "" - } - if ((!defined(invoker.disable_variants) || !invoker.disable_variants) && - use_blink) { - blink_variant = { - variant = "blink" - component_macro_suffix = "_BLINK" - for_blink = true - } - enabled_configurations = [ - default_variant, - blink_variant, - ] - } else { - enabled_configurations = [ default_variant ] - } - foreach(bindings_configuration, enabled_configurations) { - cpp_only = false - if (defined(invoker.cpp_only)) { - cpp_only = invoker.cpp_only - } - variant_suffix = "" - if (defined(bindings_configuration.variant)) { - variant = bindings_configuration.variant - variant_suffix = "_${variant}" - cpp_only = true - } - - cpp_typemap_configs = [] - export_defines = [] - export_defines_overridden = false - force_source_set = false - proxy_target = "" - extra_configs = [] - output_visibility = [] - output_visibility = [ "*" ] - cpp_source_deps = [] - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - if (defined(invoker.blink_cpp_typemaps)) { - cpp_typemap_configs = invoker.blink_cpp_typemaps - } - if (defined(invoker.export_define_blink)) { - export_defines_overridden = true - export_defines = [ invoker.export_define_blink ] - force_source_set = true - } - if (defined(invoker.blink_cpp_configs)) { - extra_configs += invoker.blink_cpp_configs - } - if (defined(invoker.blink_cpp_proxy_target)) { - proxy_target = invoker.blink_cpp_proxy_target - } - if (defined(invoker.visibility_blink)) { - output_visibility = [] - output_visibility = invoker.visibility_blink - } - if (defined(invoker.mojom_blink_source_deps)) { - cpp_source_deps = invoker.mojom_blink_source_deps - } - } else { - if (defined(invoker.cpp_typemaps)) { - cpp_typemap_configs = invoker.cpp_typemaps - } - if (defined(invoker.export_define)) { - export_defines_overridden = true - export_defines = [ invoker.export_define ] - force_source_set = true - } - if (defined(invoker.cpp_configs)) { - extra_configs += invoker.cpp_configs - } - if (defined(invoker.cpp_proxy_target)) { - proxy_target = invoker.cpp_proxy_target - } - if (defined(invoker.visibility)) { - output_visibility = [] - output_visibility = invoker.visibility - } - if (defined(invoker.mojom_source_deps)) { - cpp_source_deps = invoker.mojom_source_deps - } - } - not_needed([ "cpp_typemap_configs" ]) - if (proxy_target != "") { - group("${target_name}${variant_suffix}__has_cpp_proxy") { - } - } - - if (!export_defines_overridden && defined(invoker.component_macro_prefix)) { - output_name_override = - "${invoker.component_output_prefix}${variant_suffix}" - export_defines = - [ "IS_${invoker.component_macro_prefix}" + - "${bindings_configuration.component_macro_suffix}_IMPL" ] - } - - generate_java = false - if (!cpp_only && defined(invoker.generate_java)) { - generate_java = invoker.generate_java - } - type_mappings_target_name = "${target_name}${variant_suffix}__type_mappings" - type_mappings_path = - "$target_gen_dir/${target_name}${variant_suffix}__type_mappings" - if (sources_list != []) { - export_args = [] - export_args_overridden = false - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - if (defined(invoker.export_class_attribute_blink)) { - export_args_overridden = true - export_args += [ - "--export_attribute", - invoker.export_class_attribute_blink, - "--export_header", - invoker.export_header_blink, - ] - } - } else if (defined(invoker.export_class_attribute)) { - export_args_overridden = true - export_args += [ - "--export_attribute", - invoker.export_class_attribute, - "--export_header", - invoker.export_header, - ] - } - if (!export_args_overridden && defined(invoker.component_macro_prefix)) { - export_args += [ - "--export_attribute", - "COMPONENT_EXPORT(${invoker.component_macro_prefix}" + - "${bindings_configuration.component_macro_suffix})", - "--export_header", - "base/component_export.h", - ] - } - - generator_cpp_output_suffixes = [] - variant_dash_suffix = "" - if (defined(variant)) { - variant_dash_suffix = "-${variant}" - } - generator_cpp_output_suffixes += [ - "${variant_dash_suffix}-forward.h", - "${variant_dash_suffix}-import-headers.h", - "${variant_dash_suffix}-test-utils.h", - "${variant_dash_suffix}.cc", - "${variant_dash_suffix}.h", - ] - - generator_target_name = "${target_name}${variant_suffix}__generator" - - # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. - action(generator_target_name) { - allow_remote = true - visibility = [ ":*" ] - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = - sources_list + [ - "$root_gen_dir/mojo/public/tools/bindings/cpp_templates.zip", - type_mappings_path, - ] - if (generate_mojolpm_fuzzing && - !defined(bindings_configuration.variant)) { - sources += [ - "$root_gen_dir/mojo/public/tools/bindings/mojolpm_templates.zip", - ] - } - deps = [ - ":$parser_target_name", - ":$type_mappings_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - - if (defined(invoker.parser_deps)) { - deps += invoker.parser_deps - } - outputs = [] - args = common_generator_args + export_args - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - foreach(base_path, output_file_base_paths) { - filename = get_path_info(base_path, "file") - dirname = get_path_info(base_path, "dir") - inputs += [ "$root_gen_dir/$dirname/${filename}-module" ] - - outputs += [ - "$root_gen_dir/${base_path}${variant_dash_suffix}-forward.h", - "$root_gen_dir/${base_path}${variant_dash_suffix}-import-headers.h", - "$root_gen_dir/${base_path}${variant_dash_suffix}-test-utils.h", - "$root_gen_dir/${base_path}${variant_dash_suffix}.cc", - "$root_gen_dir/${base_path}${variant_dash_suffix}.h", - ] - if (generate_mojolpm_fuzzing && - !defined(bindings_configuration.variant)) { - outputs += [ - "$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.cc", - "$root_gen_dir/${base_path}${variant_dash_suffix}-mojolpm.h", - ] - } - } - - # Workaround for https://github.com/ninja-build/ninja/issues/1966. - rsp_file = "$target_gen_dir/${target_name}.rsp" - write_file(rsp_file, filelist) - inputs += [ rsp_file ] - args += [ - "--filelist=" + rebase_path("$rsp_file", root_build_dir), - "-g", - ] - - if (generate_mojolpm_fuzzing && - !defined(bindings_configuration.variant)) { - args += [ "c++,mojolpm" ] - } else { - args += [ "c++" ] - } - - if (defined(bindings_configuration.variant)) { - args += [ - "--variant", - bindings_configuration.variant, - ] - } - - args += [ - "--typemap", - rebase_path(type_mappings_path, root_build_dir), - ] - - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - args += [ "--for_blink" ] - } - - if (defined(invoker.support_lazy_serialization) && - invoker.support_lazy_serialization) { - args += [ "--support_lazy_serialization" ] - } - - if (enable_kythe_annotations) { - args += [ "--enable_kythe_annotations" ] - } - - if (!defined(invoker.scramble_message_ids) || - invoker.scramble_message_ids) { - inputs += message_scrambling_inputs - args += message_scrambling_args - } - - if (defined(invoker.extra_cpp_template_paths)) { - foreach(extra_cpp_template, invoker.extra_cpp_template_paths) { - args += [ - "--extra_cpp_template_paths", - rebase_path(extra_cpp_template, root_build_dir), - ] - inputs += [ extra_cpp_template ] - - assert( - get_path_info(extra_cpp_template, "extension") == "tmpl", - "--extra_cpp_template_paths only accepts template files ending in extension .tmpl") - foreach(base_path, output_file_base_paths) { - template_file_name = get_path_info("$extra_cpp_template", "name") - outputs += [ "$root_gen_dir/${base_path}${variant_dash_suffix}-${template_file_name}" ] - } - } - } - } - } - - # Write the typemapping configuration for this target out to a file to be - # validated by a Python script. This helps catch mistakes that can't - # be caught by logic in GN. - _typemap_config_filename = - "$target_gen_dir/${target_name}${variant_suffix}.typemap_config" - _typemap_stamp_filename = "${_typemap_config_filename}.validated" - _typemap_validator_target_name = "${type_mappings_target_name}__validator" - _rebased_typemap_configs = [] - foreach(config, cpp_typemap_configs) { - _rebased_config = { - } - _rebased_config = config - if (defined(config.traits_headers)) { - _rebased_config.traits_headers = [] - _rebased_config.traits_headers = - rebase_path(config.traits_headers, "//") - } - if (defined(config.traits_private_headers)) { - _rebased_config.traits_private_headers = [] - _rebased_config.traits_private_headers = - rebase_path(config.traits_private_headers, "//") - } - _rebased_typemap_configs += [ _rebased_config ] - } - write_file(_typemap_config_filename, _rebased_typemap_configs, "json") - _mojom_target_name = target_name - - action(_typemap_validator_target_name) { - allow_remote = true - script = "$mojom_generator_root/validate_typemap_config.py" - inputs = [ _typemap_config_filename ] - outputs = [ _typemap_stamp_filename ] - args = [ - get_label_info(_mojom_target_name, "label_no_toolchain"), - rebase_path(_typemap_config_filename, root_build_dir), - rebase_path(_typemap_stamp_filename, root_build_dir), - ] - } - - action(type_mappings_target_name) { - allow_remote = true - inputs = - mojom_generator_sources + jinja2_sources + [ _typemap_stamp_filename ] - outputs = [ type_mappings_path ] - script = "$mojom_generator_root/generate_type_mappings.py" - deps = [ ":$_typemap_validator_target_name" ] - args = [ - "--output", - rebase_path(type_mappings_path, root_build_dir), - ] - - sources = [] - foreach(d, all_deps) { - name = get_label_info(d, "label_no_toolchain") - toolchain = get_label_info(d, "toolchain") - dependency_output = "${name}${variant_suffix}__type_mappings" - dependency_target = "${dependency_output}(${toolchain})" - deps += [ dependency_target ] - dependency_output_dir = - get_label_info(dependency_output, "target_gen_dir") - dependency_name = get_label_info(dependency_output, "name") - dependency_path = "$dependency_output_dir/${dependency_name}" - sources += [ dependency_path ] - args += [ - "--dependency", - rebase_path(dependency_path, root_build_dir), - ] - } - - # Newer GN-based typemaps are aggregated into a single config. - inputs += [ _typemap_config_filename ] - args += [ - "--cpp-typemap-config", - rebase_path(_typemap_config_filename, root_build_dir), - ] - } - - group("${target_name}${variant_suffix}_headers") { - public_deps = [] - if (sources_list != []) { - public_deps += [ - ":$generator_cpp_message_ids_target_name", - ":$generator_shared_target_name", - ":$generator_target_name", - ] - } - foreach(d, all_deps) { - full_name = get_label_info("$d", "label_no_toolchain") - public_deps += [ "${full_name}${variant_suffix}_headers" ] - } - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] - } - } - - js_data_deps_target_name = target_name + "_js_data_deps" - not_needed([ "js_data_deps_target_name" ]) - - if (!force_source_set && defined(invoker.component_macro_prefix)) { - sources_target_type = "component" - } else { - sources_target_type = "source_set" - } - - output_target_name = "${target_name}${variant_suffix}" - if (proxy_target != "") { - group(output_target_name) { - public_deps = [ proxy_target ] - visibility = output_visibility - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - } - sources_target_name = "${output_target_name}_cpp_sources" - } else { - sources_target_name = output_target_name - } - - target(sources_target_type, sources_target_name) { - if (defined(output_name_override)) { - output_name = output_name_override - } - visibility = output_visibility + [ - ":$output_target_name", - ":${target_name}_mojolpm", - ] - if (defined(invoker.testonly)) { - testonly = invoker.testonly - } - defines = export_defines - configs += [ "//build/config/compiler:wexit_time_destructors" ] - configs += extra_configs - if (output_file_base_paths != []) { - sources = [] - foreach(base_path, output_file_base_paths) { - foreach(suffix, generator_cpp_output_suffixes) { - sources += [ "$root_gen_dir/${base_path}$suffix" ] - } - } - } - deps = [ - ":$generator_cpp_message_ids_target_name", - "//mojo/public/cpp/bindings:struct_traits", - "//mojo/public/interfaces/bindings:bindings_headers", - ] - public_deps = [ - ":$shared_cpp_library_target_name", - "//base", - ] - if (require_full_cpp_deps) { - public_deps += [ "//mojo/public/cpp/bindings" ] - } else { - public_deps += [ "//mojo/public/cpp/bindings:bindings_base" ] - } - - if (sources_list != []) { - public_deps += [ ":$generator_target_name" ] - } - foreach(d, mojom_cpp_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append variant_suffix to - # get the cpp dependency name. - full_name = get_label_info(d, "label_no_toolchain") - public_deps += [ "${full_name}${variant_suffix}" ] - } - foreach(d, cpp_source_deps) { - full_name = get_label_info(d, "label_no_toolchain") - public_deps += [ - "${full_name}${variant_suffix}__has_cpp_proxy", - "${full_name}${variant_suffix}_cpp_sources", - ] - } - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - if (defined(invoker.overridden_deps_blink)) { - foreach(d, invoker.overridden_deps_blink) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append variant_suffix - # to get the cpp dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - public_deps -= [ "${full_name}${variant_suffix}" ] - } - public_deps += invoker.component_deps_blink - } - if (defined(invoker.check_includes_blink)) { - check_includes = invoker.check_includes_blink - } - } else { - if (defined(invoker.check_includes_blink)) { - not_needed(invoker, [ "check_includes_blink" ]) - } - if (defined(invoker.overridden_deps)) { - foreach(d, invoker.overridden_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append variant_suffix - # to get the cpp dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - public_deps -= [ "${full_name}${variant_suffix}" ] - } - public_deps += invoker.component_deps - } - } - foreach(config, cpp_typemap_configs) { - if (defined(config.traits_sources)) { - sources += config.traits_sources - } - if (defined(config.traits_deps)) { - deps += config.traits_deps - } - if (defined(config.traits_public_deps)) { - public_deps += config.traits_public_deps - } - } - if (defined(bindings_configuration.for_blink) && - bindings_configuration.for_blink) { - public_deps += [ "//mojo/public/cpp/bindings:wtf_support" ] - } - } - - if (generate_mojolpm_fuzzing && !defined(variant)) { - # This block contains the C++ targets for the MojoLPM fuzzer, we need to - # do this here so that we can use the typemap configuration for the - # empty-variant Mojo target. - - mojolpm_target_name = "${target_name}_mojolpm" - mojolpm_generator_target_name = "${target_name}__generator" - source_set(mojolpm_target_name) { - # There are still a few missing header dependencies between mojo targets - # with typemaps and the dependencies of their typemap headers. It would - # be good to enable include checking for these in the future though. - check_includes = false - testonly = true - if (defined(invoker.sources)) { - # Split the input into generated and non-generated source files. They - # need to be processed separately. - gen_dir_path_wildcard = get_path_info("//", "gen_dir") + "/*" - non_gen_sources = - filter_exclude(invoker.sources, [ gen_dir_path_wildcard ]) - gen_sources = - filter_include(invoker.sources, [ gen_dir_path_wildcard ]) - sources = process_file_template( - non_gen_sources, - [ - "{{source_gen_dir}}/{{source_file_part}}-mojolpm.cc", - "{{source_gen_dir}}/{{source_file_part}}-mojolpm.h", - ]) - sources += process_file_template( - gen_sources, - [ - "{{source_dir}}/{{source_file_part}}-mojolpm.cc", - "{{source_dir}}/{{source_file_part}}-mojolpm.h", - ]) - deps = [ ":$output_target_name" ] - } else { - sources = [] - deps = [] - } - - public_deps = [ - ":$generator_shared_target_name", - - # NB: hardcoded dependency on the no-variant variant generator, since - # mojolpm only uses the no-variant type. - ":$mojolpm_generator_target_name", - ":$mojolpm_proto_target_name", - "//base", - "//mojo/public/tools/fuzzers:mojolpm", - ] - - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append variant_suffix to - # get the cpp dependency name. - full_name = get_label_info("$d", "label_no_toolchain") - public_deps += [ "${full_name}_mojolpm" ] - } - - foreach(config, cpp_typemap_configs) { - if (defined(config.traits_deps)) { - deps += config.traits_deps - } - if (defined(config.traits_public_deps)) { - public_deps += config.traits_public_deps - } - } - } - } - - if (generate_java && is_android) { - import("//build/config/android/rules.gni") - - java_generator_target_name = target_name + "_java__generator" - if (sources_list != []) { - action(java_generator_target_name) { - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = sources_list - deps = [ - ":$parser_target_name", - ":$type_mappings_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - outputs = [] - args = common_generator_args - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - foreach(base_path, output_file_base_paths) { - outputs += [ "$root_gen_dir/$base_path.srcjar" ] - } - - response_file_contents = filelist - - args += [ - "--filelist={{response_file_name}}", - "-g", - "java", - ] - - if (!defined(invoker.scramble_message_ids) || - invoker.scramble_message_ids) { - inputs += message_scrambling_inputs - args += message_scrambling_args - } - } - } else { - group(java_generator_target_name) { - } - } - - java_srcjar_target_name = target_name + "_java_sources" - - action(java_srcjar_target_name) { - script = "//build/android/gyp/zip.py" - inputs = [] - if (output_file_base_paths != []) { - foreach(base_path, output_file_base_paths) { - inputs += [ "$root_gen_dir/${base_path}.srcjar" ] - } - } - output = "$target_gen_dir/$target_name.srcjar" - outputs = [ output ] - rebase_inputs = rebase_path(inputs, root_build_dir) - rebase_output = rebase_path(output, root_build_dir) - args = [ - "--input-zips=$rebase_inputs", - "--output=$rebase_output", - ] - deps = [] - if (sources_list != []) { - deps = [ ":$java_generator_target_name" ] - } - } - - java_target_name = target_name + "_java" - android_library(java_target_name) { - forward_variables_from(invoker, [ "enable_bytecode_checks" ]) - deps = [ - "//mojo/public/java:bindings_java", - "//mojo/public/java:system_java", - "//third_party/androidx:androidx_annotation_annotation_java", - ] - - # Disable warnings/checks on these generated files. - chromium_code = false - - foreach(d, all_deps) { - # Resolve the name, so that a target //mojo/something becomes - # //mojo/something:something and we can append "_java" to get the java - # dependency name. - full_name = get_label_info(d, "label_no_toolchain") - deps += [ "${full_name}_java" ] - } - - srcjar_deps = [ ":$java_srcjar_target_name" ] - } - } - } - - if (defined(invoker.generate_webui_js_bindings)) { - assert(is_chromeos_ash, - "generate_webui_js_bindings can only be used on ChromeOS Ash") - assert(invoker.generate_webui_js_bindings, - "generate_webui_js_bindings should be set to true or removed") - } - - use_typescript_for_target = defined(invoker.webui_module_path) && - !defined(invoker.generate_webui_js_bindings) - - generate_legacy_js = !use_typescript_for_target || - (defined(invoker.generate_legacy_js_bindings) && - invoker.generate_legacy_js_bindings) - - if (!use_typescript_for_target && - defined(invoker.generate_legacy_js_bindings)) { - not_needed(invoker, [ "generate_legacy_js_bindings" ]) - } - - # Targets needed by both TS and JS bindings targets. These are needed - # unconditionally for JS bindings targets, and are needed for TS bindings - # targets when generate_legacy_js_bindings is true. This option is provided - # since the legacy bindings are needed by Blink tests and non-Chromium users, - # which are not expected to migrate to modules or TypeScript. - if (generate_legacy_js && (generate_js_fuzzing || - !defined(invoker.cpp_only) || !invoker.cpp_only)) { - if (sources_list != []) { - generator_js_target_name = "${target_name}_js__generator" - - action(generator_js_target_name) { - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = sources_list - deps = [ - ":$parser_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - if (defined(invoker.parser_deps)) { - deps += invoker.parser_deps - } - outputs = [] - args = common_generator_args - filelist = [] - foreach(source, sources_list) { - filelist += [ rebase_path(source, root_build_dir) ] - } - foreach(base_path, output_file_base_paths) { - outputs += [ - "$root_gen_dir/$base_path.js", - "$root_gen_dir/$base_path.m.js", - "$root_gen_dir/$base_path-lite.js", - "$root_gen_dir/$base_path-lite-for-compile.js", - ] - - if (defined(invoker.webui_module_path) && - !use_typescript_for_target) { - outputs += [ "$root_gen_dir/mojom-webui/$base_path-webui.js" ] - } - } - - response_file_contents = filelist - - args += [ - "--filelist={{response_file_name}}", - "-g", - "javascript", - ] - - if (defined(invoker.js_generate_struct_deserializers) && - invoker.js_generate_struct_deserializers) { - args += [ "--js_generate_struct_deserializers" ] - } - - if (!defined(invoker.scramble_message_ids) || - invoker.scramble_message_ids) { - inputs += message_scrambling_inputs - args += message_scrambling_args - } - - if (generate_js_fuzzing) { - args += [ "--generate_fuzzing" ] - } - } - } - - js_target_name = target_name + "_js" - group(js_target_name) { - public_deps = [] - if (sources_list != []) { - public_deps += [ ":$generator_js_target_name" ] - } - - foreach(d, all_deps) { - full_name = get_label_info(d, "label_no_toolchain") - public_deps += [ "${full_name}_js" ] - } - } - - group(js_data_deps_target_name) { - deps = [] - if (sources_list != []) { - data = [] - foreach(base_path, output_file_base_paths) { - data += [ - "$root_gen_dir/${base_path}.js", - "$root_gen_dir/${base_path}.m.js", - "$root_gen_dir/${base_path}-lite.js", - ] - } - deps += [ ":$generator_js_target_name" ] - } - - if (defined(invoker.disallow_native_types) && - invoker.disallow_native_types) { - data_deps = [] - } else { - data_deps = [ "//mojo/public/js:bindings_module" ] - } - foreach(d, all_deps) { - full_name = get_label_info(d, "label_no_toolchain") - data_deps += [ "${full_name}_js_data_deps" ] - } - } - } - - # js_library() closure compiler targets, primarily used on ChromeOS. Only - # generate these targets if the mojom target is not C++ only and is not using - # TypeScript. - if (generate_mojom_closure_libraries && - (!defined(invoker.cpp_only) || !invoker.cpp_only) && generate_legacy_js) { - js_library_for_compile_target_name = "${target_name}_js_library_for_compile" - if (sources_list != []) { - js_library(js_library_for_compile_target_name) { - extra_public_deps = [ ":$generator_js_target_name" ] - sources = [] - foreach(base_path, output_file_base_paths) { - sources += [ "$root_gen_dir/${base_path}-lite-for-compile.js" ] - } - externs_list = [ - "${externs_path}/mojo_core.js", - "${externs_path}/pending.js", - ] - deps = [] - if (!defined(invoker.disallow_native_types)) { - deps += [ "//mojo/public/js:bindings_lite_sources" ] - } - foreach(d, all_deps) { - full_name = get_label_info(d, "label_no_toolchain") - deps += [ "${full_name}_js_library_for_compile" ] - } - } - } else { - group(js_library_for_compile_target_name) { - } - } - - # WebUI specific closure targets, not needed by targets that are generating - # TypeScript WebUI bindings or by legacy-only targets. - if (defined(invoker.webui_module_path) && !use_typescript_for_target) { - webui_js_target_name = "${target_name}_webui_js" - if (sources_list != []) { - js_library(webui_js_target_name) { - extra_public_deps = [ ":$generator_js_target_name" ] - sources = [] - foreach(base_path, output_file_base_paths) { - sources += [ "$root_gen_dir/mojom-webui/${base_path}-webui.js" ] - } - externs_list = [ - "${externs_path}/mojo_core.js", - "${externs_path}/pending.js", - ] - if (defined(invoker.disallow_native_types) && - invoker.disallow_native_types) { - deps = [] - } else { - deps = [ "//mojo/public/js:bindings_uncompiled" ] - } - foreach(d, all_deps) { - full_name = get_label_info(d, "label_no_toolchain") - deps += [ "${full_name}_webui_js" ] - } - } - } else { - group(webui_js_target_name) { - } - } - - webui_grdp_target_name = "${target_name}_webui_grdp" - out_grd = "$target_gen_dir/${target_name}_webui_resources.grdp" - grd_prefix = "${target_name}_webui" - generate_grd(webui_grdp_target_name) { - grd_prefix = grd_prefix - out_grd = out_grd - - deps = [ ":$webui_js_target_name" ] - - input_files = [] - foreach(base_path, output_file_base_paths) { - input_files += [ "${base_path}-webui.js" ] - } - - input_files_base_dir = - rebase_path("$root_gen_dir/mojom-webui", "$root_build_dir") - } - } - } - if ((generate_js_fuzzing || !defined(invoker.cpp_only) || - !invoker.cpp_only) && use_typescript_for_target) { - if (sources_list != []) { - source_filelist = [] - foreach(source, sources_list) { - source_filelist += [ rebase_path(source, root_build_dir) ] - } - - # Generate Typescript bindings. - generator_ts_target_name = "${target_name}_ts__generator" - - action(generator_ts_target_name) { - script = mojom_generator_script - inputs = mojom_generator_sources + jinja2_sources - sources = sources_list - deps = [ - ":$parser_target_name", - "//mojo/public/tools/bindings:precompile_templates", - ] - - outputs = [] - foreach(base_path, output_file_base_paths) { - outputs += [ "$root_gen_dir/$base_path-webui.ts" ] - } - args = common_generator_args - response_file_contents = source_filelist - - args += [ - "--filelist={{response_file_name}}", - "-g", - "typescript", - ] - - if (!defined(invoker.scramble_message_ids) || - invoker.scramble_message_ids) { - inputs += message_scrambling_inputs - args += message_scrambling_args - } - - if (defined(invoker.js_generate_struct_deserializers) && - invoker.js_generate_struct_deserializers) { - args += [ "--js_generate_struct_deserializers" ] - } - - # TODO(crbug.com/1007587): Support scramble_message_ids if above is - # insufficient. - # TODO(crbug.com/1007591): Support generate_fuzzing. - } - } - } -} - -# A helper for the mojom() template above when component libraries are desired -# for generated C++ bindings units. Supports all the same arguments as mojom() -# except for the optional |component_output_prefix| and |component_macro_prefix| -# arguments. These are instead shortened to |output_prefix| and |macro_prefix| -# and are *required*. -template("mojom_component") { - assert(defined(invoker.output_prefix) && defined(invoker.macro_prefix)) - - mojom(target_name) { - forward_variables_from(invoker, - "*", - [ - "output_prefix", - "macro_prefix", - ]) - component_output_prefix = invoker.output_prefix - component_macro_prefix = invoker.macro_prefix - } -} diff --git a/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator.py b/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator.py deleted file mode 100755 index 8c641c2a..00000000 --- a/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator.py +++ /dev/null @@ -1,424 +0,0 @@ -#!/usr/bin/env python -# Copyright 2013 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""The frontend for the Mojo bindings system.""" - -from __future__ import print_function - -import argparse - -import hashlib -import importlib -import json -import os -import pprint -import re -import struct -import sys - -# Disable lint check for finding modules: -# pylint: disable=F0401 - -def _GetDirAbove(dirname): - """Returns the directory "above" this file containing |dirname| (which must - also be "above" this file).""" - path = os.path.abspath(__file__) - while True: - path, tail = os.path.split(path) - assert tail - if tail == dirname: - return path - - -sys.path.insert( - 0, - os.path.join( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "mojom")) - -from mojom.error import Error -import mojom.fileutil as fileutil -from mojom.generate.module import Module -from mojom.generate import template_expander -from mojom.generate import translate -from mojom.generate.generator import WriteFile - -sys.path.append( - os.path.join(_GetDirAbove("mojo"), "tools", "diagnosis")) -import crbug_1001171 - - -_BUILTIN_GENERATORS = { - "c++": "mojom_cpp_generator", - "javascript": "mojom_js_generator", - "java": "mojom_java_generator", - "mojolpm": "mojom_mojolpm_generator", - "typescript": "mojom_ts_generator", -} - -_BUILTIN_CHECKS = { - "attributes": "mojom_attributes_check", - "definitions": "mojom_definitions_check", - "features": "mojom_interface_feature_check", - "restrictions": "mojom_restrictions_check", -} - - -def LoadGenerators(generators_string): - if not generators_string: - return {} # No generators. - - generators = {} - for generator_name in [s.strip() for s in generators_string.split(",")]: - language = generator_name.lower() - if language not in _BUILTIN_GENERATORS: - print("Unknown generator name %s" % generator_name) - sys.exit(1) - generator_module = importlib.import_module( - "generators.%s" % _BUILTIN_GENERATORS[language]) - generators[language] = generator_module - return generators - - -def LoadChecks(checks_string): - if not checks_string: - return {} # No checks. - - checks = {} - for check_name in [s.strip() for s in checks_string.split(",")]: - check = check_name.lower() - if check not in _BUILTIN_CHECKS: - print("Unknown check name %s" % check_name) - sys.exit(1) - check_module = importlib.import_module("checks.%s" % _BUILTIN_CHECKS[check]) - checks[check] = check_module - return checks - - -def MakeImportStackMessage(imported_filename_stack): - """Make a (human-readable) message listing a chain of imports. (Returned - string begins with a newline (if nonempty) and does not end with one.)""" - return ''.join( - reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ - zip(imported_filename_stack[1:], imported_filename_stack)])) - - -class RelativePath: - """Represents a path relative to the source tree or generated output dir.""" - - def __init__(self, path, source_root, output_dir): - self.path = path - if path.startswith(source_root): - self.root = source_root - elif path.startswith(output_dir): - self.root = output_dir - else: - raise Exception("Invalid input path %s" % path) - - def relative_path(self): - return os.path.relpath( - os.path.abspath(self.path), os.path.abspath(self.root)) - - -def _GetModulePath(path, output_dir): - return os.path.join(output_dir, path.relative_path() + '-module') - - -def ScrambleMethodOrdinals(interfaces, salt): - already_generated = set() - for interface in interfaces: - i = 0 - already_generated.clear() - for method in interface.methods: - if method.explicit_ordinal is not None: - continue - while True: - i = i + 1 - if i == 1000000: - raise Exception("Could not generate %d method ordinals for %s" % - (len(interface.methods), interface.mojom_name)) - # Generate a scrambled method.ordinal value. The algorithm doesn't have - # to be very strong, cryptographically. It just needs to be non-trivial - # to guess the results without the secret salt, in order to make it - # harder for a compromised process to send fake Mojo messages. - sha256 = hashlib.sha256(salt) - sha256.update(interface.mojom_name.encode('utf-8')) - sha256.update(str(i).encode('utf-8')) - # Take the first 4 bytes as a little-endian uint32. - ordinal = struct.unpack('<L', sha256.digest()[:4])[0] - # Trim to 31 bits, so it always fits into a Java (signed) int. - ordinal = ordinal & 0x7fffffff - if ordinal in already_generated: - continue - already_generated.add(ordinal) - method.ordinal = ordinal - method.ordinal_comment = ( - 'The %s value is based on sha256(salt + "%s%d").' % - (ordinal, interface.mojom_name, i)) - break - - -def ReadFileContents(filename): - with open(filename, 'rb') as f: - return f.read() - - -class MojomProcessor: - """Takes parsed mojom modules and generates language bindings from them. - - Attributes: - _processed_files: {Dict[str, mojom.generate.module.Module]} Mapping from - relative mojom filename paths to the module AST for that mojom file. - """ - def __init__(self, should_generate): - self._should_generate = should_generate - self._processed_files = {} - self._typemap = {} - - def LoadTypemaps(self, typemaps): - # Support some very simple single-line comments in typemap JSON. - comment_expr = r"^\s*//.*$" - def no_comments(line): - return not re.match(comment_expr, line) - for filename in typemaps: - with open(filename) as f: - typemaps = json.loads("".join(filter(no_comments, f.readlines()))) - for language, typemap in typemaps.items(): - language_map = self._typemap.get(language, {}) - language_map.update(typemap) - self._typemap[language] = language_map - if 'c++' in self._typemap: - self._typemap['mojolpm'] = self._typemap['c++'] - - def _GenerateModule(self, args, remaining_args, check_modules, - generator_modules, rel_filename, imported_filename_stack): - # Return the already-generated module. - if rel_filename.path in self._processed_files: - return self._processed_files[rel_filename.path] - - if rel_filename.path in imported_filename_stack: - print("%s: Error: Circular dependency" % rel_filename.path + \ - MakeImportStackMessage(imported_filename_stack + [rel_filename.path])) - sys.exit(1) - - module_path = _GetModulePath(rel_filename, args.output_dir) - with open(module_path, 'rb') as f: - module = Module.Load(f) - - if args.scrambled_message_id_salt_paths: - salt = b''.join( - map(ReadFileContents, args.scrambled_message_id_salt_paths)) - ScrambleMethodOrdinals(module.interfaces, salt) - - if self._should_generate(rel_filename.path): - # Run checks on module first. - for check_module in check_modules.values(): - checker = check_module.Check(module) - checker.CheckModule() - # Then run generation. - for language, generator_module in generator_modules.items(): - generator = generator_module.Generator( - module, args.output_dir, typemap=self._typemap.get(language, {}), - variant=args.variant, bytecode_path=args.bytecode_path, - for_blink=args.for_blink, - js_generate_struct_deserializers=\ - args.js_generate_struct_deserializers, - export_attribute=args.export_attribute, - export_header=args.export_header, - generate_non_variant_code=args.generate_non_variant_code, - support_lazy_serialization=args.support_lazy_serialization, - disallow_native_types=args.disallow_native_types, - disallow_interfaces=args.disallow_interfaces, - generate_message_ids=args.generate_message_ids, - generate_fuzzing=args.generate_fuzzing, - enable_kythe_annotations=args.enable_kythe_annotations, - extra_cpp_template_paths=args.extra_cpp_template_paths, - generate_extra_cpp_only=args.generate_extra_cpp_only) - filtered_args = [] - if hasattr(generator_module, 'GENERATOR_PREFIX'): - prefix = '--' + generator_module.GENERATOR_PREFIX + '_' - filtered_args = [arg for arg in remaining_args - if arg.startswith(prefix)] - generator.GenerateFiles(filtered_args) - - # Save result. - self._processed_files[rel_filename.path] = module - return module - - -def _Generate(args, remaining_args): - if args.variant == "none": - args.variant = None - - for idx, import_dir in enumerate(args.import_directories): - tokens = import_dir.split(":") - if len(tokens) >= 2: - args.import_directories[idx] = RelativePath(tokens[0], tokens[1], - args.output_dir) - else: - args.import_directories[idx] = RelativePath(tokens[0], args.depth, - args.output_dir) - generator_modules = LoadGenerators(args.generators_string) - check_modules = LoadChecks(args.checks_string) - - fileutil.EnsureDirectoryExists(args.output_dir) - - processor = MojomProcessor(lambda filename: filename in args.filename) - processor.LoadTypemaps(set(args.typemaps)) - - if args.filelist: - with open(args.filelist) as f: - args.filename.extend(f.read().split()) - - for filename in args.filename: - processor._GenerateModule( - args, remaining_args, check_modules, generator_modules, - RelativePath(filename, args.depth, args.output_dir), []) - - return 0 - - -def _Precompile(args, _): - generator_modules = LoadGenerators(",".join(_BUILTIN_GENERATORS.keys())) - - template_expander.PrecompileTemplates(generator_modules, args.output_dir) - return 0 - - -def main(): - parser = argparse.ArgumentParser( - description="Generate bindings from mojom files.") - parser.add_argument("--use_bundled_pylibs", action="store_true", - help="use Python modules bundled in the SDK") - parser.add_argument( - "-o", - "--output_dir", - dest="output_dir", - default=".", - help="output directory for generated files") - - subparsers = parser.add_subparsers() - - generate_parser = subparsers.add_parser( - "generate", description="Generate bindings from mojom files.") - generate_parser.add_argument("filename", nargs="*", - help="mojom input file") - generate_parser.add_argument("--filelist", help="mojom input file list") - generate_parser.add_argument("-d", "--depth", dest="depth", default=".", - help="depth from source root") - generate_parser.add_argument("-g", - "--generators", - dest="generators_string", - metavar="GENERATORS", - default="c++,javascript,java,mojolpm", - help="comma-separated list of generators") - generate_parser.add_argument("-c", - "--checks", - dest="checks_string", - metavar="CHECKS", - default=",".join(_BUILTIN_CHECKS.keys()), - help="comma-separated list of checks") - generate_parser.add_argument( - "--gen_dir", dest="gen_directories", action="append", metavar="directory", - default=[], help="add a directory to be searched for the syntax trees.") - generate_parser.add_argument( - "-I", dest="import_directories", action="append", metavar="directory", - default=[], - help="add a directory to be searched for import files. The depth from " - "source root can be specified for each import by appending it after " - "a colon") - generate_parser.add_argument("--typemap", action="append", metavar="TYPEMAP", - default=[], dest="typemaps", - help="apply TYPEMAP to generated output") - generate_parser.add_argument("--variant", dest="variant", default=None, - help="output a named variant of the bindings") - generate_parser.add_argument( - "--bytecode_path", required=True, help=( - "the path from which to load template bytecode; to generate template " - "bytecode, run %s precompile BYTECODE_PATH" % os.path.basename( - sys.argv[0]))) - generate_parser.add_argument("--for_blink", action="store_true", - help="Use WTF types as generated types for mojo " - "string/array/map.") - generate_parser.add_argument( - "--js_generate_struct_deserializers", action="store_true", - help="Generate javascript deserialize methods for structs in " - "mojom-lite.js file") - generate_parser.add_argument( - "--export_attribute", default="", - help="Optional attribute to specify on class declaration to export it " - "for the component build.") - generate_parser.add_argument( - "--export_header", default="", - help="Optional header to include in the generated headers to support the " - "component build.") - generate_parser.add_argument( - "--generate_non_variant_code", action="store_true", - help="Generate code that is shared by different variants.") - generate_parser.add_argument( - "--scrambled_message_id_salt_path", - dest="scrambled_message_id_salt_paths", - help="If non-empty, the path to a file whose contents should be used as" - "a salt for generating scrambled message IDs. If this switch is specified" - "more than once, the contents of all salt files are concatenated to form" - "the salt value.", default=[], action="append") - generate_parser.add_argument( - "--support_lazy_serialization", - help="If set, generated bindings will serialize lazily when possible.", - action="store_true") - generate_parser.add_argument( - "--extra_cpp_template_paths", - dest="extra_cpp_template_paths", - action="append", - metavar="path_to_template", - default=[], - help="Provide a path to a new template (.tmpl) that is used to generate " - "additional C++ source/header files ") - generate_parser.add_argument( - "--generate_extra_cpp_only", - help="If set and extra_cpp_template_paths provided, will only generate" - "extra_cpp_template related C++ bindings", - action="store_true") - generate_parser.add_argument( - "--disallow_native_types", - help="Disallows the [Native] attribute to be specified on structs or " - "enums within the mojom file.", action="store_true") - generate_parser.add_argument( - "--disallow_interfaces", - help="Disallows interface definitions within the mojom file. It is an " - "error to specify this flag when processing a mojom file which defines " - "any interface.", action="store_true") - generate_parser.add_argument( - "--generate_message_ids", - help="Generates only the message IDs header for C++ bindings. Note that " - "this flag only matters if --generate_non_variant_code is also " - "specified.", action="store_true") - generate_parser.add_argument( - "--generate_fuzzing", - action="store_true", - help="Generates additional bindings for fuzzing in JS.") - generate_parser.add_argument( - "--enable_kythe_annotations", - action="store_true", - help="Adds annotations for kythe metadata generation.") - - generate_parser.set_defaults(func=_Generate) - - precompile_parser = subparsers.add_parser("precompile", - description="Precompile templates for the mojom bindings generator.") - precompile_parser.set_defaults(func=_Precompile) - - args, remaining_args = parser.parse_known_args() - return args.func(args, remaining_args) - - -if __name__ == "__main__": - with crbug_1001171.DumpStateOnLookupError(): - ret = main() - # Exit without running GC, which can save multiple seconds due to the large - # number of object created. But flush is necessary as os._exit doesn't do - # that. - sys.stdout.flush() - sys.stderr.flush() - os._exit(ret) diff --git a/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py b/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py deleted file mode 100644 index 761922b6..00000000 --- a/utils/ipc/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2014 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import unittest - -from mojom_bindings_generator import MakeImportStackMessage -from mojom_bindings_generator import ScrambleMethodOrdinals - - -class FakeIface: - def __init__(self): - self.mojom_name = None - self.methods = None - - -class FakeMethod: - def __init__(self, explicit_ordinal=None): - self.explicit_ordinal = explicit_ordinal - self.ordinal = explicit_ordinal - self.ordinal_comment = None - - -class MojoBindingsGeneratorTest(unittest.TestCase): - """Tests mojo_bindings_generator.""" - - def testMakeImportStackMessage(self): - """Tests MakeImportStackMessage().""" - self.assertEqual(MakeImportStackMessage(["x"]), "") - self.assertEqual(MakeImportStackMessage(["x", "y"]), - "\n y was imported by x") - self.assertEqual(MakeImportStackMessage(["x", "y", "z"]), - "\n z was imported by y\n y was imported by x") - - def testScrambleMethodOrdinals(self): - """Tests ScrambleMethodOrdinals().""" - interface = FakeIface() - interface.mojom_name = 'RendererConfiguration' - interface.methods = [ - FakeMethod(), - FakeMethod(), - FakeMethod(), - FakeMethod(explicit_ordinal=42) - ] - ScrambleMethodOrdinals([interface], "foo".encode('utf-8')) - # These next three values are hard-coded. If the generation algorithm - # changes from being based on sha256(seed + interface.name + str(i)) then - # these numbers will obviously need to change too. - # - # Note that hashlib.sha256('fooRendererConfiguration1').digest()[:4] is - # '\xa5\xbc\xf9\xca' and that hex(1257880741) = '0x4af9bca5'. The - # difference in 0x4a vs 0xca is because we only take 31 bits. - self.assertEqual(interface.methods[0].ordinal, 1257880741) - self.assertEqual(interface.methods[1].ordinal, 631133653) - self.assertEqual(interface.methods[2].ordinal, 549336076) - - # Explicit method ordinals should not be scrambled. - self.assertEqual(interface.methods[3].ordinal, 42) - - -if __name__ == "__main__": - unittest.main() diff --git a/utils/ipc/mojo/public/tools/bindings/validate_typemap_config.py b/utils/ipc/mojo/public/tools/bindings/validate_typemap_config.py deleted file mode 100755 index 6bb7a209..00000000 --- a/utils/ipc/mojo/public/tools/bindings/validate_typemap_config.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# Copyright 2020 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import json -import os -import re -import sys - - -def CheckCppTypemapConfigs(target_name, config_filename, out_filename): - _SUPPORTED_CONFIG_KEYS = set([ - 'types', 'traits_headers', 'traits_private_headers', 'traits_sources', - 'traits_deps', 'traits_public_deps' - ]) - _SUPPORTED_TYPE_KEYS = set([ - 'mojom', 'cpp', 'copyable_pass_by_value', 'force_serialize', 'hashable', - 'move_only', 'nullable_is_same_type', 'forward_declaration', - 'default_constructible' - ]) - with open(config_filename, 'r') as f: - for config in json.load(f): - for key in config.keys(): - if key not in _SUPPORTED_CONFIG_KEYS: - raise ValueError('Invalid typemap property "%s" when processing %s' % - (key, target_name)) - - types = config.get('types') - if not types: - raise ValueError('Typemap for %s must specify at least one type to map' - % target_name) - - for entry in types: - for key in entry.keys(): - if key not in _SUPPORTED_TYPE_KEYS: - raise IOError( - 'Invalid type property "%s" in typemap for "%s" on target %s' % - (key, entry.get('mojom', '(unknown)'), target_name)) - - with open(out_filename, 'w') as f: - f.truncate(0) - - -def main(): - parser = argparse.ArgumentParser() - _, args = parser.parse_known_args() - if len(args) != 3: - print('Usage: validate_typemap_config.py target_name config_filename ' - 'stamp_filename') - sys.exit(1) - - CheckCppTypemapConfigs(args[0], args[1], args[2]) - - -if __name__ == '__main__': - main() |