Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: base/android/jni_generator/jni_generator.py

Issue 2501193003: Selectively perform JNI registration in render processes on Android. (Closed)
Patch Set: Address Ted C comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 """Extracts native methods from a Java file and generates the JNI bindings. 6 """Extracts native methods from a Java file and generates the JNI bindings.
7 If you change this, please run and update the tests.""" 7 If you change this, please run and update the tests."""
8 8
9 import collections 9 import collections
10 import errno 10 import errno
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 java_class_name=match.group('java_class_name'), 405 java_class_name=match.group('java_class_name'),
406 native_class_name=match.group('native_class_name'), 406 native_class_name=match.group('native_class_name'),
407 return_type=match.group('return_type'), 407 return_type=match.group('return_type'),
408 name=match.group('name').replace('native', ''), 408 name=match.group('name').replace('native', ''),
409 params=JniParams.Parse(match.group('params')), 409 params=JniParams.Parse(match.group('params')),
410 ptr_type=ptr_type) 410 ptr_type=ptr_type)
411 natives += [native] 411 natives += [native]
412 return natives 412 return natives
413 413
414 414
415 def IsMainDexJavaClass(contents):
416 """Returns "true" if the class is annotated with "@MainDex", "false" if not.
417
418 JNI registration doesn't always need to be completed for non-browser processes
419 since most Java code is only used by the browser process. Classes that are
420 needed by non-browser processes must explicitly be annotated with @MainDex
421 to force JNI registration.
422 """
423 re_maindex = re.compile(r'@MainDex[\s\S]*class\s+\w+\s*{')
424 found = re.search(re_maindex, contents)
425 return 'true' if found else 'false'
426
427
415 def GetStaticCastForReturnType(return_type): 428 def GetStaticCastForReturnType(return_type):
416 type_map = { 'String' : 'jstring', 429 type_map = { 'String' : 'jstring',
417 'java/lang/String' : 'jstring', 430 'java/lang/String' : 'jstring',
418 'Throwable': 'jthrowable', 431 'Throwable': 'jthrowable',
419 'java/lang/Throwable': 'jthrowable', 432 'java/lang/Throwable': 'jthrowable',
420 'boolean[]': 'jbooleanArray', 433 'boolean[]': 'jbooleanArray',
421 'byte[]': 'jbyteArray', 434 'byte[]': 'jbyteArray',
422 'char[]': 'jcharArray', 435 'char[]': 'jcharArray',
423 'short[]': 'jshortArray', 436 'short[]': 'jshortArray',
424 'int[]': 'jintArray', 437 'int[]': 'jintArray',
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 continue 640 continue
628 value = re.match(re_constant_field_value, contents[lineno + 2]) 641 value = re.match(re_constant_field_value, contents[lineno + 2])
629 if not value: 642 if not value:
630 value = re.match(re_constant_field_value, contents[lineno + 3]) 643 value = re.match(re_constant_field_value, contents[lineno + 3])
631 if value: 644 if value:
632 self.constant_fields.append( 645 self.constant_fields.append(
633 ConstantField(name=match.group('name'), 646 ConstantField(name=match.group('name'),
634 value=value.group('value'))) 647 value=value.group('value')))
635 648
636 self.inl_header_file_generator = InlHeaderFileGenerator( 649 self.inl_header_file_generator = InlHeaderFileGenerator(
637 self.namespace, self.fully_qualified_class, [], 650 self.namespace, self.fully_qualified_class, [], self.called_by_natives,
638 self.called_by_natives, self.constant_fields, options) 651 self.constant_fields, options)
639 652
640 def GetContent(self): 653 def GetContent(self):
641 return self.inl_header_file_generator.GetContent() 654 return self.inl_header_file_generator.GetContent()
642 655
643 @staticmethod 656 @staticmethod
644 def CreateFromClass(class_file, options): 657 def CreateFromClass(class_file, options):
645 class_name = os.path.splitext(os.path.basename(class_file))[0] 658 class_name = os.path.splitext(os.path.basename(class_file))[0]
646 p = subprocess.Popen(args=[options.javap, '-c', '-verbose', 659 p = subprocess.Popen(args=[options.javap, '-c', '-verbose',
647 '-s', class_name], 660 '-s', class_name],
648 cwd=os.path.dirname(class_file), 661 cwd=os.path.dirname(class_file),
(...skipping 13 matching lines...) Expand all
662 r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', 675 r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
663 re.DOTALL | re.MULTILINE) 676 re.DOTALL | re.MULTILINE)
664 677
665 def __init__(self, contents, fully_qualified_class, options): 678 def __init__(self, contents, fully_qualified_class, options):
666 contents = self._RemoveComments(contents) 679 contents = self._RemoveComments(contents)
667 JniParams.SetFullyQualifiedClass(fully_qualified_class) 680 JniParams.SetFullyQualifiedClass(fully_qualified_class)
668 JniParams.ExtractImportsAndInnerClasses(contents) 681 JniParams.ExtractImportsAndInnerClasses(contents)
669 jni_namespace = ExtractJNINamespace(contents) or options.namespace 682 jni_namespace = ExtractJNINamespace(contents) or options.namespace
670 natives = ExtractNatives(contents, options.ptr_type) 683 natives = ExtractNatives(contents, options.ptr_type)
671 called_by_natives = ExtractCalledByNatives(contents) 684 called_by_natives = ExtractCalledByNatives(contents)
685 maindex = IsMainDexJavaClass(contents)
672 if len(natives) == 0 and len(called_by_natives) == 0: 686 if len(natives) == 0 and len(called_by_natives) == 0:
673 raise SyntaxError('Unable to find any JNI methods for %s.' % 687 raise SyntaxError('Unable to find any JNI methods for %s.' %
674 fully_qualified_class) 688 fully_qualified_class)
675 inl_header_file_generator = InlHeaderFileGenerator( 689 inl_header_file_generator = InlHeaderFileGenerator(
676 jni_namespace, fully_qualified_class, natives, called_by_natives, 690 jni_namespace, fully_qualified_class, natives, called_by_natives, [],
677 [], options) 691 options, maindex)
678 self.content = inl_header_file_generator.GetContent() 692 self.content = inl_header_file_generator.GetContent()
679 693
680 @classmethod 694 @classmethod
681 def _RemoveComments(cls, contents): 695 def _RemoveComments(cls, contents):
682 # We need to support both inline and block comments, and we need to handle 696 # We need to support both inline and block comments, and we need to handle
683 # strings that contain '//' or '/*'. 697 # strings that contain '//' or '/*'.
684 # TODO(bulach): This is a bit hacky. It would be cleaner to use a real Java 698 # TODO(bulach): This is a bit hacky. It would be cleaner to use a real Java
685 # parser. Maybe we could ditch JNIFromJavaSource and just always use 699 # parser. Maybe we could ditch JNIFromJavaSource and just always use
686 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. 700 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT.
687 # http://code.google.com/p/chromium/issues/detail?id=138941 701 # http://code.google.com/p/chromium/issues/detail?id=138941
(...skipping 15 matching lines...) Expand all
703 contents = file(java_file_name).read() 717 contents = file(java_file_name).read()
704 fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, 718 fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name,
705 contents) 719 contents)
706 return JNIFromJavaSource(contents, fully_qualified_class, options) 720 return JNIFromJavaSource(contents, fully_qualified_class, options)
707 721
708 722
709 class InlHeaderFileGenerator(object): 723 class InlHeaderFileGenerator(object):
710 """Generates an inline header file for JNI integration.""" 724 """Generates an inline header file for JNI integration."""
711 725
712 def __init__(self, namespace, fully_qualified_class, natives, 726 def __init__(self, namespace, fully_qualified_class, natives,
713 called_by_natives, constant_fields, options): 727 called_by_natives, constant_fields, options, maindex='false'):
714 self.namespace = namespace 728 self.namespace = namespace
715 self.fully_qualified_class = fully_qualified_class 729 self.fully_qualified_class = fully_qualified_class
716 self.class_name = self.fully_qualified_class.split('/')[-1] 730 self.class_name = self.fully_qualified_class.split('/')[-1]
717 self.natives = natives 731 self.natives = natives
718 self.called_by_natives = called_by_natives 732 self.called_by_natives = called_by_natives
719 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' 733 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI'
720 self.constant_fields = constant_fields 734 self.constant_fields = constant_fields
735 self.maindex = maindex
721 self.options = options 736 self.options = options
722 737
723 738
724 def GetContent(self): 739 def GetContent(self):
725 """Returns the content of the JNI binding file.""" 740 """Returns the content of the JNI binding file."""
726 template = Template("""\ 741 template = Template("""\
727 // Copyright 2014 The Chromium Authors. All rights reserved. 742 // Copyright 2014 The Chromium Authors. All rights reserved.
728 // Use of this source code is governed by a BSD-style license that can be 743 // Use of this source code is governed by a BSD-style license that can be
729 // found in the LICENSE file. 744 // found in the LICENSE file.
730 745
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 ${REGISTER_NATIVES_SIGNATURE} { 870 ${REGISTER_NATIVES_SIGNATURE} {
856 ${EARLY_EXIT} 871 ${EARLY_EXIT}
857 ${NATIVES} 872 ${NATIVES}
858 return true; 873 return true;
859 } 874 }
860 """) 875 """)
861 signature = 'static bool RegisterNativesImpl(JNIEnv* env)' 876 signature = 'static bool RegisterNativesImpl(JNIEnv* env)'
862 early_exit = '' 877 early_exit = ''
863 if self.options.native_exports_optional: 878 if self.options.native_exports_optional:
864 early_exit = """\ 879 early_exit = """\
865 if (base::android::IsManualJniRegistrationDisabled()) return true; 880 if (jni_generator::ShouldSkipJniRegistration(%s))
866 """ 881 return true;
882 """ % self.maindex
867 883
868 values = {'REGISTER_NATIVES_SIGNATURE': signature, 884 values = {'REGISTER_NATIVES_SIGNATURE': signature,
869 'EARLY_EXIT': early_exit, 885 'EARLY_EXIT': early_exit,
870 'NATIVES': natives, 886 'NATIVES': natives,
871 } 887 }
872 888
873 return template.substitute(values) 889 return template.substitute(values)
874 890
875 def GetRegisterNativesImplString(self): 891 def GetRegisterNativesImplString(self):
876 """Returns the shared implementation for RegisterNatives.""" 892 """Returns the shared implementation for RegisterNatives."""
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1393 root_name = os.path.splitext(os.path.basename(input_file))[0] 1409 root_name = os.path.splitext(os.path.basename(input_file))[0]
1394 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1410 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1395 GenerateJNIHeader(input_file, output_file, options) 1411 GenerateJNIHeader(input_file, output_file, options)
1396 1412
1397 if options.depfile: 1413 if options.depfile:
1398 build_utils.WriteDepfile(options.depfile, output_file) 1414 build_utils.WriteDepfile(options.depfile, output_file)
1399 1415
1400 1416
1401 if __name__ == '__main__': 1417 if __name__ == '__main__':
1402 sys.exit(main(sys.argv)) 1418 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « base/android/jni_generator/SampleForTests_jni.golden ('k') | base/android/jni_generator/jni_generator_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698