def GenerateJNIHeader(java_file_paths, output_file, args): """Generate a header file including two registration functions. Forward declares all JNI registration functions created by jni_generator.py. Calls the functions in RegisterMainDexNatives() if they are main dex. And calls them in RegisterNonMainDexNatives() if they are non-main dex. Args: java_file_paths: A list of java file paths. output_file: A relative path to output file. args: All input arguments. """ registration_dict = {} # Sort the file list to make sure the order is deterministic. java_file_paths.sort() for path in java_file_paths: if path in args.no_register_java: continue with open(path) as f: contents = jni_generator.RemoveComments(f.read()) natives = jni_generator.ExtractNatives(contents, 'long') if len(natives) == 0: continue namespace = jni_generator.ExtractJNINamespace(contents) fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName( path, contents) jni_params = jni_generator.JniParams(fully_qualified_class) jni_params.ExtractImportsAndInnerClasses(contents) main_dex = jni_generator.IsMainDexJavaClass(contents) header_generator = HeaderGenerator(namespace, fully_qualified_class, natives, jni_params, registration_dict, main_dex) header_generator.AddContent() header_content = CreateFromDict(registration_dict) if output_file: jni_generator.WriteOutput(output_file, header_content) else: print header_content
def testInnerClassNativesBothInnerAndOuter(self): test_data = """ class MyOuterClass { private native int nativeInit(); class MyOtherInnerClass { @NativeCall("MyOtherInnerClass") private native int nativeInit(); } } """ natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name=None, type='function'), NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name='MyOtherInnerClass', type='function') ] self.assertListEquals(golden_natives, natives) jni_params = jni_generator.JniParams('') h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, [], [], jni_params, TestOptions()) self.assertGoldenTextEquals(h.GetContent()) content = {} h2 = jni_registration_generator.HeaderGenerator( '', 'org/chromium/TestJni', natives, jni_params, content, True) h2.AddContent() self.assertGoldenTextEquals( jni_registration_generator.CreateFromDict(content), suffix='Registrations')
def testInnerClassNatives(self): test_data = """ class MyInnerClass { @NativeCall("MyInnerClass") private native int nativeInit(); } """ natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name='MyInnerClass', type='function') ] self.assertListEquals(golden_natives, natives) jni_params = jni_generator.JniParams('') h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, [], [], jni_params, TestOptions()) self.assertGoldenTextEquals(h.GetContent())
def GenerateJNIHeader(java_file_paths, output_file, args): """Generate a header file including two registration functions. Forward declares all JNI registration functions created by jni_generator.py. Calls the functions in RegisterMainDexNatives() if they are main dex. And calls them in RegisterNonMainDexNatives() if they are non-main dex. Args: java_file_paths: A list of java file paths. output_file: A relative path to output file. args: All input arguments. """ registration_dict = { 'FORWARD_DECLARATIONS': '', 'REGISTER_MAIN_DEX_NATIVES': '', 'REGISTER_NON_MAIN_DEX_NATIVES': '' } # Sort the file list to make sure the order is deterministic. java_file_paths.sort() for path in java_file_paths: if path in args.no_register_java: continue with open(path) as f: contents = f.read() natives = jni_generator.ExtractNatives(contents, 'long') if len(natives) == 0: continue fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName( path, contents) main_dex = jni_generator.IsMainDexJavaClass(contents) header_generator = HeaderGenerator( fully_qualified_class, registration_dict, main_dex) registration_dict = header_generator.GetContent() header_content = CreateFromDict(registration_dict) if output_file: jni_generator.WriteOutput(output_file, header_content) else: print header_content
def testNativesLong(self): test_options = TestOptions() test_options.ptr_type = 'long' test_data = """" private native void nativeDestroy(long nativeChromeBrowserProvider); """ jni_params = jni_generator.JniParams('') jni_params.ExtractImportsAndInnerClasses(test_data) natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type) golden_natives = [ NativeMethod(return_type='void', static=False, name='Destroy', params=[Param(datatype='long', name='nativeChromeBrowserProvider')], java_class_name=None, type='method', p0_type='ChromeBrowserProvider', ptr_type=test_options.ptr_type), ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, [], [], jni_params, test_options) self.assertGoldenTextEquals(h.GetContent())
def _DictForPath(path, use_proxy_hash=False): with open(path) as f: contents = jni_generator.RemoveComments(f.read()) if '@JniIgnoreNatives' in contents: return None fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName( path, contents) natives = jni_generator.ExtractNatives(contents, 'long') natives += jni_generator.ProxyHelpers.ExtractStaticProxyNatives( fully_qualified_class=fully_qualified_class, contents=contents, ptr_type='long') if len(natives) == 0: return None namespace = jni_generator.ExtractJNINamespace(contents) jni_params = jni_generator.JniParams(fully_qualified_class) jni_params.ExtractImportsAndInnerClasses(contents) is_main_dex = jni_generator.IsMainDexJavaClass(contents) header_generator = HeaderGenerator(namespace, fully_qualified_class, natives, jni_params, is_main_dex, use_proxy_hash) return header_generator.Generate()
def convert_file_to_proxy_natives(java_file_name, dry=False, verbose=True): if not os.path.isfile(java_file_name): if verbose: print('%s does not exist', java_file_name) return with open(java_file_name, 'r') as f: contents = f.read() no_comment_content = jni_generator.RemoveComments(contents) natives = jni_generator.ExtractNatives(no_comment_content, 'long') static_natives = [n for n in natives if n.static] if not static_natives: if verbose: print('%s has no static natives.', java_file_name) return contents = add_chromium_import_to_java_file(contents, JNI_IMPORT_STRING) # Extract comments and annotations above native methods. native_map = {} for itr in re.finditer(_NATIVES_REGEX, contents): n_dict = {} n_dict['annotations'] = itr.group('annotations').strip() n_dict['comments'] = itr.group('comments').strip() n_dict['params'] = itr.group('params').strip() native_map[itr.group('name')] = n_dict # Using static natives here ensures all the methods that are picked up by # the JNI generator are also caught by our own regex. methods = [] for n in static_natives: new_name = n.name[0].lower() + n.name[1:] n_dict = native_map['native' + n.name] params = n_dict['params'] comments = n_dict['comments'] annotations = n_dict['annotations'] methods.append( build_method_declaration(n.return_type, new_name, params, annotations, comments)) fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName( java_file_name, contents) class_name = fully_qualified_class.split('/')[-1] jni_class_name = class_name + 'Jni' # Remove all old declarations. for n in static_natives: pattern = _NATIVES_REGEX contents = re.sub(pattern, '', contents) # Replace occurences with new signature. for n in static_natives: # Okay not to match first (. # Since even if natives share a prefix, the replacement is the same. # E.g. if nativeFoo() and nativeFooBar() are both statics # and in nativeFooBar() we replace nativeFoo -> AJni.get().foo # the result is the same as replacing nativeFooBar() -> AJni.get().fooBar pattern = r'native%s' % n.name lower_name = n.name[0].lower() + n.name[1:] contents = re.sub(pattern, '%s.get().%s' % (jni_class_name, lower_name), contents) # Build and insert the @NativeMethods interface. interface = _JNI_INTERFACE_TEMPLATES.substitute({ 'INTERFACE_NAME': 'Natives', 'METHODS': ''.join(methods) }) # Insert the interface at the bottom of the top level class. # Most of the time this will be before the last }. insertion_point = contents.rfind('}') contents = contents[:insertion_point] + '\n' + interface + contents[ insertion_point:] if not dry: with open(java_file_name, 'w') as f: f.write(contents) else: print(contents) return contents
def convert_nonstatic_to_static(java_file_name, dry=False, verbose=True): if java_file_name is None: return if not os.path.isfile(java_file_name): if verbose: print('%s does not exist', java_file_name) return with open(java_file_name, 'r') as f: contents = f.read() no_comment_content = jni_generator.RemoveComments(contents) parsed_natives = jni_generator.ExtractNatives(no_comment_content, 'long') non_static_natives = [n for n in parsed_natives if not n.static] if not non_static_natives: if verbose: print('no natives found') return class_name = jni_generator.ExtractFullyQualifiedJavaClassName( java_file_name, no_comment_content).split('/')[-1] replace_patterns = [] should_add_comma = [] new_contents = contents # 1. Change non-static -> static. insertion_offset = 0 matches = [] for match in _NON_STATIC_NATIVES_REGEX.finditer(contents): if not 'static' in match.group('qualifiers'): matches.append(match) # Insert static as a keyword. qual_end = match.end('qualifiers') + insertion_offset insert_str = ' static ' new_contents = new_contents[:qual_end] + insert_str + new_contents[ qual_end:] insertion_offset += len(insert_str) # Insert an object param. start = insertion_offset + match.end('params') insert_str = '%s caller' % class_name if match.group('params'): insert_str = ', ' + insert_str # Match lines that don't have a native keyword. replace_patterns.append(r'(^\s*' + match.group('name') + r'\(.*?(?=\)))') replace_patterns.append(r'(return ' + match.group('name') + r'\(.*?(?=\)))') replace_patterns.append(r'([\:\)\(\+\*\?\&\|,\.\-\=\!\/][ \t]*' + match.group('name') + r'\(.*?(?=\)))') add_comma = bool(match.group('params')) should_add_comma.extend([add_comma] * 3) new_contents = new_contents[:start] + insert_str + new_contents[ start:] insertion_offset += len(insert_str) assert len(matches) == len(non_static_natives), ( 'Regex missed a native ' 'method that was found by ' 'the jni_generator.') # 2. Add a this param to all calls. for i, r in enumerate(replace_patterns): if should_add_comma[i]: new_contents = re.sub(r, '\g<1>, %s.this' % class_name, new_contents, flags=re.MULTILINE) else: new_contents = re.sub(r, '\g<1>%s.this' % class_name, new_contents, flags=re.MULTILINE) if dry: print(new_contents) else: with open(java_file_name, 'w') as f: f.write(new_contents)
def testNatives(self): test_data = """" import android.graphics.Bitmap; import android.view.View; interface OnFrameAvailableListener {} private native int nativeInit(); private native void nativeDestroy(int nativeChromeBrowserProvider); private native long nativeAddBookmark( int nativeChromeBrowserProvider, String url, String title, boolean isFolder, long parentId); private static native String nativeGetDomainAndRegistry(String url); private static native void nativeCreateHistoricalTabFromState( byte[] state, int tab_index); private native byte[] nativeGetStateAsByteArray(View view); private static native String[] nativeGetAutofillProfileGUIDs(); private native void nativeSetRecognitionResults( int sessionId, String[] results); private native long nativeAddBookmarkFromAPI( int nativeChromeBrowserProvider, String url, Long created, Boolean isBookmark, Long date, byte[] favicon, String title, Integer visits); native int nativeFindAll(String find); private static native OnFrameAvailableListener nativeGetInnerClass(); private native Bitmap nativeQueryBitmap( int nativeChromeBrowserProvider, String[] projection, String selection, String[] selectionArgs, String sortOrder); private native void nativeGotOrientation( int nativeDataFetcherImplAndroid, double alpha, double beta, double gamma); private static native Throwable nativeMessWithJavaException(Throwable e); """ jni_params = jni_generator.JniParams( 'org/chromium/example/jni_generator/SampleForTests') jni_params.ExtractImportsAndInnerClasses(test_data) natives = jni_generator.ExtractNatives(test_data, 'int') golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name=None, type='function'), NativeMethod(return_type='void', static=False, name='Destroy', params=[Param(datatype='int', name='nativeChromeBrowserProvider')], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='long', static=False, name='AddBookmark', params=[Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String', name='url'), Param(datatype='String', name='title'), Param(datatype='boolean', name='isFolder'), Param(datatype='long', name='parentId')], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='String', static=True, name='GetDomainAndRegistry', params=[Param(datatype='String', name='url')], java_class_name=None, type='function'), NativeMethod(return_type='void', static=True, name='CreateHistoricalTabFromState', params=[Param(datatype='byte[]', name='state'), Param(datatype='int', name='tab_index')], java_class_name=None, type='function'), NativeMethod(return_type='byte[]', static=False, name='GetStateAsByteArray', params=[Param(datatype='View', name='view')], java_class_name=None, type='function'), NativeMethod(return_type='String[]', static=True, name='GetAutofillProfileGUIDs', params=[], java_class_name=None, type='function'), NativeMethod(return_type='void', static=False, name='SetRecognitionResults', params=[Param(datatype='int', name='sessionId'), Param(datatype='String[]', name='results')], java_class_name=None, type='function'), NativeMethod(return_type='long', static=False, name='AddBookmarkFromAPI', params=[Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String', name='url'), Param(datatype='Long', name='created'), Param(datatype='Boolean', name='isBookmark'), Param(datatype='Long', name='date'), Param(datatype='byte[]', name='favicon'), Param(datatype='String', name='title'), Param(datatype='Integer', name='visits')], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='int', static=False, name='FindAll', params=[Param(datatype='String', name='find')], java_class_name=None, type='function'), NativeMethod(return_type='OnFrameAvailableListener', static=True, name='GetInnerClass', params=[], java_class_name=None, type='function'), NativeMethod(return_type='Bitmap', static=False, name='QueryBitmap', params=[Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String[]', name='projection'), Param(datatype='String', name='selection'), Param(datatype='String[]', name='selectionArgs'), Param(datatype='String', name='sortOrder'), ], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='void', static=False, name='GotOrientation', params=[Param(datatype='int', name='nativeDataFetcherImplAndroid'), Param(datatype='double', name='alpha'), Param(datatype='double', name='beta'), Param(datatype='double', name='gamma'), ], java_class_name=None, type='method', p0_type='content::DataFetcherImplAndroid'), NativeMethod(return_type='Throwable', static=True, name='MessWithJavaException', params=[Param(datatype='Throwable', name='e')], java_class_name=None, type='function') ] self.assertListEquals(golden_natives, natives) h1 = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, [], [], jni_params, TestOptions()) self.assertGoldenTextEquals(h1.GetContent()) content = {} h2 = jni_registration_generator.HeaderGenerator( '', 'org/chromium/TestJni', natives, jni_params, content, True) h2.AddContent() self.assertGoldenTextEquals( jni_registration_generator.CreateFromDict(content), suffix='Registrations')
def testInnerClassNativesBothInnerAndOuter(self): test_data = """ class MyOuterClass { private native int nativeInit(); class MyOtherInnerClass { @NativeCall("MyOtherInnerClass") private native int nativeInit(); } } """ natives = jni_generator.ExtractNatives(test_data) golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name=None, type='function'), NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name='MyOtherInnerClass', type='function') ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, []) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by // base/android/jni_generator/jni_generator_tests.py // For // org/chromium/TestJni #ifndef org_chromium_TestJni_JNI #define org_chromium_TestJni_JNI #include <jni.h> #include "base/android/jni_android.h" #include "base/android/scoped_java_ref.h" #include "base/basictypes.h" #include "base/logging.h" using base::android::ScopedJavaLocalRef; // Step 1: forward declarations. namespace { const char kMyOtherInnerClassClassPath[] = "org/chromium/TestJni$MyOtherInnerClass"; const char kTestJniClassPath[] = "org/chromium/TestJni"; // Leaking this jclass as we cannot use LazyInstance from some threads. jclass g_TestJni_clazz = NULL; } // namespace static jint Init(JNIEnv* env, jobject obj); static jint Init(JNIEnv* env, jobject obj); // Step 2: method stubs. // Step 3: GetMethodIDs and RegisterNatives. static void GetMethodIDsImpl(JNIEnv* env) { g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( base::android::GetUnscopedClass(env, kTestJniClassPath))); } static bool RegisterNativesImpl(JNIEnv* env) { GetMethodIDsImpl(env); static const JNINativeMethod kMethodsMyOtherInnerClass[] = { { "nativeInit", "(" ")" "I", reinterpret_cast<void*>(Init) }, }; const int kMethodsMyOtherInnerClassSize = arraysize(kMethodsMyOtherInnerClass); if (env->RegisterNatives(g_MyOtherInnerClass_clazz, kMethodsMyOtherInnerClass, kMethodsMyOtherInnerClassSize) < 0) { LOG(ERROR) << "RegisterNatives failed in " << __FILE__; return false; } static const JNINativeMethod kMethodsTestJni[] = { { "nativeInit", "(" ")" "I", reinterpret_cast<void*>(Init) }, }; const int kMethodsTestJniSize = arraysize(kMethodsTestJni); if (env->RegisterNatives(g_TestJni_clazz, kMethodsTestJni, kMethodsTestJniSize) < 0) { LOG(ERROR) << "RegisterNatives failed in " << __FILE__; return false; } return true; } #endif // org_chromium_TestJni_JNI """ self.assertTextEquals(golden_content, h.GetContent())
def testNatives(self): test_data = """" private native int nativeInit(); private native void nativeDestroy(int nativeChromeBrowserProvider); private native long nativeAddBookmark( int nativeChromeBrowserProvider, String url, String title, boolean isFolder, long parentId); private static native String nativeGetDomainAndRegistry(String url); private static native void nativeCreateHistoricalTabFromState( byte[] state, int tab_index); private native byte[] nativeGetStateAsByteArray(ContentView view); private static native String[] nativeGetAutofillProfileGUIDs(); private native void nativeSetRecognitionResults( int sessionId, String[] results); private native long nativeAddBookmarkFromAPI( int nativeChromeBrowserProvider, String url, Long created, Boolean isBookmark, Long date, byte[] favicon, String title, Integer visits); native int nativeFindAll(String find); private static native BookmarkNode nativeGetDefaultBookmarkFolder(); private native SQLiteCursor nativeQueryBookmarkFromAPI( int nativeChromeBrowserProvider, String[] projection, String selection, String[] selectionArgs, String sortOrder); private native void nativeGotOrientation( int nativeDataFetcherImplAndroid, double alpha, double beta, double gamma); """ natives = jni_generator.ExtractNatives(test_data) golden_natives = [ NativeMethod(return_type='int', static=False, name='Init', params=[], java_class_name=None, type='function'), NativeMethod(return_type='void', static=False, name='Destroy', params=[ Param(datatype='int', name='nativeChromeBrowserProvider') ], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='long', static=False, name='AddBookmark', params=[ Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String', name='url'), Param(datatype='String', name='title'), Param(datatype='boolean', name='isFolder'), Param(datatype='long', name='parentId') ], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='String', static=True, name='GetDomainAndRegistry', params=[Param(datatype='String', name='url')], java_class_name=None, type='function'), NativeMethod(return_type='void', static=True, name='CreateHistoricalTabFromState', params=[ Param(datatype='byte[]', name='state'), Param(datatype='int', name='tab_index') ], java_class_name=None, type='function'), NativeMethod(return_type='byte[]', static=False, name='GetStateAsByteArray', params=[Param(datatype='ContentView', name='view')], java_class_name=None, type='function'), NativeMethod(return_type='String[]', static=True, name='GetAutofillProfileGUIDs', params=[], java_class_name=None, type='function'), NativeMethod(return_type='void', static=False, name='SetRecognitionResults', params=[ Param(datatype='int', name='sessionId'), Param(datatype='String[]', name='results') ], java_class_name=None, type='function'), NativeMethod(return_type='long', static=False, name='AddBookmarkFromAPI', params=[ Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String', name='url'), Param(datatype='Long', name='created'), Param(datatype='Boolean', name='isBookmark'), Param(datatype='Long', name='date'), Param(datatype='byte[]', name='favicon'), Param(datatype='String', name='title'), Param(datatype='Integer', name='visits') ], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='int', static=False, name='FindAll', params=[Param(datatype='String', name='find')], java_class_name=None, type='function'), NativeMethod(return_type='BookmarkNode', static=True, name='GetDefaultBookmarkFolder', params=[], java_class_name=None, type='function'), NativeMethod(return_type='SQLiteCursor', static=False, name='QueryBookmarkFromAPI', params=[ Param(datatype='int', name='nativeChromeBrowserProvider'), Param(datatype='String[]', name='projection'), Param(datatype='String', name='selection'), Param(datatype='String[]', name='selectionArgs'), Param(datatype='String', name='sortOrder'), ], java_class_name=None, type='method', p0_type='ChromeBrowserProvider'), NativeMethod(return_type='void', static=False, name='GotOrientation', params=[ Param(datatype='int', name='nativeDataFetcherImplAndroid'), Param(datatype='double', name='alpha'), Param(datatype='double', name='beta'), Param(datatype='double', name='gamma'), ], java_class_name=None, type='method', p0_type='device_orientation::DataFetcherImplAndroid'), ] self.assertListEquals(golden_natives, natives) h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', natives, []) golden_content = """\ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is autogenerated by // base/android/jni_generator/jni_generator_tests.py // For // org/chromium/TestJni #ifndef org_chromium_TestJni_JNI #define org_chromium_TestJni_JNI #include <jni.h> #include "base/android/jni_android.h" #include "base/android/scoped_java_ref.h" #include "base/basictypes.h" #include "base/logging.h" using base::android::ScopedJavaLocalRef; // Step 1: forward declarations. namespace { const char kTestJniClassPath[] = "org/chromium/TestJni"; // Leaking this jclass as we cannot use LazyInstance from some threads. jclass g_TestJni_clazz = NULL; } // namespace static jint Init(JNIEnv* env, jobject obj); static jstring GetDomainAndRegistry(JNIEnv* env, jclass clazz, jstring url); static void CreateHistoricalTabFromState(JNIEnv* env, jclass clazz, jbyteArray state, jint tab_index); static jbyteArray GetStateAsByteArray(JNIEnv* env, jobject obj, jobject view); static jobjectArray GetAutofillProfileGUIDs(JNIEnv* env, jclass clazz); static void SetRecognitionResults(JNIEnv* env, jobject obj, jint sessionId, jobjectArray results); static jint FindAll(JNIEnv* env, jobject obj, jstring find); static jobject GetDefaultBookmarkFolder(JNIEnv* env, jclass clazz); // Step 2: method stubs. static void Destroy(JNIEnv* env, jobject obj, jint nativeChromeBrowserProvider) { DCHECK(nativeChromeBrowserProvider) << "Destroy"; ChromeBrowserProvider* native = reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); return native->Destroy(env, obj); } static jlong AddBookmark(JNIEnv* env, jobject obj, jint nativeChromeBrowserProvider, jstring url, jstring title, jboolean isFolder, jlong parentId) { DCHECK(nativeChromeBrowserProvider) << "AddBookmark"; ChromeBrowserProvider* native = reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); return native->AddBookmark(env, obj, url, title, isFolder, parentId); } static jlong AddBookmarkFromAPI(JNIEnv* env, jobject obj, jint nativeChromeBrowserProvider, jstring url, jobject created, jobject isBookmark, jobject date, jbyteArray favicon, jstring title, jobject visits) { DCHECK(nativeChromeBrowserProvider) << "AddBookmarkFromAPI"; ChromeBrowserProvider* native = reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); return native->AddBookmarkFromAPI(env, obj, url, created, isBookmark, date, favicon, title, visits); } static jobject QueryBookmarkFromAPI(JNIEnv* env, jobject obj, jint nativeChromeBrowserProvider, jobjectArray projection, jstring selection, jobjectArray selectionArgs, jstring sortOrder) { DCHECK(nativeChromeBrowserProvider) << "QueryBookmarkFromAPI"; ChromeBrowserProvider* native = reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider); return native->QueryBookmarkFromAPI(env, obj, projection, selection, selectionArgs, sortOrder).Release(); } static void GotOrientation(JNIEnv* env, jobject obj, jint nativeDataFetcherImplAndroid, jdouble alpha, jdouble beta, jdouble gamma) { DCHECK(nativeDataFetcherImplAndroid) << "GotOrientation"; DataFetcherImplAndroid* native = reinterpret_cast<DataFetcherImplAndroid*>(nativeDataFetcherImplAndroid); return native->GotOrientation(env, obj, alpha, beta, gamma); } // Step 3: GetMethodIDs and RegisterNatives. static void GetMethodIDsImpl(JNIEnv* env) { g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( base::android::GetUnscopedClass(env, kTestJniClassPath))); } static bool RegisterNativesImpl(JNIEnv* env) { GetMethodIDsImpl(env); static const JNINativeMethod kMethodsTestJni[] = { { "nativeInit", "(" ")" "I", reinterpret_cast<void*>(Init) }, { "nativeDestroy", "(" "I" ")" "V", reinterpret_cast<void*>(Destroy) }, { "nativeAddBookmark", "(" "I" "Ljava/lang/String;" "Ljava/lang/String;" "Z" "J" ")" "J", reinterpret_cast<void*>(AddBookmark) }, { "nativeGetDomainAndRegistry", "(" "Ljava/lang/String;" ")" "Ljava/lang/String;", reinterpret_cast<void*>(GetDomainAndRegistry) }, { "nativeCreateHistoricalTabFromState", "(" "[B" "I" ")" "V", reinterpret_cast<void*>(CreateHistoricalTabFromState) }, { "nativeGetStateAsByteArray", "(" "Lorg/chromium/content/browser/ContentView;" ")" "[B", reinterpret_cast<void*>(GetStateAsByteArray) }, { "nativeGetAutofillProfileGUIDs", "(" ")" "[Ljava/lang/String;", reinterpret_cast<void*>(GetAutofillProfileGUIDs) }, { "nativeSetRecognitionResults", "(" "I" "[Ljava/lang/String;" ")" "V", reinterpret_cast<void*>(SetRecognitionResults) }, { "nativeAddBookmarkFromAPI", "(" "I" "Ljava/lang/String;" "Ljava/lang/Long;" "Ljava/lang/Boolean;" "Ljava/lang/Long;" "[B" "Ljava/lang/String;" "Ljava/lang/Integer;" ")" "J", reinterpret_cast<void*>(AddBookmarkFromAPI) }, { "nativeFindAll", "(" "Ljava/lang/String;" ")" "I", reinterpret_cast<void*>(FindAll) }, { "nativeGetDefaultBookmarkFolder", "(" ")" "Lcom/google/android/apps/chrome/ChromeBrowserProvider$BookmarkNode;", reinterpret_cast<void*>(GetDefaultBookmarkFolder) }, { "nativeQueryBookmarkFromAPI", "(" "I" "[Ljava/lang/String;" "Ljava/lang/String;" "[Ljava/lang/String;" "Ljava/lang/String;" ")" "Lcom/google/android/apps/chrome/database/SQLiteCursor;", reinterpret_cast<void*>(QueryBookmarkFromAPI) }, { "nativeGotOrientation", "(" "I" "D" "D" "D" ")" "V", reinterpret_cast<void*>(GotOrientation) }, }; const int kMethodsTestJniSize = arraysize(kMethodsTestJni); if (env->RegisterNatives(g_TestJni_clazz, kMethodsTestJni, kMethodsTestJniSize) < 0) { LOG(ERROR) << "RegisterNatives failed in " << __FILE__; return false; } return true; } #endif // org_chromium_TestJni_JNI """ self.assertTextEquals(golden_content, h.GetContent())
def convert_nonstatic_to_static(java_file_name, skip_caller=False, dry=False, verbose=True): if java_file_name is None: return if not os.path.isfile(java_file_name): if verbose: print('%s does not exist', java_file_name) return with open(java_file_name, 'r') as f: contents = f.read() no_comment_content = jni_generator.RemoveComments(contents) parsed_natives = jni_generator.ExtractNatives(no_comment_content, 'long') non_static_natives = [n for n in parsed_natives if not n.static] if not non_static_natives: if verbose: print('no natives found') return class_name = jni_generator.ExtractFullyQualifiedJavaClassName( java_file_name, no_comment_content).split('/')[-1] # For fixing call sites. replace_patterns = [] should_append_comma = [] should_prepend_comma = [] new_contents = contents # 1. Change non-static -> static. insertion_offset = 0 matches = [] for match in _NON_STATIC_NATIVES_REGEX.finditer(contents): if not 'static' in match.group('qualifiers'): matches.append(match) # Insert static as a keyword. qual_end = match.end('qualifiers') + insertion_offset insert_str = ' static ' new_contents = new_contents[:qual_end] + insert_str + new_contents[ qual_end:] insertion_offset += len(insert_str) if skip_caller: continue # Insert an object param. insert_str = '%s caller' % class_name # No params. if not match.group('params'): start = insertion_offset + match.start('params') append_comma = False prepend_comma = False # One or more params. else: # Has mNativePtr. if _NATIVE_PTR_REGEX.match(match.group('params')): # Only 1 param, append to end of params. if match.group('params').count(',') == 0: start = insertion_offset + match.end('params') append_comma = False prepend_comma = True # Multiple params, insert after first param. else: comma_pos = match.group('params').find(',') start = insertion_offset + match.start( 'params') + comma_pos + 1 append_comma = True prepend_comma = False else: # No mNativePtr, insert as first param. start = insertion_offset + match.start('params') append_comma = True prepend_comma = False if prepend_comma: insert_str = ', ' + insert_str if append_comma: insert_str = insert_str + ', ' new_contents = new_contents[:start] + insert_str + new_contents[ start:] # Match lines that don't have a native keyword. native_match = r'\((\s*?(([ms]Native\w+)|([ms]\w+Android(Ptr)?)),?)?)' replace_patterns.append(r'(^\s*' + match.group('name') + native_match) replace_patterns.append(r'(return ' + match.group('name') + native_match) replace_patterns.append(r'([\:\)\(\+\*\?\&\|,\.\-\=\!\/][ \t]*' + match.group('name') + native_match) should_append_comma.extend([append_comma] * 3) should_prepend_comma.extend([prepend_comma] * 3) insertion_offset += len(insert_str) assert len(matches) == len(non_static_natives), ( 'Regex missed a native ' 'method that was found by ' 'the jni_generator.') # 2. Add a this param to all calls. for i, r in enumerate(replace_patterns): prepend_comma = ', ' if should_prepend_comma[i] else '' append_comma = ', ' if should_append_comma[i] else '' repl_str = '\g<1>' + prepend_comma + ' %s.this' + append_comma new_contents = re.sub(r, repl_str % class_name, new_contents, flags=re.MULTILINE) if dry: print(new_contents) else: with open(java_file_name, 'w') as f: f.write(new_contents)