Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 # TODO (qinmin): Need to refactor this file as base should not know about | 6 # TODO (qinmin): Need to refactor this file as base should not know about |
| 7 # higher level concepts. Currently this file has knowledge about higher level | 7 # higher level concepts. Currently this file has knowledge about higher level |
| 8 # java classes. | 8 # java classes. |
| 9 | 9 |
| 10 """Extracts native methods from a Java file and generates the JNI bindings. | 10 """Extracts native methods from a Java file and generates the JNI bindings. |
| 11 If you change this, please run and update the tests.""" | 11 If you change this, please run and update the tests.""" |
| 12 | 12 |
| 13 import collections | 13 import collections |
| 14 import optparse | 14 import optparse |
| 15 import os | 15 import os |
| 16 import re | 16 import re |
| 17 import string | 17 import string |
| 18 from string import Template | 18 from string import Template |
| 19 import subprocess | 19 import subprocess |
| 20 import sys | 20 import sys |
| 21 import textwrap | 21 import textwrap |
| 22 import zipfile | 22 import zipfile |
| 23 | 23 |
| 24 UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' | 24 UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' |
| 25 | 25 APP_PARAM_LIST = [] |
|
Yaron
2012/10/29 17:49:18
Nit: don't shorten. Call it APPLICATION_PARAM_LIST
bulach
2012/10/29 18:57:06
Done.
| |
| 26 | 26 |
| 27 class ParseError(Exception): | 27 class ParseError(Exception): |
| 28 """Exception thrown when we can't parse the input file.""" | 28 """Exception thrown when we can't parse the input file.""" |
| 29 | 29 |
| 30 def __init__(self, description, *context_lines): | 30 def __init__(self, description, *context_lines): |
| 31 Exception.__init__(self) | 31 Exception.__init__(self) |
| 32 self.description = description | 32 self.description = description |
| 33 self.context_lines = context_lines | 33 self.context_lines = context_lines |
| 34 | 34 |
| 35 def __str__(self): | 35 def __str__(self): |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 'Ljava/util/ArrayList', | 133 'Ljava/util/ArrayList', |
| 134 'Ljava/util/HashMap', | 134 'Ljava/util/HashMap', |
| 135 'Ljava/util/List', | 135 'Ljava/util/List', |
| 136 'Landroid/content/Context', | 136 'Landroid/content/Context', |
| 137 'Landroid/graphics/Bitmap', | 137 'Landroid/graphics/Bitmap', |
| 138 'Landroid/graphics/Canvas', | 138 'Landroid/graphics/Canvas', |
| 139 'Landroid/graphics/Rect', | 139 'Landroid/graphics/Rect', |
| 140 'Landroid/graphics/RectF', | 140 'Landroid/graphics/RectF', |
| 141 'Landroid/graphics/Matrix', | 141 'Landroid/graphics/Matrix', |
| 142 'Landroid/graphics/Point', | 142 'Landroid/graphics/Point', |
| 143 'Landroid/graphics/SurfaceTexture', | |
| 143 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', | 144 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', |
| 144 'Landroid/media/MediaPlayer', | 145 'Landroid/media/MediaPlayer', |
| 145 'Landroid/os/Message', | 146 'Landroid/os/Message', |
| 146 'Landroid/view/KeyEvent', | 147 'Landroid/view/KeyEvent', |
| 147 'Landroid/view/Surface', | 148 'Landroid/view/Surface', |
| 148 'Landroid/view/View', | 149 'Landroid/view/View', |
| 149 'Landroid/webkit/ValueCallback', | 150 'Landroid/webkit/ValueCallback', |
| 150 'Ljava/io/InputStream', | 151 'Ljava/io/InputStream', |
| 151 'Ljava/nio/ByteBuffer', | 152 'Ljava/nio/ByteBuffer', |
| 152 'Ljava/util/Vector', | 153 'Ljava/util/Vector', |
| 153 ] | 154 ] |
| 154 app_param_list = [ | |
| 155 'Landroid/graphics/SurfaceTexture', | |
| 156 'Lcom/google/android/apps/chrome/ChromeContextMenuInfo', | |
| 157 'Lcom/google/android/apps/chrome/ChromeWindow', | |
| 158 'Lcom/google/android/apps/chrome/GoogleLocationSettingsHelperImpl', | |
| 159 'Lcom/google/android/apps/chrome/OmniboxSuggestion', | |
| 160 'Lcom/google/android/apps/chrome/PageInfoViewer', | |
| 161 'Lcom/google/android/apps/chrome/Tab', | |
| 162 'Lcom/google/android/apps/chrome/infobar/AutoLogin', | |
| 163 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer', | |
| 164 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer$NativeInfoBar', | |
| 165 ('Lcom/google/android/apps/chrome/preferences/ChromeNativePreferences$' | |
| 166 'PasswordListObserver'), | |
| 167 'Lorg/chromium/android_webview/AwContents', | |
| 168 'Lorg/chromium/android_webview/AwContentsClient', | |
| 169 'Lorg/chromium/android_webview/AwHttpAuthHandler', | |
| 170 'Lorg/chromium/android_webview/AwContentsIoThreadClient', | |
| 171 'Lorg/chromium/android_webview/AwWebContentsDelegate', | |
| 172 'Lorg/chromium/android_webview/InterceptedRequestData', | |
| 173 'Lorg/chromium/android_webview/JsPromptResultReceiver', | |
| 174 'Lorg/chromium/android_webview/JsResultHandler', | |
| 175 'Lorg/chromium/android_webview/JsResultReceiver', | |
| 176 'Lorg/chromium/base/SystemMessageHandler', | |
| 177 'Lorg/chromium/chrome/browser/autofill/AutofillExternalDelegate', | |
| 178 'Lorg/chromium/chrome/browser/autofill/AutofillSuggestion', | |
| 179 'Lorg/chromium/chrome/browser/ChromeBrowserProvider$BookmarkNode', | |
| 180 'Lorg/chromium/chrome/browser/ChromeHttpAuthHandler', | |
| 181 'Lorg/chromium/chrome/browser/ChromeWebContentsDelegateAndroid', | |
| 182 'Lorg/chromium/chrome/browser/FindMatchRectsDetails', | |
| 183 'Lorg/chromium/chrome/browser/FindNotificationDetails', | |
| 184 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelper', | |
| 185 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelperStub', | |
| 186 'Lorg/chromium/chrome/browser/JavascriptAppModalDialog', | |
| 187 'Lorg/chromium/chrome/browser/ProcessUtils', | |
| 188 ('Lorg/chromium/chrome/browser/component/navigation_interception/' | |
| 189 'InterceptNavigationDelegate'), | |
| 190 ('Lorg/chromium/chrome/browser/component/web_contents_delegate_android/' | |
| 191 'WebContentsDelegateAndroid'), | |
| 192 'Lorg/chromium/chrome/browser/database/SQLiteCursor', | |
| 193 'Lorg/chromium/content/app/SandboxedProcessService', | |
| 194 'Lorg/chromium/content/browser/ContainerViewDelegate', | |
| 195 'Lorg/chromium/content/browser/ContentVideoView', | |
| 196 'Lorg/chromium/content/browser/ContentViewCore', | |
| 197 'Lorg/chromium/content/browser/DeviceOrientation', | |
| 198 'Lorg/chromium/content/browser/JavaInputStream', | |
| 199 'Lorg/chromium/content/browser/LocationProvider', | |
| 200 'Lorg/chromium/content/browser/SandboxedProcessArgs', | |
| 201 'Lorg/chromium/content/browser/SandboxedProcessConnection', | |
| 202 'Lorg/chromium/content/browser/TouchPoint', | |
| 203 'Lorg/chromium/content/browser/WaitableNativeEvent', | |
| 204 'Lorg/chromium/content/browser/WebContentsObserverAndroid', | |
| 205 'Lorg/chromium/content/common/DeviceInfo', | |
| 206 'Lorg/chromium/content/common/SurfaceTextureListener', | |
| 207 'Lorg/chromium/media/MediaPlayerListener', | |
| 208 'Lorg/chromium/net/NetworkChangeNotifier', | |
| 209 'Lorg/chromium/net/ProxyChangeListener', | |
| 210 'Lorg/chromium/ui/gfx/NativeWindow', | |
| 211 'Lorg/chromium/ui/SelectFileDialog', | |
| 212 ] | |
| 213 if param == 'byte[][]': | 155 if param == 'byte[][]': |
| 214 return '[[B' | 156 return '[[B' |
| 215 prefix = '' | 157 prefix = '' |
| 216 # Array? | 158 # Array? |
| 217 if param[-2:] == '[]': | 159 if param[-2:] == '[]': |
| 218 prefix = '[' | 160 prefix = '[' |
| 219 param = param[:-2] | 161 param = param[:-2] |
| 220 # Generic? | 162 # Generic? |
| 221 if '<' in param: | 163 if '<' in param: |
| 222 param = param[:param.index('<')] | 164 param = param[:param.index('<')] |
| 223 if param in pod_param_map: | 165 if param in pod_param_map: |
| 224 return prefix + pod_param_map[param] | 166 return prefix + pod_param_map[param] |
| 225 if '/' in param: | 167 if '/' in param: |
| 226 # Coming from javap, use the fully qualified param directly. | 168 # Coming from javap, use the fully qualified param directly. |
| 227 return 'L' + param + ';' | 169 return 'L' + param + ';' |
| 228 for qualified_name in object_param_list + app_param_list: | 170 for qualified_name in object_param_list + APP_PARAM_LIST: |
| 229 if (qualified_name.endswith('/' + param) or | 171 if (qualified_name.endswith('/' + param) or |
| 230 qualified_name.endswith('$' + param.replace('.', '$')) or | 172 qualified_name.endswith('$' + param.replace('.', '$')) or |
| 231 qualified_name == 'L' + param): | 173 qualified_name == 'L' + param): |
| 232 return prefix + qualified_name + ';' | 174 return prefix + qualified_name + ';' |
| 233 else: | 175 else: |
| 234 return UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' | 176 return UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' |
| 235 | 177 |
| 236 | 178 |
| 237 def JniSignature(params, returns, wrap): | 179 def JniSignature(params, returns, wrap): |
| 238 """Returns the JNI signature for the given datatypes.""" | 180 """Returns the JNI signature for the given datatypes.""" |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 sys.exit(1) | 946 sys.exit(1) |
| 1005 if output_file: | 947 if output_file: |
| 1006 if not os.path.exists(os.path.dirname(os.path.abspath(output_file))): | 948 if not os.path.exists(os.path.dirname(os.path.abspath(output_file))): |
| 1007 os.makedirs(os.path.dirname(os.path.abspath(output_file))) | 949 os.makedirs(os.path.dirname(os.path.abspath(output_file))) |
| 1008 with file(output_file, 'w') as f: | 950 with file(output_file, 'w') as f: |
| 1009 f.write(content) | 951 f.write(content) |
| 1010 else: | 952 else: |
| 1011 print output | 953 print output |
| 1012 | 954 |
| 1013 | 955 |
| 956 def ReadExtraAppParamList(extra_app_param_files): | |
| 957 if not extra_app_param_files: | |
| 958 return | |
| 959 for extra_app_param_file in set(extra_app_param_files): | |
| 960 with file(extra_app_param_file, 'r') as f: | |
| 961 contents = f.read() | |
| 962 global APP_PARAM_LIST | |
| 963 tmp_globals = {'APP_PARAM_LIST': APP_PARAM_LIST} | |
| 964 tmp_locals = {} | |
| 965 exec(contents) in tmp_globals, tmp_locals | |
|
Yaron
2012/10/29 17:49:18
I'm not really keen on exec'ing external files. Ca
bulach
2012/10/29 18:57:06
sounds reasonable, stripping out comments is not t
| |
| 966 APP_PARAM_LIST = tmp_locals['APP_PARAM_LIST'] | |
| 967 | |
| 968 | |
| 1014 def main(argv): | 969 def main(argv): |
| 1015 usage = """usage: %prog [OPTIONS] | 970 usage = """usage: %prog [OPTIONS] |
| 1016 This script will parse the given java source code extracting the native | 971 This script will parse the given java source code extracting the native |
| 1017 declarations and print the header file to stdout (or a file). | 972 declarations and print the header file to stdout (or a file). |
| 1018 See SampleForTests.java for more details. | 973 See SampleForTests.java for more details. |
| 1019 """ | 974 """ |
| 1020 option_parser = optparse.OptionParser(usage=usage) | 975 option_parser = optparse.OptionParser(usage=usage) |
| 1021 option_parser.add_option('-j', dest='jar_file', | 976 option_parser.add_option('-j', dest='jar_file', |
| 1022 help='Extract the list of input files from' | 977 help='Extract the list of input files from' |
| 1023 ' a specified jar file.' | 978 ' a specified jar file.' |
| 1024 ' Uses javap to extract the methods from a' | 979 ' Uses javap to extract the methods from a' |
| 1025 ' pre-compiled class. --input should point' | 980 ' pre-compiled class. --input should point' |
| 1026 ' to pre-compiled Java .class files.') | 981 ' to pre-compiled Java .class files.') |
| 1027 option_parser.add_option('-n', dest='namespace', | 982 option_parser.add_option('-n', dest='namespace', |
| 1028 help='Uses as a namespace in the generated header,' | 983 help='Uses as a namespace in the generated header,' |
| 1029 ' instead of the javap class name.') | 984 ' instead of the javap class name.') |
| 1030 option_parser.add_option('--input_file', | 985 option_parser.add_option('--input_file', |
| 1031 help='Single input file name. The output file name ' | 986 help='Single input file name. The output file name ' |
| 1032 'will be derived from it. Must be used with ' | 987 'will be derived from it. Must be used with ' |
| 1033 '--output_dir.') | 988 '--output_dir.') |
| 1034 option_parser.add_option('--output_dir', | 989 option_parser.add_option('--output_dir', |
| 1035 help='The output directory. Must be used with ' | 990 help='The output directory. Must be used with ' |
| 1036 '--input') | 991 '--input') |
| 992 option_parser.add_option('--app_param_list', | |
| 993 help='A file name containing a list with extra ' | |
| 994 'fully-qualified param names. Can be used multiple ' | |
| 995 'times.', | |
| 996 action='append') | |
| 1037 options, args = option_parser.parse_args(argv) | 997 options, args = option_parser.parse_args(argv) |
| 998 ReadExtraAppParamList(options.app_param_list) | |
| 1038 if options.jar_file: | 999 if options.jar_file: |
| 1039 input_file = ExtractJarInputFile(options.jar_file, options.input_file, | 1000 input_file = ExtractJarInputFile(options.jar_file, options.input_file, |
| 1040 options.output_dir) | 1001 options.output_dir) |
| 1041 else: | 1002 else: |
| 1042 input_file = options.input_file | 1003 input_file = options.input_file |
| 1043 output_file = None | 1004 output_file = None |
| 1044 if options.output_dir: | 1005 if options.output_dir: |
| 1045 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1006 root_name = os.path.splitext(os.path.basename(input_file))[0] |
| 1046 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1007 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
| 1047 GenerateJNIHeader(input_file, output_file, options.namespace) | 1008 GenerateJNIHeader(input_file, output_file, options.namespace) |
| 1048 | 1009 |
| 1049 | 1010 |
| 1050 if __name__ == '__main__': | 1011 if __name__ == '__main__': |
| 1051 sys.exit(main(sys.argv)) | 1012 sys.exit(main(sys.argv)) |
| OLD | NEW |