| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """The frontend for the Mojo bindings system.""" | 6 """The frontend for the Mojo bindings system.""" |
| 7 | 7 |
| 8 | 8 |
| 9 import argparse | 9 import argparse |
| 10 import hashlib |
| 10 import imp | 11 import imp |
| 11 import json | 12 import json |
| 12 import os | 13 import os |
| 13 import pprint | 14 import pprint |
| 14 import re | 15 import re |
| 16 import struct |
| 15 import sys | 17 import sys |
| 16 | 18 |
| 17 # Disable lint check for finding modules: | 19 # Disable lint check for finding modules: |
| 18 # pylint: disable=F0401 | 20 # pylint: disable=F0401 |
| 19 | 21 |
| 20 def _GetDirAbove(dirname): | 22 def _GetDirAbove(dirname): |
| 21 """Returns the directory "above" this file containing |dirname| (which must | 23 """Returns the directory "above" this file containing |dirname| (which must |
| 22 also be "above" this file).""" | 24 also be "above" this file).""" |
| 23 path = os.path.abspath(__file__) | 25 path = os.path.abspath(__file__) |
| 24 while True: | 26 while True: |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 RelativePath with first file found, or an arbitrary non-existent file | 95 RelativePath with first file found, or an arbitrary non-existent file |
| 94 otherwise.""" | 96 otherwise.""" |
| 95 for rel_search_dir in [rel_dir] + search_rel_dirs: | 97 for rel_search_dir in [rel_dir] + search_rel_dirs: |
| 96 path = os.path.join(rel_search_dir.path, file_name) | 98 path = os.path.join(rel_search_dir.path, file_name) |
| 97 if os.path.isfile(path): | 99 if os.path.isfile(path): |
| 98 return RelativePath(path, rel_search_dir.source_root) | 100 return RelativePath(path, rel_search_dir.source_root) |
| 99 return RelativePath(os.path.join(rel_dir.path, file_name), | 101 return RelativePath(os.path.join(rel_dir.path, file_name), |
| 100 rel_dir.source_root) | 102 rel_dir.source_root) |
| 101 | 103 |
| 102 | 104 |
| 105 def ScrambleMethodOrdinals(interfaces, salt): |
| 106 already_generated = set() |
| 107 for interface in interfaces: |
| 108 i = 0 |
| 109 already_generated.clear() |
| 110 for method in interface.methods: |
| 111 while True: |
| 112 i = i + 1 |
| 113 if i == 1000000: |
| 114 raise Exception("Could not generate %d method ordinals for %s" % |
| 115 (len(interface.methods), interface.name)) |
| 116 # Generate a scrambled method.ordinal value. The algorithm doesn't have |
| 117 # to be very strong, cryptographically. It just needs to be non-trivial |
| 118 # to guess the results without the secret salt, in order to make it |
| 119 # harder for a compromised process to send fake Mojo messages. |
| 120 sha256 = hashlib.sha256(salt) |
| 121 sha256.update(interface.name) |
| 122 sha256.update(str(i)) |
| 123 # Take the first 4 bytes as a little-endian uint32. |
| 124 ordinal = struct.unpack('<L', sha256.digest()[:4])[0] |
| 125 # Trim to 31 bits, so it always fits into a Java (signed) int. |
| 126 ordinal = ordinal & 0x7fffffff |
| 127 if ordinal in already_generated: |
| 128 continue |
| 129 already_generated.add(ordinal) |
| 130 method.ordinal = ordinal |
| 131 method.ordinal_comment = ( |
| 132 'The %s value is based on sha256(salt + "%s%d").' % |
| 133 (ordinal, interface.name, i)) |
| 134 break |
| 135 |
| 136 |
| 103 class MojomProcessor(object): | 137 class MojomProcessor(object): |
| 104 """Parses mojom files and creates ASTs for them. | 138 """Parses mojom files and creates ASTs for them. |
| 105 | 139 |
| 106 Attributes: | 140 Attributes: |
| 107 _processed_files: {Dict[str, mojom.generate.module.Module]} Mapping from | 141 _processed_files: {Dict[str, mojom.generate.module.Module]} Mapping from |
| 108 relative mojom filename paths to the module AST for that mojom file. | 142 relative mojom filename paths to the module AST for that mojom file. |
| 109 """ | 143 """ |
| 110 def __init__(self, should_generate): | 144 def __init__(self, should_generate): |
| 111 self._should_generate = should_generate | 145 self._should_generate = should_generate |
| 112 self._processed_files = {} | 146 self._processed_files = {} |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 imports = {} | 181 imports = {} |
| 148 for parsed_imp in tree.import_list: | 182 for parsed_imp in tree.import_list: |
| 149 rel_import_file = FindImportFile( | 183 rel_import_file = FindImportFile( |
| 150 RelativePath(dirname, rel_filename.source_root), | 184 RelativePath(dirname, rel_filename.source_root), |
| 151 parsed_imp.import_filename, args.import_directories) | 185 parsed_imp.import_filename, args.import_directories) |
| 152 imports[parsed_imp.import_filename] = self._GenerateModule( | 186 imports[parsed_imp.import_filename] = self._GenerateModule( |
| 153 args, remaining_args, generator_modules, rel_import_file) | 187 args, remaining_args, generator_modules, rel_import_file) |
| 154 | 188 |
| 155 module = translate.OrderedModule(tree, name, imports) | 189 module = translate.OrderedModule(tree, name, imports) |
| 156 | 190 |
| 191 if args.scrambled_message_id_salt: |
| 192 ScrambleMethodOrdinals(module.interfaces, args.scrambled_message_id_salt) |
| 193 |
| 157 # Set the path as relative to the source root. | 194 # Set the path as relative to the source root. |
| 158 module.path = rel_filename.relative_path() | 195 module.path = rel_filename.relative_path() |
| 159 | 196 |
| 160 # Normalize to unix-style path here to keep the generators simpler. | 197 # Normalize to unix-style path here to keep the generators simpler. |
| 161 module.path = module.path.replace('\\', '/') | 198 module.path = module.path.replace('\\', '/') |
| 162 | 199 |
| 163 if self._should_generate(rel_filename.path): | 200 if self._should_generate(rel_filename.path): |
| 164 for language, generator_module in generator_modules.iteritems(): | 201 for language, generator_module in generator_modules.iteritems(): |
| 165 generator = generator_module.Generator( | 202 generator = generator_module.Generator( |
| 166 module, args.output_dir, typemap=self._typemap.get(language, {}), | 203 module, args.output_dir, typemap=self._typemap.get(language, {}), |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 "component build.") | 349 "component build.") |
| 313 generate_parser.add_argument( | 350 generate_parser.add_argument( |
| 314 "--generate_non_variant_code", action="store_true", | 351 "--generate_non_variant_code", action="store_true", |
| 315 help="Generate code that is shared by different variants.") | 352 help="Generate code that is shared by different variants.") |
| 316 generate_parser.add_argument( | 353 generate_parser.add_argument( |
| 317 "--depfile", type=str, | 354 "--depfile", type=str, |
| 318 help="A file into which the list of input files will be written.") | 355 help="A file into which the list of input files will be written.") |
| 319 generate_parser.add_argument( | 356 generate_parser.add_argument( |
| 320 "--depfile_target", type=str, | 357 "--depfile_target", type=str, |
| 321 help="The target name to use in the depfile.") | 358 help="The target name to use in the depfile.") |
| 359 generate_parser.add_argument( |
| 360 "--scrambled_message_id_salt", |
| 361 help="If non-empty, the salt for generating scrambled message IDs.") |
| 322 generate_parser.set_defaults(func=_Generate) | 362 generate_parser.set_defaults(func=_Generate) |
| 323 | 363 |
| 324 precompile_parser = subparsers.add_parser("precompile", | 364 precompile_parser = subparsers.add_parser("precompile", |
| 325 description="Precompile templates for the mojom bindings generator.") | 365 description="Precompile templates for the mojom bindings generator.") |
| 326 precompile_parser.add_argument( | 366 precompile_parser.add_argument( |
| 327 "-o", "--output_dir", dest="output_dir", default=".", | 367 "-o", "--output_dir", dest="output_dir", default=".", |
| 328 help="output directory for precompiled templates") | 368 help="output directory for precompiled templates") |
| 329 precompile_parser.set_defaults(func=_Precompile) | 369 precompile_parser.set_defaults(func=_Precompile) |
| 330 | 370 |
| 331 args, remaining_args = parser.parse_known_args() | 371 args, remaining_args = parser.parse_known_args() |
| 332 return args.func(args, remaining_args) | 372 return args.func(args, remaining_args) |
| 333 | 373 |
| 334 | 374 |
| 335 if __name__ == "__main__": | 375 if __name__ == "__main__": |
| 336 sys.exit(main()) | 376 sys.exit(main()) |
| OLD | NEW |