| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import argparse | 5 import argparse |
| 6 import copy | 6 import copy |
| 7 from datetime import datetime | 7 from datetime import datetime |
| 8 import os | 8 import os |
| 9 | 9 |
| 10 from code import Code | 10 from code import Code |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 // Use of this source code is governed by a BSD-style license that can be | 47 // Use of this source code is governed by a BSD-style license that can be |
| 48 // found in the LICENSE file. | 48 // found in the LICENSE file. |
| 49 | 49 |
| 50 // GENERATED FROM THE FEATURES FILE: | 50 // GENERATED FROM THE FEATURES FILE: |
| 51 // %(source_files)s | 51 // %(source_files)s |
| 52 // DO NOT EDIT. | 52 // DO NOT EDIT. |
| 53 | 53 |
| 54 #include "%(header_file_path)s" | 54 #include "%(header_file_path)s" |
| 55 | 55 |
| 56 #include "extensions/common/features/api_feature.h" | 56 #include "extensions/common/features/api_feature.h" |
| 57 #include "extensions/common/features/behavior_feature.h" |
| 57 #include "extensions/common/features/complex_feature.h" | 58 #include "extensions/common/features/complex_feature.h" |
| 59 #include "extensions/common/features/manifest_feature.h" |
| 60 #include "extensions/common/features/permission_feature.h" |
| 58 | 61 |
| 59 namespace extensions { | 62 namespace extensions { |
| 60 | 63 |
| 61 """ | 64 """ |
| 62 | 65 |
| 63 # The end of the .cc file for the generated FeatureProvider. | 66 # The end of the .cc file for the generated FeatureProvider. |
| 64 CC_FILE_END = """ | 67 CC_FILE_END = """ |
| 65 %(provider_class)s::~%(provider_class)s() {} | 68 %(provider_class)s::~%(provider_class)s() {} |
| 66 | 69 |
| 67 } // namespace extensions | 70 } // namespace extensions |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 } | 188 } |
| 186 } | 189 } |
| 187 }, | 190 }, |
| 188 'whitelist': { | 191 'whitelist': { |
| 189 list: {'subtype': unicode} | 192 list: {'subtype': unicode} |
| 190 }, | 193 }, |
| 191 }) | 194 }) |
| 192 | 195 |
| 193 # These keys are used to find the parents of different features, but are not | 196 # These keys are used to find the parents of different features, but are not |
| 194 # compiled into the features themselves. | 197 # compiled into the features themselves. |
| 195 IGNORED_KEYS = ['noparent', 'default_parent'] | 198 IGNORED_KEYS = ['default_parent'] |
| 196 | 199 |
| 197 # By default, if an error is encountered, assert to stop the compilation. This | 200 # By default, if an error is encountered, assert to stop the compilation. This |
| 198 # can be disabled for testing. | 201 # can be disabled for testing. |
| 199 ENABLE_ASSERTIONS = True | 202 ENABLE_ASSERTIONS = True |
| 200 | 203 |
| 201 # JSON parsing returns all strings of characters as unicode types. For testing, | 204 # JSON parsing returns all strings of characters as unicode types. For testing, |
| 202 # we can enable converting all string types to unicode to avoid writing u'' | 205 # we can enable converting all string types to unicode to avoid writing u'' |
| 203 # everywhere. | 206 # everywhere. |
| 204 STRINGS_TO_UNICODE = False | 207 STRINGS_TO_UNICODE = False |
| 205 | 208 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 if cpp_sub_value: | 326 if cpp_sub_value: |
| 324 cpp_value.append(cpp_sub_value) | 327 cpp_value.append(cpp_sub_value) |
| 325 if cpp_value: | 328 if cpp_value: |
| 326 cpp_value = '{' + ','.join(cpp_value) + '}' | 329 cpp_value = '{' + ','.join(cpp_value) + '}' |
| 327 else: | 330 else: |
| 328 cpp_value = self._GetCheckedValue(key, expected_type, expected_values, | 331 cpp_value = self._GetCheckedValue(key, expected_type, expected_values, |
| 329 enum_map, v) | 332 enum_map, v) |
| 330 | 333 |
| 331 if cpp_value: | 334 if cpp_value: |
| 332 self.feature_values[key] = cpp_value | 335 self.feature_values[key] = cpp_value |
| 336 elif key in self.feature_values: |
| 337 # If the key is empty and this feature inherited a value from its parent, |
| 338 # remove the inherited value. |
| 339 del self.feature_values[key] |
| 333 | 340 |
| 334 def SetParent(self, parent): | 341 def SetParent(self, parent): |
| 335 """Sets the parent of this feature, and inherits all properties from that | 342 """Sets the parent of this feature, and inherits all properties from that |
| 336 parent. | 343 parent. |
| 337 """ | 344 """ |
| 338 assert not self.feature_values, 'Parents must be set before parsing' | 345 assert not self.feature_values, 'Parents must be set before parsing' |
| 339 self.feature_values = copy.deepcopy(parent.feature_values) | 346 self.feature_values = copy.deepcopy(parent.feature_values) |
| 340 self.has_parent = True | 347 self.has_parent = True |
| 341 | 348 |
| 342 def Parse(self, parsed_json): | 349 def Parse(self, parsed_json): |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 print('FAILED: Exception encountered while loading "%s"' % | 396 print('FAILED: Exception encountered while loading "%s"' % |
| 390 abs_source_file) | 397 abs_source_file) |
| 391 raise | 398 raise |
| 392 dupes = set(f_json) & set(self._json) | 399 dupes = set(f_json) & set(self._json) |
| 393 assert not dupes, 'Duplicate keys found: %s' % list(dupes) | 400 assert not dupes, 'Duplicate keys found: %s' % list(dupes) |
| 394 self._json.update(f_json) | 401 self._json.update(f_json) |
| 395 | 402 |
| 396 def _FindParent(self, feature_name, feature_value): | 403 def _FindParent(self, feature_name, feature_value): |
| 397 """Checks to see if a feature has a parent. If it does, returns the | 404 """Checks to see if a feature has a parent. If it does, returns the |
| 398 parent.""" | 405 parent.""" |
| 406 no_parent = False |
| 407 if type(feature_value) is list: |
| 408 no_parent_values = ['noparent' in v for v in feature_value] |
| 409 no_parent = all(no_parent_values) |
| 410 assert no_parent or not any(no_parent_values), ( |
| 411 '"%s:" All child features must contain the same noparent value' % |
| 412 feature_name) |
| 413 else: |
| 414 no_parent = 'noparent' in feature_value |
| 399 sep = feature_name.rfind('.') | 415 sep = feature_name.rfind('.') |
| 400 if sep is -1 or 'noparent' in feature_value: | 416 if sep is -1 or no_parent: |
| 401 return None | 417 return None |
| 402 parent_name = feature_name[:sep] | 418 parent_name = feature_name[:sep] |
| 403 if parent_name not in self._features: | 419 if parent_name not in self._features: |
| 404 # TODO(devlin): It'd be kind of nice to be able to assert that the | 420 # TODO(devlin): It'd be kind of nice to be able to assert that the |
| 405 # deduced parent name is in our features, but some dotted features don't | 421 # deduced parent name is in our features, but some dotted features don't |
| 406 # have parents and also don't have noparent, e.g. system.cpu. We should | 422 # have parents and also don't have noparent, e.g. system.cpu. We should |
| 407 # probably just noparent them so that we can assert this. | 423 # probably just noparent them so that we can assert this. |
| 408 # raise KeyError('Could not find parent "%s" for feature "%s".' % | 424 # raise KeyError('Could not find parent "%s" for feature "%s".' % |
| 409 # (parent_name, feature_name)) | 425 # (parent_name, feature_name)) |
| 410 return None | 426 return None |
| (...skipping 13 matching lines...) Expand all Loading... |
| 424 assert feature_value['nocompile'], ( | 440 assert feature_value['nocompile'], ( |
| 425 'nocompile should only be true; otherwise omit this key.') | 441 'nocompile should only be true; otherwise omit this key.') |
| 426 return | 442 return |
| 427 parent = self._FindParent(feature_name, feature_value) | 443 parent = self._FindParent(feature_name, feature_value) |
| 428 # Handle complex features, which are lists of simple features. | 444 # Handle complex features, which are lists of simple features. |
| 429 if type(feature_value) is list: | 445 if type(feature_value) is list: |
| 430 feature_list = [] | 446 feature_list = [] |
| 431 # This doesn't handle nested complex features. I think that's probably for | 447 # This doesn't handle nested complex features. I think that's probably for |
| 432 # the best. | 448 # the best. |
| 433 for v in feature_value: | 449 for v in feature_value: |
| 434 feature = Feature(feature_name) | 450 try: |
| 435 if parent: | 451 feature = Feature(feature_name) |
| 436 feature.SetParent(parent) | 452 if parent: |
| 437 feature.Parse(v) | 453 feature.SetParent(parent) |
| 438 feature_list.append(feature) | 454 feature.Parse(v) |
| 455 feature_list.append(feature) |
| 456 except: |
| 457 print('Failure to parse feature "%s"' % feature_name) |
| 458 raise |
| 439 self._features[feature_name] = feature_list | 459 self._features[feature_name] = feature_list |
| 440 return | 460 return |
| 441 | 461 |
| 442 feature = Feature(feature_name) | 462 try: |
| 443 if parent: | 463 feature = Feature(feature_name) |
| 444 feature.SetParent(parent) | 464 if parent: |
| 445 feature.Parse(feature_value) | 465 feature.SetParent(parent) |
| 446 self._features[feature_name] = feature | 466 feature.Parse(feature_value) |
| 467 self._features[feature_name] = feature |
| 468 except: |
| 469 print('Failure to parse feature "%s"' % feature_name) |
| 470 raise |
| 447 | 471 |
| 448 def Compile(self): | 472 def Compile(self): |
| 449 """Parses all features after loading the input files.""" | 473 """Parses all features after loading the input files.""" |
| 450 self._Load(); | 474 self._Load(); |
| 451 # Iterate over in sorted order so that parents come first. | 475 # Iterate over in sorted order so that parents come first. |
| 452 for k in sorted(self._json.keys()): | 476 for k in sorted(self._json.keys()): |
| 453 self._CompileFeature(k, self._json[k]) | 477 self._CompileFeature(k, self._json[k]) |
| 454 | 478 |
| 455 def Render(self): | 479 def Render(self): |
| 456 """Returns the Code object for the body of the .cc file, which handles the | 480 """Returns the Code object for the body of the .cc file, which handles the |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 'out_base_filename', type=str, | 551 'out_base_filename', type=str, |
| 528 help='The base filename for the C++ files (.h and .cc will be appended)') | 552 help='The base filename for the C++ files (.h and .cc will be appended)') |
| 529 parser.add_argument('source_files', type=str, nargs='+', | 553 parser.add_argument('source_files', type=str, nargs='+', |
| 530 help='The source features.json files') | 554 help='The source features.json files') |
| 531 args = parser.parse_args() | 555 args = parser.parse_args() |
| 532 c = FeatureCompiler(args.chrome_root, args.source_files, args.feature_class, | 556 c = FeatureCompiler(args.chrome_root, args.source_files, args.feature_class, |
| 533 args.provider_class, args.out_root, | 557 args.provider_class, args.out_root, |
| 534 args.out_base_filename) | 558 args.out_base_filename) |
| 535 c.Compile() | 559 c.Compile() |
| 536 c.Write() | 560 c.Write() |
| OLD | NEW |