summaryrefslogtreecommitdiff
path: root/utils/ipc/mojo/public/tools/bindings/checks
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2024-08-08 18:13:00 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2024-08-15 23:59:08 +0300
commit50c92cc7e2924009ecab3e4004448b01d687707c (patch)
treec22b49816a3c79dae4727780962aa0928df42b52 /utils/ipc/mojo/public/tools/bindings/checks
parentd3bf27180ef1d91b86b7b87a2378e559eaff5455 (diff)
meson: Move all code generation scripts to utils/codegen/
We have multiple code generation scripts in utils/, mixed with other miscellaneous utilities, as well as a larger code base based on mojom in utils/ipc/. To make code sharing easier between the generator scripts, without creating a mess in the utils/ directory, move all the code generation code to utils/codegen/. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Diffstat (limited to 'utils/ipc/mojo/public/tools/bindings/checks')
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/__init__.py0
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check.py170
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py194
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_definitions_check.py34
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check.py62
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_interface_feature_check_unittest.py173
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_check.py102
-rw-r--r--utils/ipc/mojo/public/tools/bindings/checks/mojom_restrictions_checks_unittest.py254
8 files changed, 0 insertions, 989 deletions
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)